diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-07-26 19:03:47 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-07-26 19:04:23 +0000 |
| commit | 7fa27ce4a07f19b07799a767fc29416f3b625afb (patch) | |
| tree | 27825c83636c4de341eb09a74f49f5d38a15d165 /libcxx/include | |
| parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) | |
Diffstat (limited to 'libcxx/include')
874 files changed, 46243 insertions, 21972 deletions
diff --git a/libcxx/include/__algorithm/adjacent_find.h b/libcxx/include/__algorithm/adjacent_find.h index 30df4a976f3d..7819e2cf49b9 100644 --- a/libcxx/include/__algorithm/adjacent_find.h +++ b/libcxx/include/__algorithm/adjacent_find.h @@ -20,6 +20,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _Iter, class _Sent, class _BinaryPredicate> @@ -50,4 +53,6 @@ adjacent_find(_ForwardIterator __first, _ForwardIterator __last) { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_ADJACENT_FIND_H diff --git a/libcxx/include/__algorithm/all_of.h b/libcxx/include/__algorithm/all_of.h index 284c34ffcda9..237f8495c645 100644 --- a/libcxx/include/__algorithm/all_of.h +++ b/libcxx/include/__algorithm/all_of.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _InputIterator, class _Predicate> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) { for (; __first != __last; ++__first) if (!__pred(*__first)) diff --git a/libcxx/include/__algorithm/binary_search.h b/libcxx/include/__algorithm/binary_search.h index 8f958c2c1ad8..0c8f5545e066 100644 --- a/libcxx/include/__algorithm/binary_search.h +++ b/libcxx/include/__algorithm/binary_search.h @@ -37,8 +37,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - return std::binary_search(__first, __last, __value, - __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); + return std::binary_search(__first, __last, __value, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/clamp.h b/libcxx/include/__algorithm/clamp.h index 30ddbdce64a9..31deb4fd94aa 100644 --- a/libcxx/include/__algorithm/clamp.h +++ b/libcxx/include/__algorithm/clamp.h @@ -19,14 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template<class _Tp, class _Compare> _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY constexpr const _Tp& clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) { - _LIBCPP_ASSERT(!__comp(__hi, __lo), "Bad bounds passed to std::clamp"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__comp(__hi, __lo), "Bad bounds passed to std::clamp"); return __comp(__v, __lo) ? __lo : __comp(__hi, __v) ? __hi : __v; } @@ -37,7 +37,7 @@ _LIBCPP_INLINE_VISIBILITY constexpr const _Tp& clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) { - return _VSTD::clamp(__v, __lo, __hi, __less<_Tp>()); + return _VSTD::clamp(__v, __lo, __hi, __less<>()); } #endif diff --git a/libcxx/include/__algorithm/comp.h b/libcxx/include/__algorithm/comp.h index af8eb7b5d76b..9474536615ff 100644 --- a/libcxx/include/__algorithm/comp.h +++ b/libcxx/include/__algorithm/comp.h @@ -10,6 +10,8 @@ #define _LIBCPP___ALGORITHM_COMP_H #include <__config> +#include <__type_traits/integral_constant.h> +#include <__type_traits/predicate_traits.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,41 +26,20 @@ struct __equal_to { } }; -template <class _T1, class _T2 = _T1> -struct __less -{ - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} +template <class _Lhs, class _Rhs> +struct __is_trivial_equality_predicate<__equal_to, _Lhs, _Rhs> : true_type {}; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T1& __x, const _T2& __y) const {return __x < __y;} +// The definition is required because __less is part of the ABI, but it's empty +// because all comparisons should be transparent. +template <class _T1 = void, class _T2 = _T1> +struct __less {}; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T2& __x, const _T1& __y) const {return __x < __y;} - - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T2& __x, const _T2& __y) const {return __x < __y;} -}; - -template <class _T1> -struct __less<_T1, _T1> -{ - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} -}; - -template <class _T1> -struct __less<const _T1, _T1> -{ - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} -}; - -template <class _T1> -struct __less<_T1, const _T1> -{ - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;} +template <> +struct __less<void, void> { + template <class _Tp, class _Up> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _Tp& __lhs, const _Up& __rhs) const { + return __lhs < __rhs; + } }; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/comp_ref_type.h b/libcxx/include/__algorithm/comp_ref_type.h index f2338e144688..d16bd0f53100 100644 --- a/libcxx/include/__algorithm/comp_ref_type.h +++ b/libcxx/include/__algorithm/comp_ref_type.h @@ -9,8 +9,8 @@ #ifndef _LIBCPP___ALGORITHM_COMP_REF_TYPE_H #define _LIBCPP___ALGORITHM_COMP_REF_TYPE_H +#include <__assert> #include <__config> -#include <__debug> #include <__utility/declval.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -23,11 +23,10 @@ template <class _Compare> struct __debug_less { _Compare &__comp_; - _LIBCPP_CONSTEXPR_SINCE_CXX14 - __debug_less(_Compare& __c) : __comp_(__c) {} + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI __debug_less(_Compare& __c) : __comp_(__c) {} template <class _Tp, class _Up> - _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Up& __y) { bool __r = __comp_(__x, __y); @@ -37,7 +36,7 @@ struct __debug_less } template <class _Tp, class _Up> - _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI bool operator()(_Tp& __x, _Up& __y) { bool __r = __comp_(__x, __y); @@ -52,7 +51,7 @@ struct __debug_less decltype((void)std::declval<_Compare&>()( std::declval<_LHS &>(), std::declval<_RHS &>())) __do_compare_assert(int, _LHS & __l, _RHS & __r) { - _LIBCPP_DEBUG_ASSERT(!__comp_(__l, __r), + _LIBCPP_ASSERT_UNCATEGORIZED(!__comp_(__l, __r), "Comparator does not induce a strict weak ordering"); (void)__l; (void)__r; @@ -66,7 +65,7 @@ struct __debug_less // Pass the comparator by lvalue reference. Or in debug mode, using a // debugging wrapper that stores a reference. -#ifdef _LIBCPP_ENABLE_DEBUG_MODE +#if _LIBCPP_ENABLE_DEBUG_MODE template <class _Comp> using __comp_ref_type = __debug_less<_Comp>; #else diff --git a/libcxx/include/__algorithm/copy.h b/libcxx/include/__algorithm/copy.h index 193a6df31656..dfe9898c6480 100644 --- a/libcxx/include/__algorithm/copy.h +++ b/libcxx/include/__algorithm/copy.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_COPY_H #include <__algorithm/copy_move_common.h> +#include <__algorithm/for_each_segment.h> #include <__algorithm/iterator_operations.h> #include <__algorithm/min.h> #include <__config> @@ -44,36 +45,34 @@ struct __copy_loop { return std::make_pair(std::move(__first), std::move(__result)); } - template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> - operator()(_InIter __first, _InIter __last, _OutIter __result) const { + template <class _InIter, class _OutIter> + struct _CopySegment { using _Traits = __segmented_iterator_traits<_InIter>; - auto __sfirst = _Traits::__segment(__first); - auto __slast = _Traits::__segment(__last); - if (__sfirst == __slast) { - auto __iters = std::__copy<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); - return std::make_pair(__last, std::move(__iters.second)); - } - __result = std::__copy<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__sfirst), std::move(__result)).second; - ++__sfirst; - while (__sfirst != __slast) { - __result = - std::__copy<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), std::move(__result)).second; - ++__sfirst; + _OutIter& __result_; + + _LIBCPP_HIDE_FROM_ABI _CopySegment(_OutIter& __result) : __result_(__result) {} + + _LIBCPP_HIDE_FROM_ABI void + operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) { + __result_ = std::__copy<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second; } - __result = - std::__copy<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__local(__last), std::move(__result)).second; + }; + + template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) const { + std::__for_each_segment(__first, __last, _CopySegment<_InIter, _OutIter>(__result)); return std::make_pair(__last, std::move(__result)); } template <class _InIter, class _OutIter, - __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value && + __enable_if_t<__has_random_access_iterator_category<_InIter>::value && !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> - operator()(_InIter __first, _InIter __last, _OutIter __result) { + operator()(_InIter __first, _InIter __last, _OutIter __result) const { using _Traits = __segmented_iterator_traits<_OutIter>; using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; @@ -98,8 +97,7 @@ struct __copy_loop { struct __copy_trivial { // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. - template <class _In, class _Out, - __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0> + template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> operator()(_In* __first, _In* __last, _Out* __result) const { return std::__copy_trivial_impl(__first, __last, __result); diff --git a/libcxx/include/__algorithm/copy_backward.h b/libcxx/include/__algorithm/copy_backward.h index bb2a4328781c..d85d297b3226 100644 --- a/libcxx/include/__algorithm/copy_backward.h +++ b/libcxx/include/__algorithm/copy_backward.h @@ -76,11 +76,11 @@ struct __copy_backward_loop { template <class _InIter, class _OutIter, - __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value && + __enable_if_t<__has_random_access_iterator_category<_InIter>::value && !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> - operator()(_InIter __first, _InIter __last, _OutIter __result) { + operator()(_InIter __first, _InIter __last, _OutIter __result) const { using _Traits = __segmented_iterator_traits<_OutIter>; auto __orig_last = __last; auto __segment_iterator = _Traits::__segment(__result); diff --git a/libcxx/include/__algorithm/copy_move_common.h b/libcxx/include/__algorithm/copy_move_common.h index b88c14911b9b..c06892e9e3c7 100644 --- a/libcxx/include/__algorithm/copy_move_common.h +++ b/libcxx/include/__algorithm/copy_move_common.h @@ -15,6 +15,7 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> +#include <__string/constexpr_c_functions.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_always_bitcastable.h> #include <__type_traits/is_constant_evaluated.h> @@ -61,7 +62,8 @@ template <class _In, class _Out> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> __copy_trivial_impl(_In* __first, _In* __last, _Out* __result) { const size_t __n = static_cast<size_t>(__last - __first); - ::__builtin_memmove(__result, __first, __n * sizeof(_Out)); + + std::__constexpr_memmove(__result, __first, __element_count(__n)); return std::make_pair(__last, __result + __n); } @@ -72,7 +74,7 @@ __copy_backward_trivial_impl(_In* __first, _In* __last, _Out* __result) { const size_t __n = static_cast<size_t>(__last - __first); __result -= __n; - ::__builtin_memmove(__result, __first, __n * sizeof(_Out)); + std::__constexpr_memmove(__result, __first, __element_count(__n)); return std::make_pair(__last, __result); } @@ -119,16 +121,6 @@ __unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) { return _Algorithm()(std::move(__first), std::move(__last), std::move(__out_first)); } -template <class _IterOps, class _InValue, class _OutIter, class = void> -struct __can_copy_without_conversion : false_type {}; - -template <class _IterOps, class _InValue, class _OutIter> -struct __can_copy_without_conversion< - _IterOps, - _InValue, - _OutIter, - __enable_if_t<is_same<_InValue, typename _IterOps::template __value_type<_OutIter> >::value> > : true_type {}; - template <class _AlgPolicy, class _NaiveAlgorithm, class _OptimizedAlgorithm, @@ -137,23 +129,6 @@ template <class _AlgPolicy, class _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> __dispatch_copy_or_move(_InIter __first, _Sent __last, _OutIter __out_first) { -#ifdef _LIBCPP_COMPILER_GCC - // GCC doesn't support `__builtin_memmove` during constant evaluation. - if (__libcpp_is_constant_evaluated()) { - return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first)); - } -#else - // In Clang, `__builtin_memmove` only supports fully trivially copyable types (just having trivial copy assignment is - // insufficient). Also, conversions are not supported. - if (__libcpp_is_constant_evaluated()) { - using _InValue = typename _IterOps<_AlgPolicy>::template __value_type<_InIter>; - if (!is_trivially_copyable<_InValue>::value || - !__can_copy_without_conversion<_IterOps<_AlgPolicy>, _InValue, _OutIter>::value) { - return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first)); - } - } -#endif // _LIBCPP_COMPILER_GCC - using _Algorithm = __overload<_NaiveAlgorithm, _OptimizedAlgorithm>; return std::__unwrap_and_dispatch<_Algorithm>(std::move(__first), std::move(__last), std::move(__out_first)); } diff --git a/libcxx/include/__algorithm/copy_n.h b/libcxx/include/__algorithm/copy_n.h index b08bbdfb9b7e..f3701662aac3 100644 --- a/libcxx/include/__algorithm/copy_n.h +++ b/libcxx/include/__algorithm/copy_n.h @@ -12,8 +12,8 @@ #include <__algorithm/copy.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> #include <__utility/convert_to_integral.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -25,8 +25,8 @@ template<class _InputIterator, class _Size, class _OutputIterator> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < - __is_cpp17_input_iterator<_InputIterator>::value && - !__is_cpp17_random_access_iterator<_InputIterator>::value, + __has_input_iterator_category<_InputIterator>::value && + !__has_random_access_iterator_category<_InputIterator>::value, _OutputIterator >::type copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) @@ -51,7 +51,7 @@ template<class _InputIterator, class _Size, class _OutputIterator> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < - __is_cpp17_random_access_iterator<_InputIterator>::value, + __has_random_access_iterator_category<_InputIterator>::value, _OutputIterator >::type copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h index cf37f46aaf69..b69aeff92bb9 100644 --- a/libcxx/include/__algorithm/equal.h +++ b/libcxx/include/__algorithm/equal.h @@ -11,9 +11,20 @@ #define _LIBCPP___ALGORITHM_EQUAL_H #include <__algorithm/comp.h> +#include <__algorithm/unwrap_iter.h> #include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> +#include <__string/constexpr_c_functions.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_equality_comparable.h> +#include <__type_traits/is_volatile.h> +#include <__type_traits/predicate_traits.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,23 +33,42 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool -equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl( + _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) { for (; __first1 != __last1; ++__first1, (void)++__first2) if (!__pred(*__first1, *__first2)) return false; return true; } +template < + class _Tp, + class _Up, + class _BinaryPredicate, + __enable_if_t<__is_trivial_equality_predicate<_BinaryPredicate, _Tp, _Up>::value && !is_volatile<_Tp>::value && + !is_volatile<_Up>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, + int> = 0> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +__equal_iter_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _BinaryPredicate&) { + return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); +} + +template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { + return std::__equal_iter_impl( + std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred); +} + template <class _InputIterator1, class _InputIterator2> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) { return std::equal(__first1, __last1, __first2, __equal_to()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _BinaryPredicate, class _InputIterator1, class _InputIterator2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _BinaryPredicate __pred, input_iterator_tag, input_iterator_tag) { for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) @@ -47,19 +77,52 @@ __equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fir return __first1 == __last1 && __first2 == __last2; } +template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl( + _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __comp, _Proj1& __proj1, _Proj2& __proj2) { + while (__first1 != __last1 && __first2 != __last2) { + if (!std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) + return false; + ++__first1; + ++__first2; + } + return __first1 == __last1 && __first2 == __last2; +} + +template <class _Tp, + class _Up, + class _Pred, + class _Proj1, + class _Proj2, + __enable_if_t<__is_trivial_equality_predicate<_Pred, _Tp, _Up>::value && __is_identity<_Proj1>::value && + __is_identity<_Proj2>::value && !is_volatile<_Tp>::value && !is_volatile<_Up>::value && + __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, + int> = 0> +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl( + _Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) { + return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); +} + template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2, _RandomAccessIterator2 __last2, _BinaryPredicate __pred, random_access_iterator_tag, random_access_iterator_tag) { if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) return false; - return _VSTD::equal<_RandomAccessIterator1, _RandomAccessIterator2, - _BinaryPredicate&>(__first1, __last1, __first2, __pred); + __identity __proj; + return std::__equal_impl( + std::__unwrap_iter(__first1), + std::__unwrap_iter(__last1), + std::__unwrap_iter(__first2), + std::__unwrap_iter(__last2), + __pred, + __proj, + __proj); } template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _BinaryPredicate __pred) { return _VSTD::__equal<_BinaryPredicate&>( @@ -68,7 +131,7 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first } template <class _InputIterator1, class _InputIterator2> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { return std::__equal( __first1, diff --git a/libcxx/include/__algorithm/equal_range.h b/libcxx/include/__algorithm/equal_range.h index 2075b03412e3..dc1268a6ff11 100644 --- a/libcxx/include/__algorithm/equal_range.h +++ b/libcxx/include/__algorithm/equal_range.h @@ -50,7 +50,7 @@ __equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp } else { _Iter __mp1 = __mid; return pair<_Iter, _Iter>( - std::__lower_bound_impl<_AlgPolicy>(__first, __mid, __value, __comp, __proj), + std::__lower_bound<_AlgPolicy>(__first, __mid, __value, __comp, __proj), std::__upper_bound<_AlgPolicy>(++__mp1, __end, __value, __comp, __proj)); } } @@ -75,11 +75,7 @@ equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu template <class _ForwardIterator, class _Tp> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator> equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - return std::equal_range( - std::move(__first), - std::move(__last), - __value, - __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); + return std::equal_range(std::move(__first), std::move(__last), __value, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/fill.h b/libcxx/include/__algorithm/fill.h index 76cf4a1477a6..0753c427ae4e 100644 --- a/libcxx/include/__algorithm/fill.h +++ b/libcxx/include/__algorithm/fill.h @@ -12,7 +12,6 @@ #include <__algorithm/fill_n.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__algorithm/fill_n.h b/libcxx/include/__algorithm/fill_n.h index fe58c8d64178..e7863ac7ec7e 100644 --- a/libcxx/include/__algorithm/fill_n.h +++ b/libcxx/include/__algorithm/fill_n.h @@ -12,7 +12,6 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/convert_to_integral.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__algorithm/find.h b/libcxx/include/__algorithm/find.h index e51dc9bb160a..e0de5032878e 100644 --- a/libcxx/include/__algorithm/find.h +++ b/libcxx/include/__algorithm/find.h @@ -10,7 +10,16 @@ #ifndef _LIBCPP___ALGORITHM_FIND_H #define _LIBCPP___ALGORITHM_FIND_H +#include <__algorithm/unwrap_iter.h> #include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__string/constexpr_c_functions.h> +#include <__type_traits/is_same.h> + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# include <cwchar> +#endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -18,15 +27,51 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _InputIterator, class _Tp> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator -find(_InputIterator __first, _InputIterator __last, const _Tp& __value) { +template <class _Iter, class _Sent, class _Tp, class _Proj> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter +__find_impl(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) { for (; __first != __last; ++__first) - if (*__first == __value) + if (std::__invoke(__proj, *__first) == __value) break; return __first; } +template <class _Tp, + class _Up, + class _Proj, + __enable_if_t<__is_identity<_Proj>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value && + sizeof(_Tp) == 1, + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* +__find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) { + if (auto __ret = std::__constexpr_memchr(__first, __value, __last - __first)) + return __ret; + return __last; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <class _Tp, + class _Up, + class _Proj, + __enable_if_t<__is_identity<_Proj>::value && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value && + sizeof(_Tp) == sizeof(wchar_t) && _LIBCPP_ALIGNOF(_Tp) >= _LIBCPP_ALIGNOF(wchar_t), + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* +__find_impl(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&) { + if (auto __ret = std::__constexpr_wmemchr(__first, __value, __last - __first)) + return __ret; + return __last; +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +template <class _InputIterator, class _Tp> +_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator +find(_InputIterator __first, _InputIterator __last, const _Tp& __value) { + __identity __proj; + return std::__rewrap_iter( + __first, std::__find_impl(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __value, __proj)); +} + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___ALGORITHM_FIND_H diff --git a/libcxx/include/__algorithm/find_end.h b/libcxx/include/__algorithm/find_end.h index e2fee6b3c459..edb9891c66f7 100644 --- a/libcxx/include/__algorithm/find_end.h +++ b/libcxx/include/__algorithm/find_end.h @@ -15,12 +15,12 @@ #include <__algorithm/search.h> #include <__config> #include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/advance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> #include <__iterator/reverse_iterator.h> #include <__utility/pair.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__algorithm/for_each_n.h b/libcxx/include/__algorithm/for_each_n.h index 38d204a11819..5bd7318224d1 100644 --- a/libcxx/include/__algorithm/for_each_n.h +++ b/libcxx/include/__algorithm/for_each_n.h @@ -12,7 +12,6 @@ #include <__config> #include <__utility/convert_to_integral.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _InputIterator, class _Size, class _Function> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator for_each_n(_InputIterator __first, diff --git a/libcxx/include/__algorithm/for_each_segment.h b/libcxx/include/__algorithm/for_each_segment.h new file mode 100644 index 000000000000..93aa8259b2f7 --- /dev/null +++ b/libcxx/include/__algorithm/for_each_segment.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_FOR_EACH_SEGMENT_H +#define _LIBCPP___ALGORITHM_FOR_EACH_SEGMENT_H + +#include <__config> +#include <__iterator/segmented_iterator.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __for_each_segment is a utility function for optimizing iterating over segmented iterators linearly. +// __first and __last are expected to be a segmented range. __func is expected to take a range of local iterators. +// Anything that is returned from __func is ignored. + +template <class _SegmentedIterator, class _Functor> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void +__for_each_segment(_SegmentedIterator __first, _SegmentedIterator __last, _Functor __func) { + using _Traits = __segmented_iterator_traits<_SegmentedIterator>; + + auto __sfirst = _Traits::__segment(__first); + auto __slast = _Traits::__segment(__last); + + // We are in a single segment, so we might not be at the beginning or end + if (__sfirst == __slast) { + __func(_Traits::__local(__first), _Traits::__local(__last)); + return; + } + + // We have more than one segment. Iterate over the first segment, since we might not start at the beginning + __func(_Traits::__local(__first), _Traits::__end(__sfirst)); + ++__sfirst; + // iterate over the segments which are guaranteed to be completely in the range + while (__sfirst != __slast) { + __func(_Traits::__begin(__sfirst), _Traits::__end(__sfirst)); + ++__sfirst; + } + // iterate over the last segment + __func(_Traits::__begin(__sfirst), _Traits::__local(__last)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_FOR_EACH_SEGMENT_H diff --git a/libcxx/include/__algorithm/generate_n.h b/libcxx/include/__algorithm/generate_n.h index 45259989bf0e..ff5c82d3e422 100644 --- a/libcxx/include/__algorithm/generate_n.h +++ b/libcxx/include/__algorithm/generate_n.h @@ -11,7 +11,6 @@ #include <__config> #include <__utility/convert_to_integral.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__algorithm/half_positive.h b/libcxx/include/__algorithm/half_positive.h index 74aede2b5668..5a0f4baf6aaa 100644 --- a/libcxx/include/__algorithm/half_positive.h +++ b/libcxx/include/__algorithm/half_positive.h @@ -10,7 +10,9 @@ #define _LIBCPP___ALGORITHM_HALF_POSITIVE_H #include <__config> -#include <type_traits> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/make_unsigned.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__algorithm/in_found_result.h b/libcxx/include/__algorithm/in_found_result.h index 3134d6e0df2c..d9ca287f017b 100644 --- a/libcxx/include/__algorithm/in_found_result.h +++ b/libcxx/include/__algorithm/in_found_result.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -44,6 +44,6 @@ struct in_found_result { _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_IN_FOUND_RESULT_H diff --git a/libcxx/include/__algorithm/in_fun_result.h b/libcxx/include/__algorithm/in_fun_result.h index 3cbb9e12d3b3..33374eddc30d 100644 --- a/libcxx/include/__algorithm/in_fun_result.h +++ b/libcxx/include/__algorithm/in_fun_result.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template <class _InIter1, class _Func1> @@ -42,7 +42,7 @@ struct in_fun_result { }; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/in_in_out_result.h b/libcxx/include/__algorithm/in_in_out_result.h index 3e747be44d66..6b50e0e24564 100644 --- a/libcxx/include/__algorithm/in_in_out_result.h +++ b/libcxx/include/__algorithm/in_in_out_result.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -49,7 +49,7 @@ struct in_in_out_result { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/in_in_result.h b/libcxx/include/__algorithm/in_in_result.h index 2098c188cc9f..1eceb9de0233 100644 --- a/libcxx/include/__algorithm/in_in_result.h +++ b/libcxx/include/__algorithm/in_in_result.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -46,7 +46,7 @@ struct in_in_result { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/in_out_out_result.h b/libcxx/include/__algorithm/in_out_out_result.h index 4046eee57df1..2f7a09b5c301 100644 --- a/libcxx/include/__algorithm/in_out_out_result.h +++ b/libcxx/include/__algorithm/in_out_out_result.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template <class _InIter1, class _OutIter1, class _OutIter2> @@ -47,7 +47,7 @@ struct in_out_out_result { }; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/in_out_result.h b/libcxx/include/__algorithm/in_out_result.h index 7f5a0271b4c1..e4741cb71f66 100644 --- a/libcxx/include/__algorithm/in_out_result.h +++ b/libcxx/include/__algorithm/in_out_result.h @@ -18,9 +18,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -46,8 +49,10 @@ struct in_out_result { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_IN_OUT_RESULT_H diff --git a/libcxx/include/__algorithm/includes.h b/libcxx/include/__algorithm/includes.h index cc39f275bf44..88253e2653d2 100644 --- a/libcxx/include/__algorithm/includes.h +++ b/libcxx/include/__algorithm/includes.h @@ -61,13 +61,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 template <class _InputIterator1, class _InputIterator2> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { - return std::includes( - std::move(__first1), - std::move(__last1), - std::move(__first2), - std::move(__last2), - __less<typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>()); + return std::includes(std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/inplace_merge.h b/libcxx/include/__algorithm/inplace_merge.h index 5bbefc94bdf2..44a9425559ef 100644 --- a/libcxx/include/__algorithm/inplace_merge.h +++ b/libcxx/include/__algorithm/inplace_merge.h @@ -246,8 +246,7 @@ inline _LIBCPP_HIDE_FROM_ABI void inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) { - std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), - __less<typename iterator_traits<_BidirectionalIterator>::value_type>()); + std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/is_heap.h b/libcxx/include/__algorithm/is_heap.h index 2dcb4a28e8d7..93d84d33806e 100644 --- a/libcxx/include/__algorithm/is_heap.h +++ b/libcxx/include/__algorithm/is_heap.h @@ -36,7 +36,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { - return _VSTD::is_heap(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); + return _VSTD::is_heap(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/is_heap_until.h b/libcxx/include/__algorithm/is_heap_until.h index 6ed4cb29c423..d7131114bd60 100644 --- a/libcxx/include/__algorithm/is_heap_until.h +++ b/libcxx/include/__algorithm/is_heap_until.h @@ -58,7 +58,7 @@ template<class _RandomAccessIterator> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) { - return _VSTD::__is_heap_until(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); + return _VSTD::__is_heap_until(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h index 005445652e9d..105a0732283c 100644 --- a/libcxx/include/__algorithm/is_permutation.h +++ b/libcxx/include/__algorithm/is_permutation.h @@ -19,19 +19,22 @@ #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> +#include <__type_traits/is_callable.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class = void> struct _ConstTimeDistance : false_type {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2> struct _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2, __enable_if_t< @@ -47,7 +50,7 @@ struct _ConstTimeDistance<_Iter1, _Iter1, _Iter2, _Iter2, __enable_if_t< is_same<typename iterator_traits<_Iter2>::iterator_category, random_access_iterator_tag>::value > > : true_type {}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 // Internal functions @@ -202,7 +205,7 @@ is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIt return std::is_permutation(__first1, __last1, __first2, __equal_to()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 // 2+2 iterators template <class _ForwardIterator1, class _ForwardIterator2> @@ -231,8 +234,10 @@ is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIt __pred, __identity(), __identity()); } -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_IS_PERMUTATION_H diff --git a/libcxx/include/__algorithm/is_sorted.h b/libcxx/include/__algorithm/is_sorted.h index bf44f45764d5..a321c2c12dc4 100644 --- a/libcxx/include/__algorithm/is_sorted.h +++ b/libcxx/include/__algorithm/is_sorted.h @@ -36,7 +36,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_sorted(_ForwardIterator __first, _ForwardIterator __last) { - return _VSTD::is_sorted(__first, __last, __less<typename iterator_traits<_ForwardIterator>::value_type>()); + return _VSTD::is_sorted(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/is_sorted_until.h b/libcxx/include/__algorithm/is_sorted_until.h index b6683000a069..890b93631c46 100644 --- a/libcxx/include/__algorithm/is_sorted_until.h +++ b/libcxx/include/__algorithm/is_sorted_until.h @@ -48,7 +48,7 @@ template<class _ForwardIterator> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) { - return _VSTD::is_sorted_until(__first, __last, __less<typename iterator_traits<_ForwardIterator>::value_type>()); + return _VSTD::is_sorted_until(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/iterator_operations.h b/libcxx/include/__algorithm/iterator_operations.h index bd3e6f1d38fd..002978014cc7 100644 --- a/libcxx/include/__algorithm/iterator_operations.h +++ b/libcxx/include/__algorithm/iterator_operations.h @@ -33,11 +33,14 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _AlgPolicy> struct _IterOps; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct _RangeAlgPolicy {}; template <> @@ -172,4 +175,6 @@ struct _IterOps<_ClassicAlgPolicy> { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H diff --git a/libcxx/include/__algorithm/lexicographical_compare.h b/libcxx/include/__algorithm/lexicographical_compare.h index 0a13c5dd31c8..62b72edc80f7 100644 --- a/libcxx/include/__algorithm/lexicographical_compare.h +++ b/libcxx/include/__algorithm/lexicographical_compare.h @@ -52,9 +52,7 @@ bool lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { - return _VSTD::lexicographical_compare(__first1, __last1, __first2, __last2, - __less<typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>()); + return _VSTD::lexicographical_compare(__first1, __last1, __first2, __last2, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/lexicographical_compare_three_way.h b/libcxx/include/__algorithm/lexicographical_compare_three_way.h new file mode 100644 index 000000000000..32de97d07a13 --- /dev/null +++ b/libcxx/include/__algorithm/lexicographical_compare_three_way.h @@ -0,0 +1,125 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_THREE_WAY_H +#define _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_THREE_WAY_H + +#include <__algorithm/min.h> +#include <__algorithm/three_way_comp_ref_type.h> +#include <__compare/compare_three_way.h> +#include <__compare/ordering.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/common_type.h> +#include <__type_traits/is_copy_constructible.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +// Fast path for random access iterators which computes the number of loop iterations up-front and +// then skips the iterator comparisons inside the loop. +template <class _InputIterator1, class _InputIterator2, class _Cmp> +_LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_fast_path( + _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp& __comp) + -> decltype(__comp(*__first1, *__first2)) { + static_assert( + signed_integral<__iter_diff_t<_InputIterator1>>, "Using a non-integral difference_type is undefined behavior."); + static_assert( + signed_integral<__iter_diff_t<_InputIterator2>>, "Using a non-integral difference_type is undefined behavior."); + + using _Len1 = __iter_diff_t<_InputIterator1>; + using _Len2 = __iter_diff_t<_InputIterator2>; + using _Common = common_type_t<_Len1, _Len2>; + + _Len1 __len1 = __last1 - __first1; + _Len2 __len2 = __last2 - __first2; + _Common __min_len = std::min<_Common>(__len1, __len2); + + for (_Common __i = 0; __i < __min_len; ++__i) { + auto __c = __comp(*__first1, *__first2); + if (__c != 0) { + return __c; + } + ++__first1; + ++__first2; + } + + return __len1 <=> __len2; +} + +// Unoptimized implementation which compares the iterators against the end in every loop iteration +template <class _InputIterator1, class _InputIterator2, class _Cmp> +_LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_slow_path( + _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp& __comp) + -> decltype(__comp(*__first1, *__first2)) { + while (true) { + bool __exhausted1 = __first1 == __last1; + bool __exhausted2 = __first2 == __last2; + + if (__exhausted1 || __exhausted2) { + if (!__exhausted1) + return strong_ordering::greater; + if (!__exhausted2) + return strong_ordering::less; + return strong_ordering::equal; + } + + auto __c = __comp(*__first1, *__first2); + if (__c != 0) { + return __c; + } + + ++__first1; + ++__first2; + } +} + +template <class _InputIterator1, class _InputIterator2, class _Cmp> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( + _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _Cmp __comp) + -> decltype(__comp(*__first1, *__first2)) { + static_assert(__comparison_category<decltype(__comp(*__first1, *__first2))>, + "The comparator passed to lexicographical_compare_three_way must return a comparison category type."); + static_assert(std::is_copy_constructible_v<_InputIterator1>, "Iterators must be copy constructible."); + static_assert(std::is_copy_constructible_v<_InputIterator2>, "Iterators must be copy constructible."); + __three_way_comp_ref_type<_Cmp> __wrapped_comp_ref(__comp); + if constexpr (__has_random_access_iterator_category<_InputIterator1>::value && + __has_random_access_iterator_category<_InputIterator2>::value) { + return std::__lexicographical_compare_three_way_fast_path( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __wrapped_comp_ref); + } else { + // Unoptimized implementation which compares the iterators against the end in every loop iteration + return std::__lexicographical_compare_three_way_slow_path( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __wrapped_comp_ref); + } +} + +template <class _InputIterator1, class _InputIterator2> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto lexicographical_compare_three_way( + _InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { + return std::lexicographical_compare_three_way( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::compare_three_way()); +} + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_THREE_WAY_H diff --git a/libcxx/include/__algorithm/lower_bound.h b/libcxx/include/__algorithm/lower_bound.h index 2648982ea506..91c3bdaafd0c 100644 --- a/libcxx/include/__algorithm/lower_bound.h +++ b/libcxx/include/__algorithm/lower_bound.h @@ -20,7 +20,6 @@ #include <__iterator/iterator_traits.h> #include <__type_traits/is_callable.h> #include <__type_traits/remove_reference.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -30,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _AlgPolicy, class _Iter, class _Sent, class _Type, class _Proj, class _Comp> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 -_Iter __lower_bound_impl(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) { +_Iter __lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) { auto __len = _IterOps<_AlgPolicy>::distance(__first, __last); while (__len != 0) { @@ -53,14 +52,13 @@ _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value, "The comparator has to be callable"); auto __proj = std::__identity(); - return std::__lower_bound_impl<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj); + return std::__lower_bound<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj); } template <class _ForwardIterator, class _Tp> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - return std::lower_bound(__first, __last, __value, - __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>()); + return std::lower_bound(__first, __last, __value, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/make_heap.h b/libcxx/include/__algorithm/make_heap.h index d66cfe2e5fc9..eaf9259c0b31 100644 --- a/libcxx/include/__algorithm/make_heap.h +++ b/libcxx/include/__algorithm/make_heap.h @@ -21,6 +21,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> @@ -47,10 +50,11 @@ void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com template <class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::make_heap(std::move(__first), std::move(__last), - __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); + std::make_heap(std::move(__first), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_MAKE_HEAP_H diff --git a/libcxx/include/__algorithm/make_projected.h b/libcxx/include/__algorithm/make_projected.h index 87d4d59042c6..ec854763a5a2 100644 --- a/libcxx/include/__algorithm/make_projected.h +++ b/libcxx/include/__algorithm/make_projected.h @@ -32,13 +32,14 @@ struct _ProjectedPred { _Pred& __pred; // Can be a unary or a binary predicate. _Proj& __proj; - _LIBCPP_CONSTEXPR _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg) : __pred(__pred_arg), __proj(__proj_arg) {} + _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg) + : __pred(__pred_arg), __proj(__proj_arg) {} template <class _Tp> typename __invoke_of<_Pred&, decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>())) >::type - _LIBCPP_CONSTEXPR operator()(_Tp&& __v) const { + _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI operator()(_Tp&& __v) const { return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v))); } @@ -47,7 +48,7 @@ struct _ProjectedPred { decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())), decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>())) >::type - _LIBCPP_CONSTEXPR operator()(_T1&& __lhs, _T2&& __rhs) const { + _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI operator()(_T1&& __lhs, _T2&& __rhs) const { return std::__invoke(__pred, std::__invoke(__proj, std::forward<_T1>(__lhs)), std::__invoke(__proj, std::forward<_T2>(__rhs))); @@ -55,25 +56,12 @@ struct _ProjectedPred { }; -template <class _Pred, class _Proj, class = void> -struct __can_use_pristine_comp : false_type {}; - -template <class _Pred, class _Proj> -struct __can_use_pristine_comp<_Pred, _Proj, __enable_if_t< - !is_member_pointer<typename decay<_Pred>::type>::value && ( -#if _LIBCPP_STD_VER > 17 - is_same<typename decay<_Proj>::type, identity>::value || -#endif - is_same<typename decay<_Proj>::type, __identity>::value - ) -> > : true_type {}; - -template <class _Pred, class _Proj> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static -__enable_if_t< - !__can_use_pristine_comp<_Pred, _Proj>::value, - _ProjectedPred<_Pred, _Proj> -> +template <class _Pred, + class _Proj, + __enable_if_t<!(!is_member_pointer<__decay_t<_Pred> >::value && + __is_identity<__decay_t<_Proj> >::value), + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ProjectedPred<_Pred, _Proj> __make_projected(_Pred& __pred, _Proj& __proj) { return _ProjectedPred<_Pred, _Proj>(__pred, __proj); } @@ -81,28 +69,27 @@ __make_projected(_Pred& __pred, _Proj& __proj) { // Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable // optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in // the call stack when the comparator is invoked, even in an unoptimized build. -template <class _Pred, class _Proj> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static -__enable_if_t< - __can_use_pristine_comp<_Pred, _Proj>::value, - _Pred& -> -__make_projected(_Pred& __pred, _Proj&) { +template <class _Pred, + class _Proj, + __enable_if_t<!is_member_pointer<__decay_t<_Pred> >::value && + __is_identity<__decay_t<_Proj> >::value, + int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Pred& __make_projected(_Pred& __pred, _Proj&) { return __pred; } _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template <class _Comp, class _Proj1, class _Proj2> -_LIBCPP_HIDE_FROM_ABI constexpr static +_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) { - if constexpr (same_as<decay_t<_Proj1>, identity> && same_as<decay_t<_Proj2>, identity> && + if constexpr (__is_identity<decay_t<_Proj1>>::value && __is_identity<decay_t<_Proj2>>::value && !is_member_pointer_v<decay_t<_Comp>>) { // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable // optimizations that rely on the type of the comparator. @@ -121,6 +108,6 @@ decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __p _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_MAKE_PROJECTED_H diff --git a/libcxx/include/__algorithm/max.h b/libcxx/include/__algorithm/max.h index a08a3fc59bda..5d8e64cfff39 100644 --- a/libcxx/include/__algorithm/max.h +++ b/libcxx/include/__algorithm/max.h @@ -28,7 +28,7 @@ template <class _Tp, class _Compare> _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& -max(const _Tp& __a, const _Tp& __b, _Compare __comp) +max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__a, __b) ? __b : __a; } @@ -37,9 +37,9 @@ template <class _Tp> _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& -max(const _Tp& __a, const _Tp& __b) +max(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { - return _VSTD::max(__a, __b, __less<_Tp>()); + return _VSTD::max(__a, __b, __less<>()); } #ifndef _LIBCPP_CXX03_LANG @@ -59,7 +59,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp max(initializer_list<_Tp> __t) { - return *_VSTD::max_element(__t.begin(), __t.end(), __less<_Tp>()); + return *_VSTD::max_element(__t.begin(), __t.end(), __less<>()); } #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__algorithm/max_element.h b/libcxx/include/__algorithm/max_element.h index 6ac310619bf9..8fd52c77723c 100644 --- a/libcxx/include/__algorithm/max_element.h +++ b/libcxx/include/__algorithm/max_element.h @@ -24,7 +24,7 @@ template <class _Compare, class _ForwardIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator __max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + static_assert(__has_forward_iterator_category<_ForwardIterator>::value, "std::max_element requires a ForwardIterator"); if (__first != __last) { @@ -48,8 +48,7 @@ template <class _ForwardIterator> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator max_element(_ForwardIterator __first, _ForwardIterator __last) { - return _VSTD::max_element(__first, __last, - __less<typename iterator_traits<_ForwardIterator>::value_type>()); + return _VSTD::max_element(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/merge.h b/libcxx/include/__algorithm/merge.h index e54e430bcb6a..7ee7aaad716e 100644 --- a/libcxx/include/__algorithm/merge.h +++ b/libcxx/include/__algorithm/merge.h @@ -60,9 +60,7 @@ _OutputIterator merge(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) { - typedef typename iterator_traits<_InputIterator1>::value_type __v1; - typedef typename iterator_traits<_InputIterator2>::value_type __v2; - return _VSTD::merge(__first1, __last1, __first2, __last2, __result, __less<__v1, __v2>()); + return _VSTD::merge(__first1, __last1, __first2, __last2, __result, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/min.h b/libcxx/include/__algorithm/min.h index 2882485ad76f..3c0debd6b046 100644 --- a/libcxx/include/__algorithm/min.h +++ b/libcxx/include/__algorithm/min.h @@ -28,7 +28,7 @@ template <class _Tp, class _Compare> _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& -min(const _Tp& __a, const _Tp& __b, _Compare __comp) +min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__b, __a) ? __b : __a; } @@ -37,9 +37,9 @@ template <class _Tp> _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& -min(const _Tp& __a, const _Tp& __b) +min(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { - return _VSTD::min(__a, __b, __less<_Tp>()); + return _VSTD::min(__a, __b, __less<>()); } #ifndef _LIBCPP_CXX03_LANG @@ -59,7 +59,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp min(initializer_list<_Tp> __t) { - return *_VSTD::min_element(__t.begin(), __t.end(), __less<_Tp>()); + return *_VSTD::min_element(__t.begin(), __t.end(), __less<>()); } #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__algorithm/min_element.h b/libcxx/include/__algorithm/min_element.h index c0706fe9e44d..45f3e85ef92d 100644 --- a/libcxx/include/__algorithm/min_element.h +++ b/libcxx/include/__algorithm/min_element.h @@ -22,6 +22,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _Comp, class _Iter, class _Sent, class _Proj> @@ -49,7 +52,7 @@ template <class _ForwardIterator, class _Compare> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + static_assert(__has_forward_iterator_category<_ForwardIterator>::value, "std::min_element requires a ForwardIterator"); static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable"); @@ -61,10 +64,11 @@ template <class _ForwardIterator> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator min_element(_ForwardIterator __first, _ForwardIterator __last) { - return _VSTD::min_element(__first, __last, - __less<typename iterator_traits<_ForwardIterator>::value_type>()); + return _VSTD::min_element(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_MIN_ELEMENT_H diff --git a/libcxx/include/__algorithm/min_max_result.h b/libcxx/include/__algorithm/min_max_result.h index 4be39992b42c..ef2d99038087 100644 --- a/libcxx/include/__algorithm/min_max_result.h +++ b/libcxx/include/__algorithm/min_max_result.h @@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -47,7 +47,7 @@ struct min_max_result { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/minmax.h b/libcxx/include/__algorithm/minmax.h index 6ef0a777083f..bdcf57b101e4 100644 --- a/libcxx/include/__algorithm/minmax.h +++ b/libcxx/include/__algorithm/minmax.h @@ -27,7 +27,7 @@ template<class _Tp, class _Compare> _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<const _Tp&, const _Tp&> -minmax(const _Tp& __a, const _Tp& __b, _Compare __comp) +minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b, _Compare __comp) { return __comp(__b, __a) ? pair<const _Tp&, const _Tp&>(__b, __a) : pair<const _Tp&, const _Tp&>(__a, __b); @@ -37,9 +37,9 @@ template<class _Tp> _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<const _Tp&, const _Tp&> -minmax(const _Tp& __a, const _Tp& __b) +minmax(_LIBCPP_LIFETIMEBOUND const _Tp& __a, _LIBCPP_LIFETIMEBOUND const _Tp& __b) { - return std::minmax(__a, __b, __less<_Tp>()); + return std::minmax(__a, __b, __less<>()); } #ifndef _LIBCPP_CXX03_LANG @@ -59,7 +59,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t) { - return std::minmax(__t, __less<_Tp>()); + return std::minmax(__t, __less<>()); } #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__algorithm/minmax_element.h b/libcxx/include/__algorithm/minmax_element.h index caa963e112e1..5bcaf8354d9f 100644 --- a/libcxx/include/__algorithm/minmax_element.h +++ b/libcxx/include/__algorithm/minmax_element.h @@ -12,9 +12,10 @@ #include <__algorithm/comp.h> #include <__config> #include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_callable.h> #include <__utility/pair.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -82,7 +83,7 @@ template <class _ForwardIterator, class _Compare> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { - static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + static_assert(__has_forward_iterator_category<_ForwardIterator>::value, "std::minmax_element requires a ForwardIterator"); static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable"); @@ -93,7 +94,7 @@ minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __com template <class _ForwardIterator> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_ForwardIterator, _ForwardIterator> minmax_element(_ForwardIterator __first, _ForwardIterator __last) { - return std::minmax_element(__first, __last, __less<typename iterator_traits<_ForwardIterator>::value_type>()); + return std::minmax_element(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/mismatch.h b/libcxx/include/__algorithm/mismatch.h index 600e2cdd3da4..e5b014f45738 100644 --- a/libcxx/include/__algorithm/mismatch.h +++ b/libcxx/include/__algorithm/mismatch.h @@ -38,7 +38,7 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY return std::mismatch(__first1, __last1, __first2, __equal_to()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> diff --git a/libcxx/include/__algorithm/move.h b/libcxx/include/__algorithm/move.h index ac95bda7b61f..01aeef4e177e 100644 --- a/libcxx/include/__algorithm/move.h +++ b/libcxx/include/__algorithm/move.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_MOVE_H #include <__algorithm/copy_move_common.h> +#include <__algorithm/for_each_segment.h> #include <__algorithm/iterator_operations.h> #include <__algorithm/min.h> #include <__config> @@ -45,36 +46,34 @@ struct __move_loop { return std::make_pair(std::move(__first), std::move(__result)); } - template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> - operator()(_InIter __first, _InIter __last, _OutIter __result) const { + template <class _InIter, class _OutIter> + struct _MoveSegment { using _Traits = __segmented_iterator_traits<_InIter>; - auto __sfirst = _Traits::__segment(__first); - auto __slast = _Traits::__segment(__last); - if (__sfirst == __slast) { - auto __iters = std::__move<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result)); - return std::make_pair(__last, std::move(__iters.second)); - } - __result = std::__move<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__sfirst), std::move(__result)).second; - ++__sfirst; - while (__sfirst != __slast) { - __result = - std::__move<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), std::move(__result)).second; - ++__sfirst; + _OutIter& __result_; + + _LIBCPP_HIDE_FROM_ABI _MoveSegment(_OutIter& __result) : __result_(__result) {} + + _LIBCPP_HIDE_FROM_ABI void + operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) { + __result_ = std::__move<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second; } - __result = - std::__move<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__local(__last), std::move(__result)).second; + }; + + template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> + operator()(_InIter __first, _InIter __last, _OutIter __result) const { + std::__for_each_segment(__first, __last, _MoveSegment<_InIter, _OutIter>(__result)); return std::make_pair(__last, std::move(__result)); } template <class _InIter, class _OutIter, - __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value && + __enable_if_t<__has_random_access_iterator_category<_InIter>::value && !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> - operator()(_InIter __first, _InIter __last, _OutIter __result) { + operator()(_InIter __first, _InIter __last, _OutIter __result) const { using _Traits = __segmented_iterator_traits<_OutIter>; using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; diff --git a/libcxx/include/__algorithm/move_backward.h b/libcxx/include/__algorithm/move_backward.h index d4f013be6807..e396abfe0d38 100644 --- a/libcxx/include/__algorithm/move_backward.h +++ b/libcxx/include/__algorithm/move_backward.h @@ -76,11 +76,11 @@ struct __move_backward_loop { template <class _InIter, class _OutIter, - __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value && + __enable_if_t<__has_random_access_iterator_category<_InIter>::value && !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> - operator()(_InIter __first, _InIter __last, _OutIter __result) { + operator()(_InIter __first, _InIter __last, _OutIter __result) const { using _Traits = __segmented_iterator_traits<_OutIter>; using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type; diff --git a/libcxx/include/__algorithm/next_permutation.h b/libcxx/include/__algorithm/next_permutation.h index 73e8b99ab90b..d89768ddc194 100644 --- a/libcxx/include/__algorithm/next_permutation.h +++ b/libcxx/include/__algorithm/next_permutation.h @@ -69,8 +69,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) { - return _VSTD::next_permutation(__first, __last, - __less<typename iterator_traits<_BidirectionalIterator>::value_type>()); + return _VSTD::next_permutation(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/nth_element.h b/libcxx/include/__algorithm/nth_element.h index 9fdfb2cae64c..dbacf58f9ecd 100644 --- a/libcxx/include/__algorithm/nth_element.h +++ b/libcxx/include/__algorithm/nth_element.h @@ -14,7 +14,6 @@ #include <__algorithm/iterator_operations.h> #include <__algorithm/sort.h> #include <__config> -#include <__debug> #include <__debug_utils/randomize_range.h> #include <__iterator/iterator_traits.h> #include <__utility/move.h> @@ -249,8 +248,7 @@ void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Ra template <class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last) { - std::nth_element(std::move(__first), std::move(__nth), std::move(__last), __less<typename - iterator_traits<_RandomAccessIterator>::value_type>()); + std::nth_element(std::move(__first), std::move(__nth), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/partial_sort.h b/libcxx/include/__algorithm/partial_sort.h index e0812affe6b5..56bc9052c748 100644 --- a/libcxx/include/__algorithm/partial_sort.h +++ b/libcxx/include/__algorithm/partial_sort.h @@ -16,11 +16,11 @@ #include <__algorithm/sift_down.h> #include <__algorithm/sort_heap.h> #include <__config> -#include <__debug> #include <__debug_utils/randomize_range.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -87,8 +87,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) { - _VSTD::partial_sort(__first, __middle, __last, - __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); + _VSTD::partial_sort(__first, __middle, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/partial_sort_copy.h b/libcxx/include/__algorithm/partial_sort_copy.h index 1aba07105dc8..b9635c51d5fa 100644 --- a/libcxx/include/__algorithm/partial_sort_copy.h +++ b/libcxx/include/__algorithm/partial_sort_copy.h @@ -79,8 +79,7 @@ _RandomAccessIterator partial_sort_copy(_InputIterator __first, _InputIterator __last, _RandomAccessIterator __result_first, _RandomAccessIterator __result_last) { - return _VSTD::partial_sort_copy(__first, __last, __result_first, __result_last, - __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); + return _VSTD::partial_sort_copy(__first, __last, __result_first, __result_last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/partition.h b/libcxx/include/__algorithm/partition.h index 0e094bf8dd92..a58dd6464aae 100644 --- a/libcxx/include/__algorithm/partition.h +++ b/libcxx/include/__algorithm/partition.h @@ -14,7 +14,6 @@ #include <__iterator/iterator_traits.h> #include <__utility/move.h> #include <__utility/pair.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__algorithm/pop_heap.h b/libcxx/include/__algorithm/pop_heap.h index 94d32a42391b..033af6f2f80f 100644 --- a/libcxx/include/__algorithm/pop_heap.h +++ b/libcxx/include/__algorithm/pop_heap.h @@ -17,20 +17,24 @@ #include <__assert> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len) { - _LIBCPP_ASSERT(__len > 0, "The heap given to pop_heap must be non-empty"); + _LIBCPP_ASSERT_UNCATEGORIZED(__len > 0, "The heap given to pop_heap must be non-empty"); __comp_ref_type<_Compare> __comp_ref = __comp; @@ -64,10 +68,11 @@ void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp template <class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::pop_heap(std::move(__first), std::move(__last), - __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); + std::pop_heap(std::move(__first), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_POP_HEAP_H diff --git a/libcxx/include/__algorithm/prev_permutation.h b/libcxx/include/__algorithm/prev_permutation.h index 0b86ab74ee01..187f1e3e5ba3 100644 --- a/libcxx/include/__algorithm/prev_permutation.h +++ b/libcxx/include/__algorithm/prev_permutation.h @@ -70,8 +70,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last) { - return _VSTD::prev_permutation(__first, __last, - __less<typename iterator_traits<_BidirectionalIterator>::value_type>()); + return _VSTD::prev_permutation(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/pstl_any_all_none_of.h b/libcxx/include/__algorithm/pstl_any_all_none_of.h new file mode 100644 index 000000000000..0e50e0ed3662 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_any_all_none_of.h @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H +#define _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H + +#include <__algorithm/pstl_find.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class> +void __pstl_any_of(); // declaration needed for the frontend dispatch below + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Predicate, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +any_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_any_of), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { + return std::find_if(__policy, __g_first, __g_last, __g_pred) != __g_last; + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +template <class> +void __pstl_all_of(); // declaration needed for the frontend dispatch below + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Pred, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +all_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_all_of), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) { + return !std::any_of(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __value) { + return !__g_pred(__value); + }); + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +template <class> +void __pstl_none_of(); // declaration needed for the frontend dispatch below + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Pred, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +none_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_none_of), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) { + return !std::any_of(__policy, __g_first, __g_last, __g_pred); + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H diff --git a/libcxx/include/__algorithm/pstl_backend.h b/libcxx/include/__algorithm/pstl_backend.h new file mode 100644 index 000000000000..93372f019031 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backend.h @@ -0,0 +1,198 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKEND_H +#define _LIBCPP___ALGORITHM_PSTL_BACKEND_H + +#include <__algorithm/pstl_backends/cpu_backend.h> +#include <__config> +#include <execution> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +/* +TODO: Documentation of how backends work + +A PSTL parallel backend is a tag type to which the following functions are associated, at minimum: + + template <class _ExecutionPolicy, class _Iterator, class _Func> + void __pstl_for_each(_Backend, _ExecutionPolicy&&, _Iterator __first, _Iterator __last, _Func __f); + + template <class _ExecutionPolicy, class _Iterator, class _Predicate> + _Iterator __pstl_find_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); + + template <class _ExecutionPolicy, class _RandomAccessIterator, class _Comp> + void __pstl_stable_sort(_Backend, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp); + + template <class _ExecutionPolicy, class _InIterator, class _OutIterator, class _UnaryOperation> + _OutIterator __pstl_transform(_InIterator __first, _InIterator __last, _OutIterator __result, _UnaryOperation __op); + + template <class _ExecutionPolicy, class _InIterator1, class _InIterator2, class _OutIterator, class _BinaryOperation> + _OutIterator __pstl_transform(_InIterator1 __first1, + _InIterator1 __last1, + _InIterator2 __first2, + _OutIterator __result, + _BinaryOperation __op); + + template <class _ExecutionPolicy, + class _Iterator1, + class _Iterator2, + class _Tp, + class _BinaryOperation1, + class _BinaryOperation2> + _Tp __pstl_transform_reduce(_Backend, + _Iterator1 __first1, + _Iterator1 __last1, + _Iterator2 __first2, + _Iterator2 __last2, + _Tp __init, + _BinaryOperation1 __reduce, + _BinaryOperation2 __transform); + + template <class _ExecutionPolicy, class _Iterator, class _Tp, class _BinaryOperation, class _UnaryOperation> + _Tp __pstl_transform_reduce(_Backend, + _Iterator __first, + _Iterator __last, + _Tp __init, + _BinaryOperation __reduce, + _UnaryOperation __transform); + +// TODO: Complete this list + +The following functions are optional but can be provided. If provided, they are used by the corresponding +algorithms, otherwise they are implemented in terms of other algorithms. If none of the optional algorithms are +implemented, all the algorithms will eventually forward to the basis algorithms listed above: + + template <class _ExecutionPolicy, class _Iterator, class _Size, class _Func> + void __pstl_for_each_n(_Backend, _Iterator __first, _Size __n, _Func __f); + + template <class _ExecutionPolicy, class _Iterator, class _Predicate> + bool __pstl_any_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); + + template <class _ExecutionPolicy, class _Iterator, class _Predicate> + bool __pstl_all_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); + + template <class _ExecutionPolicy, class _Iterator, class _Predicate> + bool __pstl_none_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred); + + template <class _ExecutionPolicy, class _Iterator, class _Tp> + _Iterator __pstl_find(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); + + template <class _ExecutionPolicy, class _Iterator, class _Predicate> + _Iterator __pstl_find_if_not(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); + + template <class _ExecutionPolicy, class _Iterator, class _Tp> + void __pstl_fill(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); + + template <class _ExecutionPolicy, class _Iterator, class _SizeT, class _Tp> + void __pstl_fill_n(_Backend, _Iterator __first, _SizeT __n, const _Tp& __value); + + template <class _ExecutionPolicy, class _Iterator, class _Generator> + void __pstl_generate(_Backend, _Iterator __first, _Iterator __last, _Generator __gen); + + template <class _ExecutionPolicy, class _Iterator, class _Predicate> + void __pstl_is_partitioned(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); + + template <class _ExecutionPolicy, class _Iterator, class _Size, class _Generator> + void __pstl_generator_n(_Backend, _Iterator __first, _Size __n, _Generator __gen); + + template <class _ExecutionPolicy, class _terator1, class _Iterator2, class _OutIterator, class _Comp> + _OutIterator __pstl_merge(_Backend, + _Iterator1 __first1, + _Iterator1 __last1, + _Iterator2 __first2, + _Iterator2 __last2, + _OutIterator __result, + _Comp __comp); + + template <class _ExecutionPolicy, class _Iterator, class _Tp, class _BinaryOperation> + _Tp __pstl_reduce(_Backend, _Iterator __first, _Iterator __last, _Tp __init, _BinaryOperation __op); + + temlate <class _ExecutionPolicy, class _Iterator> + __iter_value_type<_Iterator> __pstl_reduce(_Backend, _Iterator __first, _Iterator __last); + + template <class _ExecuitonPolicy, class _Iterator, class _Tp> + __iter_diff_t<_Iterator> __pstl_count(_Backend, _Iterator __first, _Iterator __last, const _Tp& __value); + + template <class _ExecutionPolicy, class _Iterator, class _Predicate> + __iter_diff_t<_Iterator> __pstl_count_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred); + + template <class _ExecutionPolicy, class _Iterator, class _Tp> + void __pstl_replace(_Backend, _Iterator __first, _Iterator __last, const _Tp& __old_value, const _Tp& __new_value); + + template <class _ExecutionPolicy, class _Iterator, class _Pred, class _Tp> + void __pstl_replace_if(_Backend, _Iterator __first, _Iterator __last, _Pred __pred, const _Tp& __new_value); + + template <class _ExecutionPolicy, class _Iterator, class _OutIterator, class _Tp> + void __pstl_replace_copy(_Backend, + _Iterator __first, + _Iterator __last, + _OutIterator __result, + const _Tp& __old_value, + const _Tp& __new_value); + + template <class _ExecutionPolicy, class _Iterator, class _OutIterator, class _Pred, class _Tp> + void __pstl_replace_copy_if(_Backend, + _Iterator __first, + _Iterator __last, + _OutIterator __result, + _Pred __pred, + const _Tp& __new_value); + + template <class _ExecutionPolicy, class _Iterator, class _Comp> + void __pstl_sort(_Backend, _Iterator __first, _Iterator __last, _Comp __comp); + +// TODO: Complete this list + +*/ + +template <class _ExecutionPolicy> +struct __select_backend; + +template <> +struct __select_backend<std::execution::sequenced_policy> { + using type = __cpu_backend_tag; +}; + +# if _LIBCPP_STD_VER >= 20 +template <> +struct __select_backend<std::execution::unsequenced_policy> { + using type = __cpu_backend_tag; +}; +# endif + +# if defined(_LIBCPP_PSTL_CPU_BACKEND_SERIAL) || defined(_LIBCPP_PSTL_CPU_BACKEND_THREAD) || \ + defined(_LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) +template <> +struct __select_backend<std::execution::parallel_policy> { + using type = __cpu_backend_tag; +}; + +template <> +struct __select_backend<std::execution::parallel_unsequenced_policy> { + using type = __cpu_backend_tag; +}; + +# else + +// ...New vendors can add parallel backends here... + +# error "Invalid choice of a PSTL parallel backend" +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKEND_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backend.h b/libcxx/include/__algorithm/pstl_backends/cpu_backend.h new file mode 100644 index 000000000000..e54f331b9430 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backend.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H + +#include <__config> + +/* + + // _Functor takes a subrange for [__first, __last) that should be executed in serial + template <class _RandomAccessIterator, class _Functor> + void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func); + + template <class _Iterator, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduction> + _Tp __parallel_transform_reduce(_Iterator __first, _Iterator __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduction); + + // Cancel the execution of other jobs - they aren't needed anymore + void __cancel_execution(); + + template <class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _RandomAccessIterator3, + class _Compare, + class _LeafMerge> + void __parallel_merge( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __outit, + _Compare __comp, + _LeafMerge __leaf_merge); + + template <class _RandomAccessIterator, class _Comp, class _LeafSort> + void __parallel_stable_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Comp __comp, + _LeafSort __leaf_sort); + + TODO: Document the parallel backend +*/ + +#include <__algorithm/pstl_backends/cpu_backends/any_of.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__algorithm/pstl_backends/cpu_backends/fill.h> +#include <__algorithm/pstl_backends/cpu_backends/find_if.h> +#include <__algorithm/pstl_backends/cpu_backends/for_each.h> +#include <__algorithm/pstl_backends/cpu_backends/merge.h> +#include <__algorithm/pstl_backends/cpu_backends/stable_sort.h> +#include <__algorithm/pstl_backends/cpu_backends/transform.h> +#include <__algorithm/pstl_backends/cpu_backends/transform_reduce.h> + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h new file mode 100644 index 000000000000..8fe26797bf15 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/any_of.h @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H + +#include <__algorithm/any_of.h> +#include <__algorithm/find_if.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__atomic/atomic.h> +#include <__atomic/memory_order.h> +#include <__config> +#include <__functional/operations.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/pair.h> +#include <__utility/terminate_on_exception.h> +#include <cstdint> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Index, class _Brick> +_LIBCPP_HIDE_FROM_ABI bool __parallel_or(_Index __first, _Index __last, _Brick __f) { + std::atomic<bool> __found(false); + __par_backend::__parallel_for(__first, __last, [__f, &__found](_Index __i, _Index __j) { + if (!__found.load(std::memory_order_relaxed) && __f(__i, __j)) { + __found.store(true, std::memory_order_relaxed); + __par_backend::__cancel_execution(); + } + }); + return __found; +} + +// TODO: check whether __simd_first() can be used here +template <class _Index, class _DifferenceType, class _Pred> +_LIBCPP_HIDE_FROM_ABI bool __simd_or(_Index __first, _DifferenceType __n, _Pred __pred) noexcept { + _DifferenceType __block_size = 4 < __n ? 4 : __n; + const _Index __last = __first + __n; + while (__last != __first) { + int32_t __flag = 1; + _PSTL_PRAGMA_SIMD_REDUCTION(& : __flag) + for (_DifferenceType __i = 0; __i < __block_size; ++__i) + if (__pred(*(__first + __i))) + __flag = 0; + if (!__flag) + return true; + + __first += __block_size; + if (__last - __first >= __block_size << 1) { + // Double the block _Size. Any unnecessary iterations can be amortized against work done so far. + __block_size <<= 1; + } else { + __block_size = __last - __first; + } + } + return false; +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> +_LIBCPP_HIDE_FROM_ABI bool +__pstl_any_of(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + return std::__terminate_on_exception([&] { + return std::__parallel_or( + __first, __last, [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + return std::__pstl_any_of<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __pred); + }); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + return std::__simd_or(__first, __last - __first, __pred); + } else { + return std::any_of(__first, __last, __pred); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/backend.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/backend.h new file mode 100644 index 000000000000..ea2210a4a7ad --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/backend.h @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H + +#include <__config> +#include <cstddef> + +#if defined(_LIBCPP_PSTL_CPU_BACKEND_SERIAL) +# include <__algorithm/pstl_backends/cpu_backends/serial.h> +#elif defined(_LIBCPP_PSTL_CPU_BACKEND_THREAD) +# include <__algorithm/pstl_backends/cpu_backends/thread.h> +#elif defined(_LIBCPP_PSTL_CPU_BACKEND_LIBDISPATCH) +# include <__algorithm/pstl_backends/cpu_backends/libdispatch.h> +#else +# error "Invalid CPU backend choice" +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __cpu_backend_tag {}; + +inline constexpr size_t __lane_size = 64; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_BACKEND_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h new file mode 100644 index 000000000000..5e5e0a23bf89 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/fill.h @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H + +#include <__algorithm/fill.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Index, class _DifferenceType, class _Tp> +_LIBCPP_HIDE_FROM_ABI _Index __simd_fill_n(_Index __first, _DifferenceType __n, const _Tp& __value) noexcept { + _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __first[__i] = __value; + return __first + __n; +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +_LIBCPP_HIDE_FROM_ABI void +__pstl_fill(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + std::__terminate_on_exception([&] { + __par_backend::__parallel_for( + __first, __last, [&__value](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + std::__pstl_fill<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __value); + }); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + std::__simd_fill_n(__first, __last - __first, __value); + } else { + std::fill(__first, __last, __value); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h new file mode 100644 index 000000000000..3fa49549e64e --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/find_if.h @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H + +#include <__algorithm/find_if.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__atomic/atomic.h> +#include <__config> +#include <__functional/operations.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/pair.h> +#include <__utility/terminate_on_exception.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Index, class _Brick, class _Compare> +_LIBCPP_HIDE_FROM_ABI _Index +__parallel_find(_Index __first, _Index __last, _Brick __f, _Compare __comp, bool __b_first) { + typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType; + const _DifferenceType __n = __last - __first; + _DifferenceType __initial_dist = __b_first ? __n : -1; + std::atomic<_DifferenceType> __extremum(__initial_dist); + // TODO: find out what is better here: parallel_for or parallel_reduce + __par_backend::__parallel_for(__first, __last, [__comp, __f, __first, &__extremum](_Index __i, _Index __j) { + // See "Reducing Contention Through Priority Updates", PPoPP '13, for discussion of + // why using a shared variable scales fairly well in this situation. + if (__comp(__i - __first, __extremum)) { + _Index __res = __f(__i, __j); + // If not '__last' returned then we found what we want so put this to extremum + if (__res != __j) { + const _DifferenceType __k = __res - __first; + for (_DifferenceType __old = __extremum; __comp(__k, __old); __old = __extremum) { + __extremum.compare_exchange_weak(__old, __k); + } + } + } + }); + return __extremum != __initial_dist ? __first + __extremum : __last; +} + +template <class _Index, class _DifferenceType, class _Compare> +_LIBCPP_HIDE_FROM_ABI _Index +__simd_first(_Index __first, _DifferenceType __begin, _DifferenceType __end, _Compare __comp) noexcept { + // Experiments show good block sizes like this + const _DifferenceType __block_size = 8; + alignas(__lane_size) _DifferenceType __lane[__block_size] = {0}; + while (__end - __begin >= __block_size) { + _DifferenceType __found = 0; + _PSTL_PRAGMA_SIMD_REDUCTION(| : __found) for (_DifferenceType __i = __begin; __i < __begin + __block_size; ++__i) { + const _DifferenceType __t = __comp(__first, __i); + __lane[__i - __begin] = __t; + __found |= __t; + } + if (__found) { + _DifferenceType __i; + // This will vectorize + for (__i = 0; __i < __block_size; ++__i) { + if (__lane[__i]) { + break; + } + } + return __first + __begin + __i; + } + __begin += __block_size; + } + + // Keep remainder scalar + while (__begin != __end) { + if (__comp(__first, __begin)) { + return __first + __begin; + } + ++__begin; + } + return __first + __end; +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +__pstl_find_if(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + return std::__terminate_on_exception([&] { + return std::__parallel_find( + __first, + __last, + [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + return std::__pstl_find_if<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __pred); + }, + less<>{}, + true); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + using __diff_t = __iter_diff_t<_ForwardIterator>; + return std::__simd_first(__first, __diff_t(0), __last - __first, [&__pred](_ForwardIterator __iter, __diff_t __i) { + return __pred(__iter[__i]); + }); + } else { + return std::find_if(__first, __last, __pred); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FIND_IF_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h new file mode 100644 index 000000000000..36d0ac238e24 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/for_each.h @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H + +#include <__algorithm/for_each.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Iterator, class _DifferenceType, class _Function> +_LIBCPP_HIDE_FROM_ABI _Iterator __simd_walk_1(_Iterator __first, _DifferenceType __n, _Function __f) noexcept { + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first[__i]); + + return __first + __n; +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Functor> +_LIBCPP_HIDE_FROM_ABI void +__pstl_for_each(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Functor __func) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + std::__terminate_on_exception([&] { + std::__par_backend::__parallel_for( + __first, __last, [__func](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + std::__pstl_for_each<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __func); + }); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + std::__simd_walk_1(__first, __last - __first, __func); + } else { + std::for_each(__first, __last, __func); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKNEDS_FOR_EACH_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h new file mode 100644 index 000000000000..bab6a3639bd0 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/libdispatch.h @@ -0,0 +1,241 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H + +#include <__algorithm/lower_bound.h> +#include <__algorithm/max.h> +#include <__algorithm/upper_bound.h> +#include <__atomic/atomic.h> +#include <__config> +#include <__exception/terminate.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/move_iterator.h> +#include <__memory/allocator.h> +#include <__memory/construct_at.h> +#include <__memory/unique_ptr.h> +#include <__numeric/reduce.h> +#include <__utility/exception_guard.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include <__utility/terminate_on_exception.h> +#include <cstddef> +#include <new> + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __par_backend { +inline namespace __libdispatch { + +// ::dispatch_apply is marked as __attribute__((nothrow)) because it doesn't let exceptions propagate, and neither do +// we. +// TODO: Do we want to add [[_Clang::__callback__(__func, __context, __)]]? +_LIBCPP_EXPORTED_FROM_ABI void +__dispatch_apply(size_t __chunk_count, void* __context, void (*__func)(void* __context, size_t __chunk)) noexcept; + +template <class _Func> +_LIBCPP_HIDE_FROM_ABI void __dispatch_apply(size_t __chunk_count, _Func __func) noexcept { + __libdispatch::__dispatch_apply(__chunk_count, &__func, [](void* __context, size_t __chunk) { + (*static_cast<_Func*>(__context))(__chunk); + }); +} + +struct __chunk_partitions { + ptrdiff_t __chunk_count_; // includes the first chunk + ptrdiff_t __chunk_size_; + ptrdiff_t __first_chunk_size_; +}; + +[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI __chunk_partitions __partition_chunks(ptrdiff_t __size); + +template <class _RandomAccessIterator, class _Functor> +_LIBCPP_HIDE_FROM_ABI void +__parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func) { + auto __partitions = __libdispatch::__partition_chunks(__last - __first); + + // Perform the chunked execution. + __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __chunk) { + auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_; + auto __index = + __chunk == 0 + ? 0 + : (__chunk * __partitions.__chunk_size_) + (__partitions.__first_chunk_size_ - __partitions.__chunk_size_); + __func(__first + __index, __first + __index + __this_chunk_size); + }); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIteratorOut> +struct __merge_range { + __merge_range(_RandomAccessIterator1 __mid1, _RandomAccessIterator2 __mid2, _RandomAccessIteratorOut __result) + : __mid1_(__mid1), __mid2_(__mid2), __result_(__result) {} + + _RandomAccessIterator1 __mid1_; + _RandomAccessIterator2 __mid2_; + _RandomAccessIteratorOut __result_; +}; + +template <typename _RandomAccessIterator1, + typename _RandomAccessIterator2, + typename _RandomAccessIterator3, + typename _Compare, + typename _LeafMerge> +_LIBCPP_HIDE_FROM_ABI void __parallel_merge( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp, + _LeafMerge __leaf_merge) { + __chunk_partitions __partitions = + __libdispatch::__partition_chunks(std::max<ptrdiff_t>(__last1 - __first1, __last2 - __first2)); + + if (__partitions.__chunk_count_ == 0) + return; + + if (__partitions.__chunk_count_ == 1) { + __leaf_merge(__first1, __last1, __first2, __last2, __result, __comp); + return; + } + + using __merge_range_t = __merge_range<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3>; + auto const __n_ranges = __partitions.__chunk_count_ + 1; + + // TODO: use __uninitialized_buffer + auto __destroy = [=](__merge_range_t* __ptr) { + std::destroy_n(__ptr, __n_ranges); + std::allocator<__merge_range_t>().deallocate(__ptr, __n_ranges); + }; + unique_ptr<__merge_range_t[], decltype(__destroy)> __ranges( + std::allocator<__merge_range_t>().allocate(__n_ranges), __destroy); + + // TODO: Improve the case where the smaller range is merged into just a few (or even one) chunks of the larger case + std::__terminate_on_exception([&] { + __merge_range_t* __r = __ranges.get(); + std::__construct_at(__r++, __first1, __first2, __result); + + bool __iterate_first_range = __last1 - __first1 > __last2 - __first2; + + auto __compute_chunk = [&](size_t __chunk_size) -> __merge_range_t { + auto [__mid1, __mid2] = [&] { + if (__iterate_first_range) { + auto __m1 = __first1 + __chunk_size; + auto __m2 = std::lower_bound(__first2, __last2, __m1[-1], __comp); + return std::make_pair(__m1, __m2); + } else { + auto __m2 = __first2 + __chunk_size; + auto __m1 = std::lower_bound(__first1, __last1, __m2[-1], __comp); + return std::make_pair(__m1, __m2); + } + }(); + + __result += (__mid1 - __first1) + (__mid2 - __first2); + __first1 = __mid1; + __first2 = __mid2; + return {std::move(__mid1), std::move(__mid2), __result}; + }; + + // handle first chunk + std::__construct_at(__r++, __compute_chunk(__partitions.__first_chunk_size_)); + + // handle 2 -> N - 1 chunks + for (ptrdiff_t __i = 0; __i != __partitions.__chunk_count_ - 2; ++__i) + std::__construct_at(__r++, __compute_chunk(__partitions.__chunk_size_)); + + // handle last chunk + std::__construct_at(__r, __last1, __last2, __result); + + __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __index) { + auto __first_iters = __ranges[__index]; + auto __last_iters = __ranges[__index + 1]; + __leaf_merge( + __first_iters.__mid1_, + __last_iters.__mid1_, + __first_iters.__mid2_, + __last_iters.__mid2_, + __first_iters.__result_, + __comp); + }); + }); +} + +template <class _RandomAccessIterator, class _Transform, class _Value, class _Combiner, class _Reduction> +_LIBCPP_HIDE_FROM_ABI _Value __parallel_transform_reduce( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Transform __transform, + _Value __init, + _Combiner __combiner, + _Reduction __reduction) { + if (__first == __last) + return __init; + + auto __partitions = __libdispatch::__partition_chunks(__last - __first); + + auto __destroy = [__count = __partitions.__chunk_count_](_Value* __ptr) { + std::destroy_n(__ptr, __count); + std::allocator<_Value>().deallocate(__ptr, __count); + }; + + // TODO: use __uninitialized_buffer + // TODO: allocate one element per worker instead of one element per chunk + unique_ptr<_Value[], decltype(__destroy)> __values( + std::allocator<_Value>().allocate(__partitions.__chunk_count_), __destroy); + + // __dispatch_apply is noexcept + __libdispatch::__dispatch_apply(__partitions.__chunk_count_, [&](size_t __chunk) { + auto __this_chunk_size = __chunk == 0 ? __partitions.__first_chunk_size_ : __partitions.__chunk_size_; + auto __index = + __chunk == 0 + ? 0 + : (__chunk * __partitions.__chunk_size_) + (__partitions.__first_chunk_size_ - __partitions.__chunk_size_); + if (__this_chunk_size != 1) { + std::__construct_at( + __values.get() + __chunk, + __reduction(__first + __index + 2, + __first + __index + __this_chunk_size, + __combiner(__transform(__first + __index), __transform(__first + __index + 1)))); + } else { + std::__construct_at(__values.get() + __chunk, __transform(__first + __index)); + } + }); + + return std::__terminate_on_exception([&] { + return std::reduce( + std::make_move_iterator(__values.get()), + std::make_move_iterator(__values.get() + __partitions.__chunk_count_), + std::move(__init), + __combiner); + }); +} + +// TODO: parallelize this +template <class _RandomAccessIterator, class _Comp, class _LeafSort> +_LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( + _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp, _LeafSort __leaf_sort) { + __leaf_sort(__first, __last, __comp); +} + +_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} + +} // namespace __libdispatch +} // namespace __par_backend + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_LIBDISPATCH_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h new file mode 100644 index 000000000000..d5be1e302d35 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/merge.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H + +#include <__algorithm/merge.h> +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardOutIterator, + class _Comp> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_merge( + __cpu_backend_tag, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardOutIterator __result, + _Comp __comp) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value && + __has_random_access_iterator_category<_ForwardOutIterator>::value) { + return std::__terminate_on_exception([&] { + __par_backend::__parallel_merge( + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_ForwardIterator1 __g_first1, + _ForwardIterator1 __g_last1, + _ForwardIterator2 __g_first2, + _ForwardIterator2 __g_last2, + _ForwardOutIterator __g_result, + _Comp __g_comp) { + return std::__pstl_merge<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + std::move(__g_first1), + std::move(__g_last1), + std::move(__g_first2), + std::move(__g_last2), + std::move(__g_result), + std::move(__g_comp)); + }); + return __result + (__last1 - __first1) + (__last2 - __first2); + }); + } else { + return std::merge(__first1, __last1, __first2, __last2, __result, __comp); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_MERGE_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h new file mode 100644 index 000000000000..f151c3b098f6 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/serial.h @@ -0,0 +1,72 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H + +#include <__config> +#include <__utility/move.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __par_backend { +inline namespace __serial_cpu_backend { + +template <class _RandomAccessIterator, class _Fp> +_LIBCPP_HIDE_FROM_ABI void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { + __f(__first, __last); +} + +template <class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce> +_LIBCPP_HIDE_FROM_ABI _Tp +__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { + return __reduce(std::move(__first), std::move(__last), std::move(__init)); +} + +template <class _RandomAccessIterator, class _Compare, class _LeafSort> +_LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( + _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { + __leaf_sort(__first, __last, __comp); +} + +_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} + +template <class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _RandomAccessIterator3, + class _Compare, + class _LeafMerge> +_LIBCPP_HIDE_FROM_ABI void __parallel_merge( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __outit, + _Compare __comp, + _LeafMerge __leaf_merge) { + __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); +} + +// TODO: Complete this list + +} // namespace __serial_cpu_backend +} // namespace __par_backend + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_SERIAL_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h new file mode 100644 index 000000000000..0a701443b3c4 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/stable_sort.h @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H + +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__algorithm/stable_sort.h> +#include <__config> +#include <__type_traits/is_execution_policy.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Comp> +_LIBCPP_HIDE_FROM_ABI void +__pstl_stable_sort(__cpu_backend_tag, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy>) { + std::__terminate_on_exception([&] { + __par_backend::__parallel_stable_sort( + __first, __last, __comp, [](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { + std::stable_sort(__g_first, __g_last, __g_comp); + }); + }); + } else { + std::stable_sort(__first, __last, __comp); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_STABLE_SORT_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h new file mode 100644 index 000000000000..30eb0ae3626d --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/thread.h @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H + +#include <__assert> +#include <__config> +#include <__utility/move.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +// This backend implementation is for testing purposes only and not meant for production use. This will be replaced +// by a proper implementation once the PSTL implementation is somewhat stable. + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __par_backend { +inline namespace __thread_cpu_backend { + +template <class _RandomAccessIterator, class _Fp> +_LIBCPP_HIDE_FROM_ABI void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Fp __f) { + __f(__first, __last); +} + +template <class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce> +_LIBCPP_HIDE_FROM_ABI _Tp +__parallel_transform_reduce(_Index __first, _Index __last, _UnaryOp, _Tp __init, _BinaryOp, _Reduce __reduce) { + return __reduce(std::move(__first), std::move(__last), std::move(__init)); +} + +template <class _RandomAccessIterator, class _Compare, class _LeafSort> +_LIBCPP_HIDE_FROM_ABI void __parallel_stable_sort( + _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort) { + __leaf_sort(__first, __last, __comp); +} + +_LIBCPP_HIDE_FROM_ABI inline void __cancel_execution() {} + +template <class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _RandomAccessIterator3, + class _Compare, + class _LeafMerge> +_LIBCPP_HIDE_FROM_ABI void __parallel_merge( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __outit, + _Compare __comp, + _LeafMerge __leaf_merge) { + __leaf_merge(__first1, __last1, __first2, __last2, __outit, __comp); +} + +} // namespace __thread_cpu_backend +} // namespace __par_backend + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && && _LIBCPP_STD_VER >= 17 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_THREAD_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h new file mode 100644 index 000000000000..ef25ff0238da --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform.h @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H + +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__algorithm/transform.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Iterator1, class _DifferenceType, class _Iterator2, class _Function> +_LIBCPP_HIDE_FROM_ABI _Iterator2 +__simd_walk_2(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Function __f) noexcept { + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first1[__i], __first2[__i]); + return __first2 + __n; +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _ForwardOutIterator, class _UnaryOperation> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform( + __cpu_backend_tag, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + _UnaryOperation __op) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value && + __has_random_access_iterator_category<_ForwardOutIterator>::value) { + std::__terminate_on_exception([&] { + std::__par_backend::__parallel_for( + __first, __last, [__op, __first, __result](_ForwardIterator __brick_first, _ForwardIterator __brick_last) { + return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, __brick_first, __brick_last, __result + (__brick_first - __first), __op); + }); + }); + return __result + (__last - __first); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value && + __has_random_access_iterator_category<_ForwardOutIterator>::value) { + return std::__simd_walk_2( + __first, + __last - __first, + __result, + [&](__iter_reference<_ForwardIterator> __in_value, __iter_reference<_ForwardOutIterator> __out_value) { + __out_value = __op(__in_value); + }); + } else { + return std::transform(__first, __last, __result, __op); + } +} + +template <class _Iterator1, class _DifferenceType, class _Iterator2, class _Iterator3, class _Function> +_LIBCPP_HIDE_FROM_ABI _Iterator3 __simd_walk_3( + _Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Iterator3 __first3, _Function __f) noexcept { + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first1[__i], __first2[__i], __first3[__i]); + return __first3 + __n; +} +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardOutIterator, + class _BinaryOperation, + enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator __pstl_transform( + __cpu_backend_tag, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardOutIterator __result, + _BinaryOperation __op) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value && + __has_random_access_iterator_category<_ForwardOutIterator>::value) { + std::__terminate_on_exception([&] { + std::__par_backend::__parallel_for( + __first1, + __last1, + [__op, __first1, __first2, __result](_ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last) { + return std::__pstl_transform<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + __brick_first, + __brick_last, + __first2 + (__brick_first - __first1), + __result + (__brick_first - __first1), + __op); + }); + }); + return __result + (__last1 - __first1); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value && + __has_random_access_iterator_category<_ForwardOutIterator>::value) { + return std::__simd_walk_3( + __first1, + __last1 - __first1, + __first2, + __result, + [&](__iter_reference<_ForwardIterator1> __in1, + __iter_reference<_ForwardIterator2> __in2, + __iter_reference<_ForwardOutIterator> __out_value) { __out_value = __op(__in1, __in2); }); + } else { + return std::transform(__first1, __last1, __first2, __result, __op); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_H diff --git a/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h new file mode 100644 index 000000000000..c51c312d938a --- /dev/null +++ b/libcxx/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h @@ -0,0 +1,194 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H +#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H + +#include <__algorithm/pstl_backends/cpu_backends/backend.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__numeric/transform_reduce.h> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/operation_traits.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> +#include <new> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template < + typename _DifferenceType, + typename _Tp, + typename _BinaryOperation, + typename _UnaryOperation, + __enable_if_t<__is_trivial_plus_operation<_BinaryOperation, _Tp, _Tp>::value && is_arithmetic_v<_Tp>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp +__simd_transform_reduce(_DifferenceType __n, _Tp __init, _BinaryOperation, _UnaryOperation __f) noexcept { + _PSTL_PRAGMA_SIMD_REDUCTION(+ : __init) + for (_DifferenceType __i = 0; __i < __n; ++__i) + __init += __f(__i); + return __init; +} + +template < + typename _Size, + typename _Tp, + typename _BinaryOperation, + typename _UnaryOperation, + __enable_if_t<!(__is_trivial_plus_operation<_BinaryOperation, _Tp, _Tp>::value && is_arithmetic_v<_Tp>), int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp +__simd_transform_reduce(_Size __n, _Tp __init, _BinaryOperation __binary_op, _UnaryOperation __f) noexcept { + const _Size __block_size = __lane_size / sizeof(_Tp); + if (__n > 2 * __block_size && __block_size > 1) { + alignas(__lane_size) char __lane_buffer[__lane_size]; + _Tp* __lane = reinterpret_cast<_Tp*>(__lane_buffer); + + // initializer + _PSTL_PRAGMA_SIMD + for (_Size __i = 0; __i < __block_size; ++__i) { + ::new (__lane + __i) _Tp(__binary_op(__f(__i), __f(__block_size + __i))); + } + // main loop + _Size __i = 2 * __block_size; + const _Size __last_iteration = __block_size * (__n / __block_size); + for (; __i < __last_iteration; __i += __block_size) { + _PSTL_PRAGMA_SIMD + for (_Size __j = 0; __j < __block_size; ++__j) { + __lane[__j] = __binary_op(std::move(__lane[__j]), __f(__i + __j)); + } + } + // remainder + _PSTL_PRAGMA_SIMD + for (_Size __j = 0; __j < __n - __last_iteration; ++__j) { + __lane[__j] = __binary_op(std::move(__lane[__j]), __f(__last_iteration + __j)); + } + // combiner + for (_Size __j = 0; __j < __block_size; ++__j) { + __init = __binary_op(std::move(__init), std::move(__lane[__j])); + } + // destroyer + _PSTL_PRAGMA_SIMD + for (_Size __j = 0; __j < __block_size; ++__j) { + __lane[__j].~_Tp(); + } + } else { + for (_Size __i = 0; __i < __n; ++__i) { + __init = __binary_op(std::move(__init), __f(__i)); + } + } + return __init; +} + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _Tp, + class _BinaryOperation1, + class _BinaryOperation2> +_LIBCPP_HIDE_FROM_ABI _Tp __pstl_transform_reduce( + __cpu_backend_tag, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Tp __init, + _BinaryOperation1 __reduce, + _BinaryOperation2 __transform) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value) { + return std::__terminate_on_exception([&] { + return __par_backend::__parallel_transform_reduce( + __first1, + std::move(__last1), + [__first1, __first2, __transform](_ForwardIterator1 __iter) { + return __transform(*__iter, *(__first2 + (__iter - __first1))); + }, + std::move(__init), + std::move(__reduce), + [__first1, __first2, __reduce, __transform]( + _ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last, _Tp __brick_init) { + return std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + __brick_first, + std::move(__brick_last), + __first2 + (__brick_first - __first1), + std::move(__brick_init), + std::move(__reduce), + std::move(__transform)); + }); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator1>::value && + __has_random_access_iterator_category<_ForwardIterator2>::value) { + return std::__simd_transform_reduce( + __last1 - __first1, std::move(__init), std::move(__reduce), [&](__iter_diff_t<_ForwardIterator1> __i) { + return __transform(__first1[__i], __first2[__i]); + }); + } else { + return std::transform_reduce( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__init), + std::move(__reduce), + std::move(__transform)); + } +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation, class _UnaryOperation> +_LIBCPP_HIDE_FROM_ABI _Tp __pstl_transform_reduce( + __cpu_backend_tag, + _ForwardIterator __first, + _ForwardIterator __last, + _Tp __init, + _BinaryOperation __reduce, + _UnaryOperation __transform) { + if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + return std::__terminate_on_exception([&] { + return __par_backend::__parallel_transform_reduce( + std::move(__first), + std::move(__last), + [__transform](_ForwardIterator __iter) { return __transform(*__iter); }, + std::move(__init), + __reduce, + [__transform, __reduce](auto __brick_first, auto __brick_last, _Tp __brick_init) { + return std::__pstl_transform_reduce<__remove_parallel_policy_t<_ExecutionPolicy>>( + __cpu_backend_tag{}, + std::move(__brick_first), + std::move(__brick_last), + std::move(__brick_init), + std::move(__reduce), + std::move(__transform)); + }); + }); + } else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> && + __has_random_access_iterator_category<_ForwardIterator>::value) { + return std::__simd_transform_reduce( + __last - __first, + std::move(__init), + std::move(__reduce), + [=, &__transform](__iter_diff_t<_ForwardIterator> __i) { return __transform(__first[__i]); }); + } else { + return std::transform_reduce( + std::move(__first), std::move(__last), std::move(__init), std::move(__reduce), std::move(__transform)); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_TRANSFORM_REDUCE_H diff --git a/libcxx/include/__algorithm/pstl_copy.h b/libcxx/include/__algorithm/pstl_copy.h new file mode 100644 index 000000000000..83c712c35407 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_copy.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_COPY_H +#define _LIBCPP___ALGORITHM_PSTL_COPY_H + +#include <__algorithm/copy_n.h> +#include <__algorithm/pstl_transform.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/is_trivially_copyable.h> +#include <__type_traits/remove_cvref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +// TODO: Use the std::copy/move shenanigans to forward to std::memmove + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _ForwardOutIterator, + enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +copy(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _ForwardOutIterator __result) { + return std::transform(__policy, __first, __last, __result, __identity()); +} + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _ForwardOutIterator, + class _Size, + enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +copy_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _ForwardOutIterator __result) { + if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) + return std::copy(__policy, __first, __first + __n, __result); + else + return std::copy_n(__first, __n, __result); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_COPY_H diff --git a/libcxx/include/__algorithm/pstl_count.h b/libcxx/include/__algorithm/pstl_count.h new file mode 100644 index 000000000000..15acb85de0bf --- /dev/null +++ b/libcxx/include/__algorithm/pstl_count.h @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_COUNT_H +#define _LIBCPP___ALGORITHM_PSTL_COUNT_H + +#include <__algorithm/count.h> +#include <__algorithm/for_each.h> +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_for_each.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__atomic/atomic.h> +#include <__config> +#include <__functional/operations.h> +#include <__iterator/iterator_traits.h> +#include <__numeric/pstl_transform_reduce.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class> +void __pstl_count_if(); // declaration needed for the frontend dispatch below + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Predicate, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> +count_if(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + using __diff_t = __iter_diff_t<_ForwardIterator>; + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_count_if), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { + return std::transform_reduce( + __policy, + std::move(__g_first), + std::move(__g_last), + __diff_t(), + std::plus{}, + [&](__iter_reference<_ForwardIterator> __element) -> bool { return __g_pred(__element); }); + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +template <class> +void __pstl_count(); // declaration needed for the frontend dispatch below + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Tp, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI __iter_diff_t<_ForwardIterator> +count(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_count), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { + return std::count_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __v) { + return __v == __g_value; + }); + }, + std::move(__first), + std::move(__last), + __value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_COUNT_H diff --git a/libcxx/include/__algorithm/pstl_fill.h b/libcxx/include/__algorithm/pstl_fill.h new file mode 100644 index 000000000000..d64c828d9046 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_fill.h @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_FILL_H +#define _LIBCPP___ALGORITHM_PSTL_FILL_H + +#include <__algorithm/fill_n.h> +#include <__algorithm/pstl_for_each.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class> +void __pstl_fill(); // declaration needed for the frontend dispatch below + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Tp, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { + std::for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) { + __element = __g_value; + }); + }, + std::move(__first), + std::move(__last), + __value); +} + +template <class> +void __pstl_fill_n(); // declaration needed for the frontend dispatch below + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _SizeT, + class _Tp, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _SizeT __n, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill_n), + [&](_ForwardIterator __g_first, _SizeT __g_n, const _Tp& __g_value) { + if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) + std::fill(__policy, __g_first, __g_first + __g_n, __g_value); + else + std::fill_n(__g_first, __g_n, __g_value); + }, + std::move(__first), + __n, + __value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_FILL_H diff --git a/libcxx/include/__algorithm/pstl_find.h b/libcxx/include/__algorithm/pstl_find.h new file mode 100644 index 000000000000..8e8adfecfa46 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_find.h @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_FIND_H +#define _LIBCPP___ALGORITHM_PSTL_FIND_H + +#include <__algorithm/comp.h> +#include <__algorithm/find.h> +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Predicate, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +find_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_find_if<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__pred)); +} + +template <class> +void __pstl_find_if_not(); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Predicate, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find_if_not), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { + return std::find_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __value) { + return !__g_pred(__value); + }); + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +template <class> +void __pstl_find(); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Tp, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find), + [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { + return std::find_if(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) { + return __element == __g_value; + }); + }, + std::move(__first), + std::move(__last), + __value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_FIND_H diff --git a/libcxx/include/__algorithm/pstl_for_each.h b/libcxx/include/__algorithm/pstl_for_each.h new file mode 100644 index 000000000000..09efc24950db --- /dev/null +++ b/libcxx/include/__algorithm/pstl_for_each.h @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_FOR_EACH_H +#define _LIBCPP___ALGORITHM_PSTL_FOR_EACH_H + +#include <__algorithm/for_each.h> +#include <__algorithm/for_each_n.h> +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/void_t.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Function, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +for_each(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __func) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + using _Backend = typename __select_backend<_RawPolicy>::type; + std::__pstl_for_each<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__func)); +} + +template <class> +void __pstl_for_each_n(); // declaration needed for the frontend dispatch below + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Size, + class _Function, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +for_each_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_for_each_n), + [&](_ForwardIterator __g_first, _Size __g_size, _Function __g_func) { + if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) { + std::for_each(__policy, std::move(__g_first), __g_first + __g_size, std::move(__g_func)); + } else { + std::for_each_n(std::move(__g_first), __g_size, std::move(__g_func)); + } + }, + __first, + __size, + std::move(__func)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_FOR_EACH_H diff --git a/libcxx/include/__algorithm/pstl_frontend_dispatch.h b/libcxx/include/__algorithm/pstl_frontend_dispatch.h new file mode 100644 index 000000000000..dc49f3e5163a --- /dev/null +++ b/libcxx/include/__algorithm/pstl_frontend_dispatch.h @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_FRONTEND_DISPATCH +#define _LIBCPP___ALGORITHM_PSTL_FRONTEND_DISPATCH + +#include <__config> +#include <__type_traits/is_callable.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +# define _LIBCPP_PSTL_CUSTOMIZATION_POINT(name) \ + [](auto&&... __args) -> decltype(std::name<_RawPolicy>(typename __select_backend<_RawPolicy>::type{}, \ + std::forward<decltype(__args)>(__args)...)) { \ + return std::name<_RawPolicy>( \ + typename __select_backend<_RawPolicy>::type{}, std::forward<decltype(__args)>(__args)...); \ + } + +template <class _SpecializedImpl, class _GenericImpl, class... _Args> +_LIBCPP_HIDE_FROM_ABI decltype(auto) +__pstl_frontend_dispatch(_SpecializedImpl __specialized_impl, _GenericImpl __generic_impl, _Args&&... __args) { + if constexpr (__is_callable<_SpecializedImpl, _Args...>::value) { + return __specialized_impl(std::forward<_Args>(__args)...); + } else { + return __generic_impl(std::forward<_Args>(__args)...); + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_FRONTEND_DISPATCH diff --git a/libcxx/include/__algorithm/pstl_generate.h b/libcxx/include/__algorithm/pstl_generate.h new file mode 100644 index 000000000000..e1ba0183dcba --- /dev/null +++ b/libcxx/include/__algorithm/pstl_generate.h @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_GENERATE_H +#define _LIBCPP___ALGORITHM_PSTL_GENERATE_H + +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_for_each.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class> +void __pstl_generate(); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Generator, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +generate(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Generator __gen) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_generate), + [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Generator __g_gen) { + std::for_each( + __policy, std::move(__g_first), std::move(__g_last), [&](__iter_reference<_ForwardIterator> __element) { + __element = __g_gen(); + }); + }, + std::move(__first), + std::move(__last), + std::move(__gen)); +} + +template <class> +void __pstl_generate_n(); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Size, + class _Generator, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +generate_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __n, _Generator __gen) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_generate_n), + [&__policy](_ForwardIterator __g_first, _Size __g_n, _Generator __g_gen) { + std::for_each_n(__policy, std::move(__g_first), __g_n, [&](__iter_reference<_ForwardIterator> __element) { + __element = __g_gen(); + }); + }, + std::move(__first), + __n, + std::move(__gen)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_GENERATE_H diff --git a/libcxx/include/__algorithm/pstl_is_partitioned.h b/libcxx/include/__algorithm/pstl_is_partitioned.h new file mode 100644 index 000000000000..6f6e9b2f4478 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_is_partitioned.h @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED +#define _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED + +#include <__algorithm/pstl_any_all_none_of.h> +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_find.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class> +void __pstl_is_partitioned(); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Predicate, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool +is_partitioned(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_is_partitioned), + [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { + __g_first = std::find_if_not(__policy, __g_first, __g_last, __g_pred); + if (__g_first == __g_last) + return true; + ++__g_first; + return std::none_of(__policy, __g_first, __g_last, __g_pred); + }, + std::move(__first), + std::move(__last), + std::move(__pred)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_IS_PARITTIONED diff --git a/libcxx/include/__algorithm/pstl_merge.h b/libcxx/include/__algorithm/pstl_merge.h new file mode 100644 index 000000000000..f10ac7674282 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_merge.h @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_MERGE_H +#define _LIBCPP___ALGORITHM_PSTL_MERGE_H + +#include <__algorithm/pstl_backend.h> +#include <__config> +#include <__functional/operations.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardOutIterator, + class _Comp = std::less<>, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator +merge(_ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardOutIterator __result, + _Comp __comp = {}) { + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_merge<_RawPolicy>( + _Backend{}, + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + std::move(__comp)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_MERGE_H diff --git a/libcxx/include/__algorithm/pstl_replace.h b/libcxx/include/__algorithm/pstl_replace.h new file mode 100644 index 000000000000..04ffaaba596a --- /dev/null +++ b/libcxx/include/__algorithm/pstl_replace.h @@ -0,0 +1,167 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_REPLACE_H +#define _LIBCPP___ALGORITHM_PSTL_REPLACE_H + +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_for_each.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__algorithm/pstl_transform.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class> +void __pstl_replace_if(); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Pred, + class _Tp, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +replace_if(_ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _Pred __pred, + const _Tp& __new_value) { + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_if), + [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred, const _Tp& __g_new_value) { + std::for_each(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __element) { + if (__g_pred(__element)) + __element = __g_new_value; + }); + }, + std::move(__first), + std::move(__last), + std::move(__pred), + __new_value); +} + +template <class> +void __pstl_replace(); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Tp, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +replace(_ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + const _Tp& __old_value, + const _Tp& __new_value) { + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace), + [&__policy]( + _ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_old_value, const _Tp& __g_new_value) { + std::replace_if( + __policy, + std::move(__g_first), + std::move(__g_last), + [&](__iter_reference<_ForwardIterator> __element) { return __element == __g_old_value; }, + __g_new_value); + }, + std::move(__first), + std::move(__last), + __old_value, + __new_value); +} + +template <class> +void __pstl_replace_copy_if(); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _ForwardOutIterator, + class _Pred, + class _Tp, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void replace_copy_if( + _ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + _Pred __pred, + const _Tp& __new_value) { + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy_if), + [&__policy](_ForwardIterator __g_first, + _ForwardIterator __g_last, + _ForwardOutIterator __g_result, + _Pred __g_pred, + const _Tp& __g_new_value) { + std::transform(__policy, __g_first, __g_last, __g_result, [&](__iter_reference<_ForwardIterator> __element) { + return __g_pred(__element) ? __g_new_value : __element; + }); + }, + std::move(__first), + std::move(__last), + std::move(__result), + std::move(__pred), + __new_value); +} + +template <class> +void __pstl_replace_copy(); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _ForwardOutIterator, + class _Tp, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void replace_copy( + _ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + const _Tp& __old_value, + const _Tp& __new_value) { + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_replace_copy), + [&__policy](_ForwardIterator __g_first, + _ForwardIterator __g_last, + _ForwardOutIterator __g_result, + const _Tp& __g_old_value, + const _Tp& __g_new_value) { + return std::replace_copy_if( + __policy, + std::move(__g_first), + std::move(__g_last), + std::move(__g_result), + [&](__iter_reference<_ForwardIterator> __element) { return __element == __g_old_value; }, + __g_new_value); + }, + std::move(__first), + std::move(__last), + std::move(__result), + __old_value, + __new_value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_REPLACE_H diff --git a/libcxx/include/__algorithm/pstl_sort.h b/libcxx/include/__algorithm/pstl_sort.h new file mode 100644 index 000000000000..81514953f24b --- /dev/null +++ b/libcxx/include/__algorithm/pstl_sort.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_SORT_H +#define _LIBCPP___ALGORITHM_PSTL_SORT_H + +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__algorithm/pstl_stable_sort.h> +#include <__config> +#include <__functional/operations.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class> +void __pstl_sort(); + +template <class _ExecutionPolicy, + class _RandomAccessIterator, + class _Comp, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { + std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_sort), + [&__policy](_RandomAccessIterator __g_first, _RandomAccessIterator __g_last, _Comp __g_comp) { + std::stable_sort(__policy, std::move(__g_first), std::move(__g_last), std::move(__g_comp)); + }, + std::move(__first), + std::move(__last), + std::move(__comp)); +} + +template <class _ExecutionPolicy, + class _RandomAccessIterator, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +sort(_ExecutionPolicy&& __policy, _RandomAccessIterator __first, _RandomAccessIterator __last) { + std::sort(std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), less{}); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_SORT_H diff --git a/libcxx/include/__algorithm/pstl_stable_sort.h b/libcxx/include/__algorithm/pstl_stable_sort.h new file mode 100644 index 000000000000..510ffd862980 --- /dev/null +++ b/libcxx/include/__algorithm/pstl_stable_sort.h @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H +#define _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H + +#include <__algorithm/pstl_backend.h> +#include <__config> +#include <__functional/operations.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _ExecutionPolicy, + class _RandomAccessIterator, + class _Comp = less<>, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI void +stable_sort(_ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp = {}) { + using _Backend = typename __select_backend<_RawPolicy>::type; + std::__pstl_stable_sort<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__comp)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_STABLE_SORT_H diff --git a/libcxx/include/__algorithm/pstl_transform.h b/libcxx/include/__algorithm/pstl_transform.h new file mode 100644 index 000000000000..27d95349fc8b --- /dev/null +++ b/libcxx/include/__algorithm/pstl_transform.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H +#define _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H + +#include <__algorithm/pstl_backend.h> +#include <__config> +#include <__iterator/cpp17_iterator_concepts.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/remove_cvref.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _ForwardOutIterator, + class _UnaryOperation, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform( + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardOutIterator __result, + _UnaryOperation __op) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first))); + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_transform<_RawPolicy>( + _Backend{}, std::move(__first), std::move(__last), std::move(__result), std::move(__op)); +} + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardOutIterator, + class _BinaryOperation, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform( + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardOutIterator __result, + _BinaryOperation __op) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first1, *__first2))); + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_transform<_RawPolicy>( + _Backend{}, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__result), std::move(__op)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___ALGORITHM_PSTL_TRANSFORM_H diff --git a/libcxx/include/__algorithm/push_heap.h b/libcxx/include/__algorithm/push_heap.h index 90684957744d..82b571e44bd4 100644 --- a/libcxx/include/__algorithm/push_heap.h +++ b/libcxx/include/__algorithm/push_heap.h @@ -14,13 +14,17 @@ #include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> @@ -68,10 +72,11 @@ void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com template <class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::push_heap(std::move(__first), std::move(__last), - __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); + std::push_heap(std::move(__first), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_PUSH_HEAP_H diff --git a/libcxx/include/__algorithm/ranges_adjacent_find.h b/libcxx/include/__algorithm/ranges_adjacent_find.h index d338d13e6eee..5f33192666ae 100644 --- a/libcxx/include/__algorithm/ranges_adjacent_find.h +++ b/libcxx/include/__algorithm/ranges_adjacent_find.h @@ -24,17 +24,16 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __adjacent_find { struct __fn { - template <class _Iter, class _Sent, class _Proj, class _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __adjacent_find_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __adjacent_find_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { if (__first == __last) return __first; @@ -47,32 +46,33 @@ struct __fn { return __i; } - template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, - class _Proj = identity, + template <forward_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_binary_predicate<projected<_Iter, _Proj>, projected<_Iter, _Proj>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __adjacent_find_impl(std::move(__first), std::move(__last), __pred, __proj); } template <forward_range _Range, class _Proj = identity, - indirect_binary_predicate<projected<iterator_t<_Range>, _Proj>, - projected<iterator_t<_Range>, _Proj>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const { + indirect_binary_predicate<projected<iterator_t<_Range>, _Proj>, projected<iterator_t<_Range>, _Proj>> + _Pred = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const { return __adjacent_find_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; } // namespace __adjacent_find inline namespace __cpo { - inline constexpr auto adjacent_find = __adjacent_find::__fn{}; +inline constexpr auto adjacent_find = __adjacent_find::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ADJACENT_FIND_H diff --git a/libcxx/include/__algorithm/ranges_all_of.h b/libcxx/include/__algorithm/ranges_all_of.h index e45c4e584379..39a2ae4de01e 100644 --- a/libcxx/include/__algorithm/ranges_all_of.h +++ b/libcxx/include/__algorithm/ranges_all_of.h @@ -22,17 +22,15 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __all_of { struct __fn { - template <class _Iter, class _Sent, class _Proj, class _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __all_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static bool __all_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (!std::invoke(__pred, std::invoke(__proj, *__first))) return false; @@ -40,29 +38,32 @@ struct __fn { return true; } - template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, + template <input_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __all_of_impl(std::move(__first), std::move(__last), __pred, __proj); } - template <input_range _Range, class _Proj = identity, + template <input_range _Range, + class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __all_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; } // namespace __all_of inline namespace __cpo { - inline constexpr auto all_of = __all_of::__fn{}; +inline constexpr auto all_of = __all_of::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ALL_OF_H diff --git a/libcxx/include/__algorithm/ranges_any_of.h b/libcxx/include/__algorithm/ranges_any_of.h index e7d1e723a70f..2ca8531102ea 100644 --- a/libcxx/include/__algorithm/ranges_any_of.h +++ b/libcxx/include/__algorithm/ranges_any_of.h @@ -22,17 +22,15 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __any_of { struct __fn { - template <class _Iter, class _Sent, class _Proj, class _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __any_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static bool __any_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) return true; @@ -40,29 +38,32 @@ struct __fn { return false; } - template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, + template <input_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __any_of_impl(std::move(__first), std::move(__last), __pred, __proj); } - template <input_range _Range, class _Proj = identity, + template <input_range _Range, + class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __any_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; } // namespace __any_of inline namespace __cpo { - inline constexpr auto any_of = __any_of::__fn{}; +inline constexpr auto any_of = __any_of::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ANY_OF_H diff --git a/libcxx/include/__algorithm/ranges_binary_search.h b/libcxx/include/__algorithm/ranges_binary_search.h index b2a8977652fb..22008e0f1bc8 100644 --- a/libcxx/include/__algorithm/ranges_binary_search.h +++ b/libcxx/include/__algorithm/ranges_binary_search.h @@ -24,40 +24,45 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __binary_search { struct __fn { - template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity, + template <forward_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Type, + class _Proj = identity, indirect_strict_weak_order<const _Type*, projected<_Iter, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); - return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first)); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); + return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); } - template <forward_range _Range, class _Type, class _Proj = identity, + template <forward_range _Range, + class _Type, + class _Proj = identity, indirect_strict_weak_order<const _Type*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); - return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first)); + auto __last = ranges::end(__r); + auto __ret = std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); + return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret)); } }; } // namespace __binary_search inline namespace __cpo { - inline constexpr auto binary_search = __binary_search::__fn{}; +inline constexpr auto binary_search = __binary_search::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_BINARY_SEARCH_H diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 09a97fc790ea..9613f7f37720 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -22,25 +22,20 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __clamp { struct __fn { - template <class _Type, - class _Proj = identity, + class _Proj = identity, indirect_strict_weak_order<projected<const _Type*, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - const _Type& operator()(const _Type& __value, - const _Type& __low, - const _Type& __high, - _Comp __comp = {}, - _Proj __proj = {}) const { - _LIBCPP_ASSERT(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), - "Bad bounds passed to std::ranges::clamp"); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Type& operator()( + const _Type& __value, const _Type& __low, const _Type& __high, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), + "Bad bounds passed to std::ranges::clamp"); if (std::invoke(__comp, std::invoke(__proj, __value), std::invoke(__proj, __low))) return __low; @@ -49,17 +44,16 @@ struct __fn { else return __value; } - }; } // namespace __clamp inline namespace __cpo { - inline constexpr auto clamp = __clamp::__fn{}; +inline constexpr auto clamp = __clamp::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_CLAMP_H diff --git a/libcxx/include/__algorithm/ranges_copy.h b/libcxx/include/__algorithm/ranges_copy.h index bb02c84efbdb..1c87f074e7ca 100644 --- a/libcxx/include/__algorithm/ranges_copy.h +++ b/libcxx/include/__algorithm/ranges_copy.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -36,19 +36,18 @@ using copy_result = in_out_result<_InIter, _OutIter>; namespace __copy { struct __fn { - template <input_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter> requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr copy_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { auto __ret = std::__copy<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } template <input_range _Range, weakly_incrementable _OutIter> requires indirectly_copyable<iterator_t<_Range>, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_result<borrowed_iterator_t<_Range>, _OutIter> operator()(_Range&& __r, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr copy_result<borrowed_iterator_t<_Range>, _OutIter> + operator()(_Range&& __r, _OutIter __result) const { auto __ret = std::__copy<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } @@ -56,12 +55,12 @@ struct __fn { } // namespace __copy inline namespace __cpo { - inline constexpr auto copy = __copy::__fn{}; +inline constexpr auto copy = __copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_COPY_H diff --git a/libcxx/include/__algorithm/ranges_copy_backward.h b/libcxx/include/__algorithm/ranges_copy_backward.h index f41af66f39fb..865e944d4384 100644 --- a/libcxx/include/__algorithm/ranges_copy_backward.h +++ b/libcxx/include/__algorithm/ranges_copy_backward.h @@ -23,30 +23,29 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { -template<class _Ip, class _Op> +template <class _Ip, class _Op> using copy_backward_result = in_out_result<_Ip, _Op>; namespace __copy_backward { struct __fn { - template <bidirectional_iterator _InIter1, sentinel_for<_InIter1> _Sent1, bidirectional_iterator _InIter2> requires indirectly_copyable<_InIter1, _InIter2> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_backward_result<_InIter1, _InIter2> operator()(_InIter1 __first, _Sent1 __last, _InIter2 __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr copy_backward_result<_InIter1, _InIter2> + operator()(_InIter1 __first, _Sent1 __last, _InIter2 __result) const { auto __ret = std::__copy_backward<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } template <bidirectional_range _Range, bidirectional_iterator _Iter> requires indirectly_copyable<iterator_t<_Range>, _Iter> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_backward_result<borrowed_iterator_t<_Range>, _Iter> operator()(_Range&& __r, _Iter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr copy_backward_result<borrowed_iterator_t<_Range>, _Iter> + operator()(_Range&& __r, _Iter __result) const { auto __ret = std::__copy_backward<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } @@ -54,12 +53,12 @@ struct __fn { } // namespace __copy_backward inline namespace __cpo { - inline constexpr auto copy_backward = __copy_backward::__fn{}; +inline constexpr auto copy_backward = __copy_backward::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_COPY_BACKWARD_H diff --git a/libcxx/include/__algorithm/ranges_copy_if.h b/libcxx/include/__algorithm/ranges_copy_if.h index dba41c3b3ab9..b77dbd37fcee 100644 --- a/libcxx/include/__algorithm/ranges_copy_if.h +++ b/libcxx/include/__algorithm/ranges_copy_if.h @@ -24,21 +24,19 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { -template<class _Ip, class _Op> +template <class _Ip, class _Op> using copy_if_result = in_out_result<_Ip, _Op>; namespace __copy_if { struct __fn { - template <class _InIter, class _Sent, class _OutIter, class _Proj, class _Pred> - _LIBCPP_HIDE_FROM_ABI static constexpr - copy_if_result <_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI static constexpr copy_if_result<_InIter, _OutIter> __copy_if_impl(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) { @@ -49,20 +47,23 @@ struct __fn { return {std::move(__first), std::move(__result)}; } - template <input_iterator _Iter, sentinel_for<_Iter> _Sent, weakly_incrementable _OutIter, class _Proj = identity, + template <input_iterator _Iter, + sentinel_for<_Iter> _Sent, + weakly_incrementable _OutIter, + class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> requires indirectly_copyable<_Iter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_if_result<_Iter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr copy_if_result<_Iter, _OutIter> operator()(_Iter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { return __copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); } - template <input_range _Range, weakly_incrementable _OutIter, class _Proj = identity, + template <input_range _Range, + weakly_incrementable _OutIter, + class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> requires indirectly_copyable<iterator_t<_Range>, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_if_result<borrowed_iterator_t<_Range>, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr copy_if_result<borrowed_iterator_t<_Range>, _OutIter> operator()(_Range&& __r, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { return __copy_if_impl(ranges::begin(__r), ranges::end(__r), std::move(__result), __pred, __proj); } @@ -70,12 +71,12 @@ struct __fn { } // namespace __copy_if inline namespace __cpo { - inline constexpr auto copy_if = __copy_if::__fn{}; +inline constexpr auto copy_if = __copy_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_COPY_IF_H diff --git a/libcxx/include/__algorithm/ranges_copy_n.h b/libcxx/include/__algorithm/ranges_copy_n.h index 04bb80b3ba1a..99e8eee14d0f 100644 --- a/libcxx/include/__algorithm/ranges_copy_n.h +++ b/libcxx/include/__algorithm/ranges_copy_n.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -36,10 +36,9 @@ using copy_n_result = in_out_result<_Ip, _Op>; namespace __copy_n { struct __fn { - template <class _InIter, class _DiffType, class _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr static - copy_n_result<_InIter, _OutIter> __go(_InIter __first, _DiffType __n, _OutIter __result) { + _LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter> + __go(_InIter __first, _DiffType __n, _OutIter __result) { while (__n != 0) { *__result = *__first; ++__first; @@ -50,27 +49,27 @@ struct __fn { } template <random_access_iterator _InIter, class _DiffType, random_access_iterator _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr static - copy_n_result<_InIter, _OutIter> __go(_InIter __first, _DiffType __n, _OutIter __result) { + _LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter> + __go(_InIter __first, _DiffType __n, _OutIter __result) { auto __ret = std::__copy<_RangeAlgPolicy>(__first, __first + __n, __result); return {__ret.first, __ret.second}; } template <input_iterator _Ip, weakly_incrementable _Op> requires indirectly_copyable<_Ip, _Op> - _LIBCPP_HIDE_FROM_ABI constexpr - copy_n_result<_Ip, _Op> operator()(_Ip __first, iter_difference_t<_Ip> __n, _Op __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr copy_n_result<_Ip, _Op> + operator()(_Ip __first, iter_difference_t<_Ip> __n, _Op __result) const { return __go(std::move(__first), __n, std::move(__result)); } }; } // namespace __copy_n inline namespace __cpo { - inline constexpr auto copy_n = __copy_n::__fn{}; +inline constexpr auto copy_n = __copy_n::__fn{}; } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/ranges_count.h b/libcxx/include/__algorithm/ranges_count.h index 527dd0620085..82f54567561f 100644 --- a/libcxx/include/__algorithm/ranges_count.h +++ b/libcxx/include/__algorithm/ranges_count.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -34,16 +34,16 @@ namespace __count { struct __fn { template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __e) { return __e == __value; }; return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj); } template <input_range _Range, class _Type, class _Proj = identity> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - range_difference_t<_Range> operator()(_Range&& __r, const _Type& __value, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> + operator()(_Range&& __r, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __e) { return __e == __value; }; return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } @@ -51,12 +51,12 @@ struct __fn { } // namespace __count inline namespace __cpo { - inline constexpr auto count = __count::__fn{}; +inline constexpr auto count = __count::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_COUNT_H diff --git a/libcxx/include/__algorithm/ranges_count_if.h b/libcxx/include/__algorithm/ranges_count_if.h index 931618b7b545..92f37d049e0c 100644 --- a/libcxx/include/__algorithm/ranges_count_if.h +++ b/libcxx/include/__algorithm/ranges_count_if.h @@ -25,15 +25,14 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template <class _Iter, class _Sent, class _Proj, class _Pred> -_LIBCPP_HIDE_FROM_ABI constexpr -iter_difference_t<_Iter> __count_if_impl(_Iter __first, _Sent __last, - _Pred& __pred, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> +__count_if_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { iter_difference_t<_Iter> __counter(0); for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) @@ -44,29 +43,32 @@ iter_difference_t<_Iter> __count_if_impl(_Iter __first, _Sent __last, namespace __count_if { struct __fn { - template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, + template <input_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Predicate> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, _Predicate __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, _Predicate __pred, _Proj __proj = {}) const { return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj); } - template <input_range _Range, class _Proj = identity, + template <input_range _Range, + class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Predicate> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - range_difference_t<_Range> operator()(_Range&& __r, _Predicate __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_Range> + operator()(_Range&& __r, _Predicate __pred, _Proj __proj = {}) const { return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } }; } // namespace __count_if inline namespace __cpo { - inline constexpr auto count_if = __count_if::__fn{}; +inline constexpr auto count_if = __count_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_COUNT_IF_H diff --git a/libcxx/include/__algorithm/ranges_equal.h b/libcxx/include/__algorithm/ranges_equal.h index 3c417f09de90..4cb1f7df1952 100644 --- a/libcxx/include/__algorithm/ranges_equal.h +++ b/libcxx/include/__algorithm/ranges_equal.h @@ -9,6 +9,8 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_EQUAL_H #define _LIBCPP___ALGORITHM_RANGES_EQUAL_H +#include <__algorithm/equal.h> +#include <__algorithm/unwrap_range.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -24,92 +26,79 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __equal { struct __fn { -private: - template <class _Iter1, class _Sent1, - class _Iter2, class _Sent2, - class _Pred, - class _Proj1, - class _Proj2> - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __equal_impl(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred& __pred, - _Proj1& __proj1, - _Proj2& __proj2) { - while (__first1 != __last1 && __first2 != __last2) { - if (!std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) - return false; - ++__first1; - ++__first2; - } - return __first1 == __last1 && __first2 == __last2; - } - -public: - - template <input_iterator _Iter1, sentinel_for<_Iter1> _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Pred = ranges::equal_to, + template <input_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + input_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { if constexpr (sized_sentinel_for<_Sent1, _Iter1> && sized_sentinel_for<_Sent2, _Iter2>) { if (__last1 - __first1 != __last2 - __first2) return false; } - return __equal_impl(std::move(__first1), std::move(__last1), - std::move(__first2), std::move(__last2), - __pred, - __proj1, - __proj2); + auto __unwrapped1 = std::__unwrap_range(std::move(__first1), std::move(__last1)); + auto __unwrapped2 = std::__unwrap_range(std::move(__first2), std::move(__last2)); + return std::__equal_impl( + std::move(__unwrapped1.first), + std::move(__unwrapped1.second), + std::move(__unwrapped2.first), + std::move(__unwrapped2.second), + __pred, + __proj1, + __proj2); } template <input_range _Range1, input_range _Range2, - class _Pred = ranges::equal_to, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range1&& __range1, - _Range2&& __range2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { if (ranges::distance(__range1) != ranges::distance(__range2)) return false; } - return __equal_impl(ranges::begin(__range1), ranges::end(__range1), - ranges::begin(__range2), ranges::end(__range2), - __pred, - __proj1, - __proj2); + auto __unwrapped1 = std::__unwrap_range(ranges::begin(__range1), ranges::end(__range1)); + auto __unwrapped2 = std::__unwrap_range(ranges::begin(__range2), ranges::end(__range2)); + return std::__equal_impl( + std::move(__unwrapped1.first), + std::move(__unwrapped1.second), + std::move(__unwrapped2.first), + std::move(__unwrapped2.second), + __pred, + __proj1, + __proj2); return false; } }; } // namespace __equal inline namespace __cpo { - inline constexpr auto equal = __equal::__fn{}; +inline constexpr auto equal = __equal::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_EQUAL_H diff --git a/libcxx/include/__algorithm/ranges_equal_range.h b/libcxx/include/__algorithm/ranges_equal_range.h index 94dc058e7bc1..ed78cf312c6b 100644 --- a/libcxx/include/__algorithm/ranges_equal_range.h +++ b/libcxx/include/__algorithm/ranges_equal_range.h @@ -30,7 +30,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -38,28 +38,25 @@ namespace ranges { namespace __equal_range { struct __fn { - template < - forward_iterator _Iter, - sentinel_for<_Iter> _Sent, - class _Tp, - class _Proj = identity, - indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> + template <forward_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Tp, + class _Proj = identity, + indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__equal_range<_RangeAlgPolicy>( - std::move(__first), std::move(__last), __value, __comp, __proj); + auto __ret = std::__equal_range<_RangeAlgPolicy>(std::move(__first), std::move(__last), __value, __comp, __proj); return {std::move(__ret.first), std::move(__ret.second)}; } - template < - forward_range _Range, - class _Tp, - class _Proj = identity, - indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> + template <forward_range _Range, + class _Tp, + class _Proj = identity, + indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__equal_range<_RangeAlgPolicy>( - ranges::begin(__range), ranges::end(__range), __value, __comp, __proj); + auto __ret = + std::__equal_range<_RangeAlgPolicy>(ranges::begin(__range), ranges::end(__range), __value, __comp, __proj); return {std::move(__ret.first), std::move(__ret.second)}; } }; @@ -67,12 +64,12 @@ struct __fn { } // namespace __equal_range inline namespace __cpo { - inline constexpr auto equal_range = __equal_range::__fn{}; +inline constexpr auto equal_range = __equal_range::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_EQUAL_RANGE_H diff --git a/libcxx/include/__algorithm/ranges_fill.h b/libcxx/include/__algorithm/ranges_fill.h index 6ebc2bd67d6b..88a892f5c278 100644 --- a/libcxx/include/__algorithm/ranges_fill.h +++ b/libcxx/include/__algorithm/ranges_fill.h @@ -20,7 +20,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -28,9 +28,8 @@ namespace ranges { namespace __fill { struct __fn { template <class _Type, output_iterator<const _Type&> _Iter, sentinel_for<_Iter> _Sent> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, const _Type& __value) const { - if constexpr(random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>) { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, const _Type& __value) const { + if constexpr (random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>) { return ranges::fill_n(__first, __last - __first, __value); } else { for (; __first != __last; ++__first) @@ -40,20 +39,19 @@ struct __fn { } template <class _Type, output_range<const _Type&> _Range> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, const _Type& __value) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, const _Type& __value) const { return (*this)(ranges::begin(__range), ranges::end(__range), __value); } }; } // namespace __fill inline namespace __cpo { - inline constexpr auto fill = __fill::__fn{}; +inline constexpr auto fill = __fill::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FILL_H diff --git a/libcxx/include/__algorithm/ranges_fill_n.h b/libcxx/include/__algorithm/ranges_fill_n.h index a2660e8b592a..dbd8ec27aef9 100644 --- a/libcxx/include/__algorithm/ranges_fill_n.h +++ b/libcxx/include/__algorithm/ranges_fill_n.h @@ -17,7 +17,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -25,8 +25,8 @@ namespace ranges { namespace __fill_n { struct __fn { template <class _Type, output_iterator<const _Type&> _Iter> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, iter_difference_t<_Iter> __n, const _Type& __value) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n, const _Type& __value) const { for (; __n != 0; --__n) { *__first = __value; ++__first; @@ -37,12 +37,12 @@ struct __fn { } // namespace __fill_n inline namespace __cpo { - inline constexpr auto fill_n = __fill_n::__fn{}; +inline constexpr auto fill_n = __fill_n::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FILL_N_H diff --git a/libcxx/include/__algorithm/ranges_find.h b/libcxx/include/__algorithm/ranges_find.h index 580c2a14c9ed..de870e381184 100644 --- a/libcxx/include/__algorithm/ranges_find.h +++ b/libcxx/include/__algorithm/ranges_find.h @@ -9,7 +9,9 @@ #ifndef _LIBCPP___ALGORITHM_RANGES_FIND_H #define _LIBCPP___ALGORITHM_RANGES_FIND_H +#include <__algorithm/find.h> #include <__algorithm/ranges_find_if.h> +#include <__algorithm/unwrap_range.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -26,38 +28,48 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __find { struct __fn { + template <class _Iter, class _Sent, class _Tp, class _Proj> + _LIBCPP_HIDE_FROM_ABI static constexpr _Iter + __find_unwrap(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) { + if constexpr (forward_iterator<_Iter>) { + auto [__first_un, __last_un] = std::__unwrap_range(__first, std::move(__last)); + return std::__rewrap_range<_Sent>( + std::move(__first), std::__find_impl(std::move(__first_un), std::move(__last_un), __value, __proj)); + } else { + return std::__find_impl(std::move(__first), std::move(__last), __value, __proj); + } + } + template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, class _Proj = identity> requires indirect_binary_predicate<ranges::equal_to, projected<_Ip, _Proj>, const _Tp*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Ip operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const { - auto __pred = [&](auto&& __e) { return std::forward<decltype(__e)>(__e) == __value; }; - return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const { + return __find_unwrap(std::move(__first), std::move(__last), __value, __proj); } template <input_range _Rp, class _Tp, class _Proj = identity> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Rp>, _Proj>, const _Tp*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Rp> operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const { - auto __pred = [&](auto&& __e) { return std::forward<decltype(__e)>(__e) == __value; }; - return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const { + return __find_unwrap(ranges::begin(__r), ranges::end(__r), __value, __proj); } }; } // namespace __find inline namespace __cpo { - inline constexpr auto find = __find::__fn{}; +inline constexpr auto find = __find::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FIND_H diff --git a/libcxx/include/__algorithm/ranges_find_end.h b/libcxx/include/__algorithm/ranges_find_end.h index ea36f4d4e6e7..2c57ad424bfd 100644 --- a/libcxx/include/__algorithm/ranges_find_end.h +++ b/libcxx/include/__algorithm/ranges_find_end.h @@ -27,25 +27,29 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __find_end { struct __fn { - template <forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Pred = ranges::equal_to, + template <forward_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + forward_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter1> operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __ret = std::__find_end_impl<_RangeAlgPolicy>( __first1, __last1, @@ -61,16 +65,12 @@ struct __fn { template <forward_range _Range1, forward_range _Range2, - class _Pred = ranges::equal_to, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range1> operator()(_Range1&& __range1, - _Range2&& __range2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __ret = std::__find_end_impl<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), @@ -87,12 +87,12 @@ struct __fn { } // namespace __find_end inline namespace __cpo { - inline constexpr auto find_end = __find_end::__fn{}; +inline constexpr auto find_end = __find_end::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FIND_END_H diff --git a/libcxx/include/__algorithm/ranges_find_first_of.h b/libcxx/include/__algorithm/ranges_find_first_of.h index 9d66e7511c0f..ec6d52c63250 100644 --- a/libcxx/include/__algorithm/ranges_find_first_of.h +++ b/libcxx/include/__algorithm/ranges_find_first_of.h @@ -24,21 +24,22 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __find_first_of { struct __fn { - template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter1 __find_first_of_impl(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred& __pred, - _Proj1& __proj1, - _Proj2& __proj2) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter1 __find_first_of_impl( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2) { for (; __first1 != __last1; ++__first1) { for (auto __j = __first2; __j != __last2; ++__j) { if (std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__j))) @@ -48,54 +49,53 @@ struct __fn { return __first1; } - template <input_iterator _Iter1, sentinel_for<_Iter1> _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Pred = ranges::equal_to, + template <input_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + forward_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter1 operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { - return __find_first_of_impl(std::move(__first1), std::move(__last1), - std::move(__first2), std::move(__last2), - __pred, - __proj1, - __proj2); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter1 operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __find_first_of_impl( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); } template <input_range _Range1, forward_range _Range2, - class _Pred = ranges::equal_to, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range1> operator()(_Range1&& __range1, - _Range2&& __range2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { - return __find_first_of_impl(ranges::begin(__range1), ranges::end(__range1), - ranges::begin(__range2), ranges::end(__range2), - __pred, - __proj1, - __proj2); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range1> operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __find_first_of_impl( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __pred, + __proj1, + __proj2); } - }; } // namespace __find_first_of inline namespace __cpo { - inline constexpr auto find_first_of = __find_first_of::__fn{}; +inline constexpr auto find_first_of = __find_first_of::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FIND_FIRST_OF_H diff --git a/libcxx/include/__algorithm/ranges_find_if.h b/libcxx/include/__algorithm/ranges_find_if.h index 45ce6e460d68..af54a5007ee2 100644 --- a/libcxx/include/__algorithm/ranges_find_if.h +++ b/libcxx/include/__algorithm/ranges_find_if.h @@ -24,15 +24,14 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template <class _Ip, class _Sp, class _Pred, class _Proj> -_LIBCPP_HIDE_FROM_ABI static constexpr -_Ip __find_if_impl(_Ip __first, _Sp __last, _Pred& __pred, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr _Ip __find_if_impl(_Ip __first, _Sp __last, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) break; @@ -42,30 +41,30 @@ _Ip __find_if_impl(_Ip __first, _Sp __last, _Pred& __pred, _Proj& __proj) { namespace __find_if { struct __fn { - - template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity, + template <input_iterator _Ip, + sentinel_for<_Ip> _Sp, + class _Proj = identity, indirect_unary_predicate<projected<_Ip, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj); } - template <input_range _Rp, class _Proj = identity, - indirect_unary_predicate<projected<iterator_t<_Rp>, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { + template <input_range _Rp, class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Rp>, _Proj>> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj); } }; } // namespace __find_if inline namespace __cpo { - inline constexpr auto find_if = __find_if::__fn{}; +inline constexpr auto find_if = __find_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FIND_IF_H diff --git a/libcxx/include/__algorithm/ranges_find_if_not.h b/libcxx/include/__algorithm/ranges_find_if_not.h index 3dd12132754b..6beade1462e0 100644 --- a/libcxx/include/__algorithm/ranges_find_if_not.h +++ b/libcxx/include/__algorithm/ranges_find_if_not.h @@ -26,25 +26,26 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __find_if_not { struct __fn { - template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity, + template <input_iterator _Ip, + sentinel_for<_Ip> _Sp, + class _Proj = identity, indirect_unary_predicate<projected<_Ip, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const { auto __pred2 = [&](auto&& __e) { return !std::invoke(__pred, std::forward<decltype(__e)>(__e)); }; return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred2, __proj); } - template <input_range _Rp, class _Proj = identity, - indirect_unary_predicate<projected<iterator_t<_Rp>, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { + template <input_range _Rp, class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Rp>, _Proj>> _Pred> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const { auto __pred2 = [&](auto&& __e) { return !std::invoke(__pred, std::forward<decltype(__e)>(__e)); }; return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred2, __proj); } @@ -52,12 +53,12 @@ struct __fn { } // namespace __find_if_not inline namespace __cpo { - inline constexpr auto find_if_not = __find_if_not::__fn{}; +inline constexpr auto find_if_not = __find_if_not::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FIND_IF_NOT_H diff --git a/libcxx/include/__algorithm/ranges_for_each.h b/libcxx/include/__algorithm/ranges_for_each.h index 0c70c05981a7..7878ed26709f 100644 --- a/libcxx/include/__algorithm/ranges_for_each.h +++ b/libcxx/include/__algorithm/ranges_for_each.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -37,42 +37,40 @@ namespace __for_each { struct __fn { private: template <class _Iter, class _Sent, class _Proj, class _Func> - _LIBCPP_HIDE_FROM_ABI constexpr static - for_each_result<_Iter, _Func> __for_each_impl(_Iter __first, _Sent __last, _Func& __func, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static for_each_result<_Iter, _Func> + __for_each_impl(_Iter __first, _Sent __last, _Func& __func, _Proj& __proj) { for (; __first != __last; ++__first) std::invoke(__func, std::invoke(__proj, *__first)); return {std::move(__first), std::move(__func)}; } public: - template <input_iterator _Iter, sentinel_for<_Iter> _Sent, + template <input_iterator _Iter, + sentinel_for<_Iter> _Sent, class _Proj = identity, indirectly_unary_invocable<projected<_Iter, _Proj>> _Func> - _LIBCPP_HIDE_FROM_ABI constexpr - for_each_result<_Iter, _Func> operator()(_Iter __first, _Sent __last, _Func __func, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr for_each_result<_Iter, _Func> + operator()(_Iter __first, _Sent __last, _Func __func, _Proj __proj = {}) const { return __for_each_impl(std::move(__first), std::move(__last), __func, __proj); } template <input_range _Range, class _Proj = identity, indirectly_unary_invocable<projected<iterator_t<_Range>, _Proj>> _Func> - _LIBCPP_HIDE_FROM_ABI constexpr - for_each_result<borrowed_iterator_t<_Range>, _Func> operator()(_Range&& __range, - _Func __func, - _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr for_each_result<borrowed_iterator_t<_Range>, _Func> + operator()(_Range&& __range, _Func __func, _Proj __proj = {}) const { return __for_each_impl(ranges::begin(__range), ranges::end(__range), __func, __proj); } - }; } // namespace __for_each inline namespace __cpo { - inline constexpr auto for_each = __for_each::__fn{}; +inline constexpr auto for_each = __for_each::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H diff --git a/libcxx/include/__algorithm/ranges_for_each_n.h b/libcxx/include/__algorithm/ranges_for_each_n.h index 261816aba436..53ccb9a6035a 100644 --- a/libcxx/include/__algorithm/ranges_for_each_n.h +++ b/libcxx/include/__algorithm/ranges_for_each_n.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,32 +35,25 @@ using for_each_n_result = in_fun_result<_Iter, _Func>; namespace __for_each_n { struct __fn { - - template <input_iterator _Iter, - class _Proj = identity, - indirectly_unary_invocable<projected<_Iter, _Proj>> _Func> - _LIBCPP_HIDE_FROM_ABI constexpr - for_each_n_result<_Iter, _Func> operator()(_Iter __first, - iter_difference_t<_Iter> __count, - _Func __func, - _Proj __proj = {}) const { + template <input_iterator _Iter, class _Proj = identity, indirectly_unary_invocable<projected<_Iter, _Proj>> _Func> + _LIBCPP_HIDE_FROM_ABI constexpr for_each_n_result<_Iter, _Func> + operator()(_Iter __first, iter_difference_t<_Iter> __count, _Func __func, _Proj __proj = {}) const { while (__count-- > 0) { std::invoke(__func, std::invoke(__proj, *__first)); ++__first; } return {std::move(__first), std::move(__func)}; } - }; } // namespace __for_each_n inline namespace __cpo { - inline constexpr auto for_each_n = __for_each_n::__fn{}; +inline constexpr auto for_each_n = __for_each_n::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H diff --git a/libcxx/include/__algorithm/ranges_generate.h b/libcxx/include/__algorithm/ranges_generate.h index ae486ae65395..3ff1e13c4220 100644 --- a/libcxx/include/__algorithm/ranges_generate.h +++ b/libcxx/include/__algorithm/ranges_generate.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -32,10 +32,8 @@ namespace ranges { namespace __generate { struct __fn { - template <class _OutIter, class _Sent, class _Func> - _LIBCPP_HIDE_FROM_ABI constexpr - static _OutIter __generate_fn_impl(_OutIter __first, _Sent __last, _Func& __gen) { + _LIBCPP_HIDE_FROM_ABI constexpr static _OutIter __generate_fn_impl(_OutIter __first, _Sent __last, _Func& __gen) { for (; __first != __last; ++__first) { *__first = __gen(); } @@ -44,30 +42,27 @@ struct __fn { } template <input_or_output_iterator _OutIter, sentinel_for<_OutIter> _Sent, copy_constructible _Func> - requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> - _LIBCPP_HIDE_FROM_ABI constexpr - _OutIter operator()(_OutIter __first, _Sent __last, _Func __gen) const { + requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> + _LIBCPP_HIDE_FROM_ABI constexpr _OutIter operator()(_OutIter __first, _Sent __last, _Func __gen) const { return __generate_fn_impl(std::move(__first), std::move(__last), __gen); } template <class _Range, copy_constructible _Func> - requires invocable<_Func&> && output_range<_Range, invoke_result_t<_Func&>> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Func __gen) const { + requires invocable<_Func&> && output_range<_Range, invoke_result_t<_Func&>> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, _Func __gen) const { return __generate_fn_impl(ranges::begin(__range), ranges::end(__range), __gen); } - }; } // namespace __generate inline namespace __cpo { - inline constexpr auto generate = __generate::__fn{}; +inline constexpr auto generate = __generate::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_GENERATE_H diff --git a/libcxx/include/__algorithm/ranges_generate_n.h b/libcxx/include/__algorithm/ranges_generate_n.h index e625e3a97428..c025c621a191 100644 --- a/libcxx/include/__algorithm/ranges_generate_n.h +++ b/libcxx/include/__algorithm/ranges_generate_n.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -33,11 +33,10 @@ namespace ranges { namespace __generate_n { struct __fn { - template <input_or_output_iterator _OutIter, copy_constructible _Func> - requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> - _LIBCPP_HIDE_FROM_ABI constexpr - _OutIter operator()(_OutIter __first, iter_difference_t<_OutIter> __n, _Func __gen) const { + requires invocable<_Func&> && indirectly_writable<_OutIter, invoke_result_t<_Func&>> + _LIBCPP_HIDE_FROM_ABI constexpr _OutIter + operator()(_OutIter __first, iter_difference_t<_OutIter> __n, _Func __gen) const { for (; __n > 0; --__n) { *__first = __gen(); ++__first; @@ -45,18 +44,17 @@ struct __fn { return __first; } - }; } // namespace __generate_n inline namespace __cpo { - inline constexpr auto generate_n = __generate_n::__fn{}; +inline constexpr auto generate_n = __generate_n::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H diff --git a/libcxx/include/__algorithm/ranges_includes.h b/libcxx/include/__algorithm/ranges_includes.h index 8438117cfa80..aa35080c8cfd 100644 --- a/libcxx/include/__algorithm/ranges_includes.h +++ b/libcxx/include/__algorithm/ranges_includes.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,14 +35,13 @@ namespace ranges { namespace __includes { struct __fn { - template < - input_iterator _Iter1, - sentinel_for<_Iter1> _Sent1, - input_iterator _Iter2, - sentinel_for<_Iter2> _Sent2, - class _Proj1 = identity, - class _Proj2 = identity, - indirect_strict_weak_order<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Comp = ranges::less> + template <input_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + input_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_strict_weak_order<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Comp = ranges::less> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, @@ -61,13 +60,12 @@ struct __fn { std::move(__proj2)); } - template < - input_range _Range1, - input_range _Range2, - class _Proj1 = identity, - class _Proj2 = identity, - indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>> - _Comp = ranges::less> + template <input_range _Range1, + input_range _Range2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>> + _Comp = ranges::less> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return std::__includes( @@ -84,12 +82,12 @@ struct __fn { } // namespace __includes inline namespace __cpo { - inline constexpr auto includes = __includes::__fn{}; +inline constexpr auto includes = __includes::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_INCLUDES_H diff --git a/libcxx/include/__algorithm/ranges_inplace_merge.h b/libcxx/include/__algorithm/ranges_inplace_merge.h index 88171a65c8e9..86001b003d5c 100644 --- a/libcxx/include/__algorithm/ranges_inplace_merge.h +++ b/libcxx/include/__algorithm/ranges_inplace_merge.h @@ -31,55 +31,49 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __inplace_merge { - struct __fn { - template <class _Iter, class _Sent, class _Comp, class _Proj> - _LIBCPP_HIDE_FROM_ABI static constexpr auto - __inplace_merge_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp&& __comp, _Proj&& __proj) { - auto __last_iter = ranges::next(__middle, __last); - std::__inplace_merge<_RangeAlgPolicy>( - std::move(__first), std::move(__middle), __last_iter, std::__make_projected(__comp, __proj)); - return __last_iter; - } +struct __fn { + template <class _Iter, class _Sent, class _Comp, class _Proj> + _LIBCPP_HIDE_FROM_ABI static constexpr auto + __inplace_merge_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp&& __comp, _Proj&& __proj) { + auto __last_iter = ranges::next(__middle, __last); + std::__inplace_merge<_RangeAlgPolicy>( + std::move(__first), std::move(__middle), __last_iter, std::__make_projected(__comp, __proj)); + return __last_iter; + } - template < - bidirectional_iterator _Iter, - sentinel_for<_Iter> _Sent, - class _Comp = ranges::less, - class _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI _Iter - operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - return __inplace_merge_impl( - std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj)); - } + template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + return __inplace_merge_impl( + std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj)); + } - template <bidirectional_range _Range, class _Comp = ranges::less, class _Proj = identity> - requires sortable< - iterator_t<_Range>, - _Comp, - _Proj> _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> - operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const { - return __inplace_merge_impl( - ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj)); - } - }; + template <bidirectional_range _Range, class _Comp = ranges::less, class _Proj = identity> + requires sortable<iterator_t<_Range>, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> + operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const { + return __inplace_merge_impl( + ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj)); + } +}; } // namespace __inplace_merge inline namespace __cpo { - inline constexpr auto inplace_merge = __inplace_merge::__fn{}; +inline constexpr auto inplace_merge = __inplace_merge::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_INPLACE_MERGE_H diff --git a/libcxx/include/__algorithm/ranges_is_heap.h b/libcxx/include/__algorithm/ranges_is_heap.h index a16c075b0763..f298c347b747 100644 --- a/libcxx/include/__algorithm/ranges_is_heap.h +++ b/libcxx/include/__algorithm/ranges_is_heap.h @@ -26,7 +26,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -34,28 +34,30 @@ namespace ranges { namespace __is_heap { struct __fn { - template <class _Iter, class _Sent, class _Proj, class _Comp> - _LIBCPP_HIDE_FROM_ABI constexpr - static bool __is_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { - auto __last_iter = ranges::next(__first, __last); + _LIBCPP_HIDE_FROM_ABI constexpr static bool + __is_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = std::__make_projected(__comp, __proj); auto __result = std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp); return __result == __last; } - template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, + template <random_access_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } - template <random_access_range _Range, class _Proj = identity, + template <random_access_range _Range, + class _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } }; @@ -63,12 +65,12 @@ struct __fn { } // namespace __is_heap inline namespace __cpo { - inline constexpr auto is_heap = __is_heap::__fn{}; +inline constexpr auto is_heap = __is_heap::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_IS_HEAP_H diff --git a/libcxx/include/__algorithm/ranges_is_heap_until.h b/libcxx/include/__algorithm/ranges_is_heap_until.h index 8c8dac5bc909..73f13fb50440 100644 --- a/libcxx/include/__algorithm/ranges_is_heap_until.h +++ b/libcxx/include/__algorithm/ranges_is_heap_until.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,41 +35,42 @@ namespace ranges { namespace __is_heap_until { struct __fn { - template <class _Iter, class _Sent, class _Proj, class _Comp> - _LIBCPP_HIDE_FROM_ABI constexpr - static _Iter __is_heap_until_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { - auto __last_iter = ranges::next(__first, __last); + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __is_heap_until_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = std::__make_projected(__comp, __proj); return std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp); } - template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, + template <random_access_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_until_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } - template <random_access_range _Range, class _Proj = identity, + template <random_access_range _Range, + class _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return __is_heap_until_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } - }; } // namespace __is_heap_until inline namespace __cpo { - inline constexpr auto is_heap_until = __is_heap_until::__fn{}; +inline constexpr auto is_heap_until = __is_heap_until::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_IS_HEAP_UNTIL_H diff --git a/libcxx/include/__algorithm/ranges_is_partitioned.h b/libcxx/include/__algorithm/ranges_is_partitioned.h index b903953d6165..76db870efc70 100644 --- a/libcxx/include/__algorithm/ranges_is_partitioned.h +++ b/libcxx/include/__algorithm/ranges_is_partitioned.h @@ -23,17 +23,16 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __is_partitioned { struct __fn { - template <class _Iter, class _Sent, class _Proj, class _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __is_parititioned_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static bool + __is_partitioned_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (!std::invoke(__pred, std::invoke(__proj, *__first))) break; @@ -51,31 +50,32 @@ struct __fn { return true; } - template <input_iterator _Iter, sentinel_for<_Iter> _Sent, + template <input_iterator _Iter, + sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { - return __is_parititioned_impl(std::move(__first), std::move(__last), __pred, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + return __is_partitioned_impl(std::move(__first), std::move(__last), __pred, __proj); } template <input_range _Range, class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { - return __is_parititioned_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + return __is_partitioned_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; } // namespace __is_partitioned inline namespace __cpo { - inline constexpr auto is_partitioned = __is_partitioned::__fn{}; +inline constexpr auto is_partitioned = __is_partitioned::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_IS_PARTITIONED_H diff --git a/libcxx/include/__algorithm/ranges_is_permutation.h b/libcxx/include/__algorithm/ranges_is_permutation.h index b617500ea0d8..2b99839bc66f 100644 --- a/libcxx/include/__algorithm/ranges_is_permutation.h +++ b/libcxx/include/__algorithm/ranges_is_permutation.h @@ -25,65 +25,78 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __is_permutation { struct __fn { - - template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, - class _Proj1, class _Proj2, class _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __is_permutation_func_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Proj1, class _Proj2, class _Pred> + _LIBCPP_HIDE_FROM_ABI constexpr static bool __is_permutation_func_impl( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred& __pred, + _Proj1& __proj1, + _Proj2& __proj2) { return std::__is_permutation<_RangeAlgPolicy>( - std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), - __pred, __proj1, __proj2); + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); } - template <forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Proj1 = identity, - class _Proj2 = identity, - indirect_equivalence_relation<projected<_Iter1, _Proj1>, - projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + template < + forward_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + forward_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_equivalence_relation<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { return __is_permutation_func_impl( - std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), - __pred, __proj1, __proj2); + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); } template <forward_range _Range1, forward_range _Range2, - class _Proj1 = identity, - class _Proj2 = identity, - indirect_equivalence_relation<projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>> _Pred = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range1&& __range1, _Range2&& __range2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + class _Proj1 = identity, + class _Proj2 = identity, + indirect_equivalence_relation<projected<iterator_t<_Range1>, _Proj1>, + projected<iterator_t<_Range2>, _Proj2>> _Pred = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { if constexpr (sized_range<_Range1> && sized_range<_Range2>) { if (ranges::distance(__range1) != ranges::distance(__range2)) return false; } return __is_permutation_func_impl( - ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), ranges::end(__range2), - __pred, __proj1, __proj2); + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __pred, + __proj1, + __proj2); } }; } // namespace __is_permutation inline namespace __cpo { - inline constexpr auto is_permutation = __is_permutation::__fn{}; +inline constexpr auto is_permutation = __is_permutation::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H diff --git a/libcxx/include/__algorithm/ranges_is_sorted.h b/libcxx/include/__algorithm/ranges_is_sorted.h index ce3032ff226e..3eb2c768d66a 100644 --- a/libcxx/include/__algorithm/ranges_is_sorted.h +++ b/libcxx/include/__algorithm/ranges_is_sorted.h @@ -23,26 +23,27 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __is_sorted { struct __fn { - template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, - class _Proj = identity, + template <forward_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(std::move(__first), __last, __comp, __proj) == __last; } template <forward_range _Range, - class _Proj = identity, + class _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { auto __last = ranges::end(__range); return ranges::__is_sorted_until_impl(ranges::begin(__range), __last, __comp, __proj) == __last; } @@ -50,12 +51,12 @@ struct __fn { } // namespace __is_sorted inline namespace __cpo { - inline constexpr auto is_sorted = __is_sorted::__fn{}; +inline constexpr auto is_sorted = __is_sorted::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP__ALGORITHM_RANGES_IS_SORTED_H diff --git a/libcxx/include/__algorithm/ranges_is_sorted_until.h b/libcxx/include/__algorithm/ranges_is_sorted_until.h index 17fc42e97fd3..19e9875d2757 100644 --- a/libcxx/include/__algorithm/ranges_is_sorted_until.h +++ b/libcxx/include/__algorithm/ranges_is_sorted_until.h @@ -24,15 +24,15 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template <class _Iter, class _Sent, class _Proj, class _Comp> -_LIBCPP_HIDE_FROM_ABI constexpr -_Iter __is_sorted_until_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr _Iter +__is_sorted_until_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { if (__first == __last) return __first; auto __i = __first; @@ -46,31 +46,32 @@ _Iter __is_sorted_until_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& namespace __is_sorted_until { struct __fn { - template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, - class _Proj = identity, + template <forward_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(std::move(__first), std::move(__last), __comp, __proj); } template <forward_range _Range, - class _Proj = identity, + class _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__is_sorted_until_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj); } }; } // namespace __is_sorted_until inline namespace __cpo { - inline constexpr auto is_sorted_until = __is_sorted_until::__fn{}; +inline constexpr auto is_sorted_until = __is_sorted_until::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP__ALGORITHM_RANGES_IS_SORTED_UNTIL_H diff --git a/libcxx/include/__algorithm/ranges_iterator_concept.h b/libcxx/include/__algorithm/ranges_iterator_concept.h index 3ac6b317031a..9a9203040336 100644 --- a/libcxx/include/__algorithm/ranges_iterator_concept.h +++ b/libcxx/include/__algorithm/ranges_iterator_concept.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -46,6 +46,6 @@ using __iterator_concept = decltype(__get_iterator_concept<_Iter>()); } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ITERATOR_CONCEPT_H diff --git a/libcxx/include/__algorithm/ranges_lexicographical_compare.h b/libcxx/include/__algorithm/ranges_lexicographical_compare.h index 2972e327169d..5b843dfd7b31 100644 --- a/libcxx/include/__algorithm/ranges_lexicographical_compare.h +++ b/libcxx/include/__algorithm/ranges_lexicographical_compare.h @@ -23,24 +23,24 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __lexicographical_compare { struct __fn { - template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Proj1, class _Proj2, class _Comp> - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __lexicographical_compare_impl(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Comp& __comp, - _Proj1& __proj1, - _Proj2& __proj2) { + _LIBCPP_HIDE_FROM_ABI constexpr static bool __lexicographical_compare_impl( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Comp& __comp, + _Proj1& __proj1, + _Proj2& __proj2) { while (__first2 != __last2) { - if (__first1 == __last1 - || std::invoke(__comp, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) + if (__first1 == __last1 || std::invoke(__comp, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) return true; if (std::invoke(__comp, std::invoke(__proj2, *__first2), std::invoke(__proj1, *__first1))) return false; @@ -50,49 +50,52 @@ struct __fn { return false; } - template <input_iterator _Iter1, sentinel_for<_Iter1> _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Proj1 = identity, - class _Proj2 = identity, + template <input_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + input_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, indirect_strict_weak_order<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { - return __lexicographical_compare_impl(std::move(__first1), std::move(__last1), - std::move(__first2), std::move(__last2), - __comp, - __proj1, - __proj2); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __lexicographical_compare_impl( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __comp, __proj1, __proj2); } template <input_range _Range1, input_range _Range2, class _Proj1 = identity, class _Proj2 = identity, - indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>, - projected<iterator_t<_Range2>, _Proj2>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - return __lexicographical_compare_impl(ranges::begin(__range1), ranges::end(__range1), - ranges::begin(__range2), ranges::end(__range2), - __comp, - __proj1, - __proj2); + indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>> + _Comp = ranges::less> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __lexicographical_compare_impl( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __comp, + __proj1, + __proj2); } - }; } // namespace __lexicographical_compare inline namespace __cpo { - inline constexpr auto lexicographical_compare = __lexicographical_compare::__fn{}; +inline constexpr auto lexicographical_compare = __lexicographical_compare::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_LEXICOGRAPHICAL_COMPARE_H diff --git a/libcxx/include/__algorithm/ranges_lower_bound.h b/libcxx/include/__algorithm/ranges_lower_bound.h index 78cbb6d4fb24..58b3f815b96a 100644 --- a/libcxx/include/__algorithm/ranges_lower_bound.h +++ b/libcxx/include/__algorithm/ranges_lower_bound.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,32 +35,34 @@ namespace ranges { namespace __lower_bound { struct __fn { - template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity, + template <forward_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Type, + class _Proj = identity, indirect_strict_weak_order<const _Type*, projected<_Iter, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { - return std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + return std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj); } - template <forward_range _Range, class _Type, class _Proj = identity, + template <forward_range _Range, + class _Type, + class _Proj = identity, indirect_strict_weak_order<const _Type*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, - const _Type& __value, - _Comp __comp = {}, - _Proj __proj = {}) const { - return std::__lower_bound_impl<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __comp, __proj); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + return std::__lower_bound<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), __value, __comp, __proj); } }; } // namespace __lower_bound inline namespace __cpo { - inline constexpr auto lower_bound = __lower_bound::__fn{}; +inline constexpr auto lower_bound = __lower_bound::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_LOWER_BOUND_H diff --git a/libcxx/include/__algorithm/ranges_make_heap.h b/libcxx/include/__algorithm/ranges_make_heap.h index f25c7ab58888..f17eabff43d2 100644 --- a/libcxx/include/__algorithm/ranges_make_heap.h +++ b/libcxx/include/__algorithm/ranges_make_heap.h @@ -32,7 +32,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,8 +41,8 @@ namespace __make_heap { struct __fn { template <class _Iter, class _Sent, class _Comp, class _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __make_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __make_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = std::__make_projected(__comp, __proj); @@ -53,15 +53,15 @@ struct __fn { template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __make_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity> requires sortable<iterator_t<_Range>, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __make_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -69,12 +69,12 @@ struct __fn { } // namespace __make_heap inline namespace __cpo { - inline constexpr auto make_heap = __make_heap::__fn{}; +inline constexpr auto make_heap = __make_heap::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MAKE_HEAP_H diff --git a/libcxx/include/__algorithm/ranges_max.h b/libcxx/include/__algorithm/ranges_max.h index 55aef997698c..5cc418d3393c 100644 --- a/libcxx/include/__algorithm/ranges_max.h +++ b/libcxx/include/__algorithm/ranges_max.h @@ -20,6 +20,7 @@ #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> +#include <__type_traits/is_trivially_copyable.h> #include <__utility/move.h> #include <initializer_list> @@ -27,44 +28,50 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_PUSH_MACROS -#include <__undef_macros> +# include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __max { struct __fn { - template <class _Tp, class _Proj = identity, + template <class _Tp, + class _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& + operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, + _LIBCPP_LIFETIMEBOUND const _Tp& __b, + _Comp __comp = {}, + _Proj __proj = {}) const { return std::invoke(__comp, std::invoke(__proj, __a), std::invoke(__proj, __b)) ? __b : __a; } - template <copyable _Tp, class _Proj = identity, + template <copyable _Tp, + class _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { - _LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list must contain at least one element"); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp + operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT_UNCATEGORIZED(__il.begin() != __il.end(), "initializer_list must contain at least one element"); auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp_lhs_rhs_swapped, __proj); } - template <input_range _Rp, class _Proj = identity, + template <input_range _Rp, + class _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<_Rp>, range_value_t<_Rp>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> + operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); + auto __last = ranges::end(__r); - _LIBCPP_ASSERT(__first != __last, "range must contain at least one element"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __last, "range must contain at least one element"); - if constexpr (forward_range<_Rp>) { + if constexpr (forward_range<_Rp> && !__is_cheap_to_copy<range_value_t<_Rp>>) { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; return *ranges::__min_element_impl(std::move(__first), std::move(__last), __comp_lhs_rhs_swapped, __proj); } else { @@ -80,7 +87,7 @@ struct __fn { } // namespace __max inline namespace __cpo { - inline constexpr auto max = __max::__fn{}; +inline constexpr auto max = __max::__fn{}; } // namespace __cpo } // namespace ranges @@ -88,6 +95,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP_STD_VER > 17 && +#endif // _LIBCPP_STD_VER >= 20 && #endif // _LIBCPP___ALGORITHM_RANGES_MAX_H diff --git a/libcxx/include/__algorithm/ranges_max_element.h b/libcxx/include/__algorithm/ranges_max_element.h index 490f32075a4c..2d92661c8109 100644 --- a/libcxx/include/__algorithm/ranges_max_element.h +++ b/libcxx/include/__algorithm/ranges_max_element.h @@ -24,25 +24,28 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __max_element { struct __fn { - template <forward_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity, + template <forward_iterator _Ip, + sentinel_for<_Ip> _Sp, + class _Proj = identity, indirect_strict_weak_order<projected<_Ip, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; return ranges::__min_element_impl(__first, __last, __comp_lhs_rhs_swapped, __proj); } - template <forward_range _Rp, class _Proj = identity, + template <forward_range _Rp, + class _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); }; return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj); } @@ -50,12 +53,12 @@ struct __fn { } // namespace __max_element inline namespace __cpo { - inline constexpr auto max_element = __max_element::__fn{}; +inline constexpr auto max_element = __max_element::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MAX_ELEMENT_H diff --git a/libcxx/include/__algorithm/ranges_merge.h b/libcxx/include/__algorithm/ranges_merge.h index b36a05abc41e..7f49154ec922 100644 --- a/libcxx/include/__algorithm/ranges_merge.h +++ b/libcxx/include/__algorithm/ranges_merge.h @@ -20,14 +20,14 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> +#include <__type_traits/remove_cvref.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -38,25 +38,25 @@ using merge_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; namespace __merge { -template < - class _InIter1, - class _Sent1, - class _InIter2, - class _Sent2, - class _OutIter, - class _Comp, - class _Proj1, - class _Proj2> -_LIBCPP_HIDE_FROM_ABI constexpr merge_result<__remove_cvref_t<_InIter1>, __remove_cvref_t<_InIter2>, __remove_cvref_t<_OutIter>> -__merge_impl( - _InIter1&& __first1, - _Sent1&& __last1, - _InIter2&& __first2, - _Sent2&& __last2, - _OutIter&& __result, - _Comp&& __comp, - _Proj1&& __proj1, - _Proj2&& __proj2) { +template < class _InIter1, + class _Sent1, + class _InIter2, + class _Sent2, + class _OutIter, + class _Comp, + class _Proj1, + class _Proj2> +_LIBCPP_HIDE_FROM_ABI constexpr merge_result<__remove_cvref_t<_InIter1>, + __remove_cvref_t<_InIter2>, + __remove_cvref_t<_OutIter>> +__merge_impl(_InIter1&& __first1, + _Sent1&& __last1, + _InIter2&& __first2, + _Sent2&& __last2, + _OutIter&& __result, + _Comp&& __comp, + _Proj1&& __proj1, + _Proj2&& __proj2) { for (; __first1 != __last1 && __first2 != __last2; ++__result) { if (std::invoke(__comp, std::invoke(__proj2, *__first2), std::invoke(__proj1, *__first1))) { *__result = *__first2; @@ -72,15 +72,14 @@ __merge_impl( } struct __fn { - template < - input_iterator _InIter1, - sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, - sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> + template <input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr merge_result<_InIter1, _InIter2, _OutIter> operator()( _InIter1 __first1, @@ -94,28 +93,20 @@ struct __fn { return __merge::__merge_impl(__first1, __last1, __first2, __last2, __result, __comp, __proj1, __proj2); } - template < - input_range _Range1, - input_range _Range2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> - requires mergeable< - iterator_t<_Range1>, - iterator_t<_Range2>, - _OutIter, - _Comp, - _Proj1, - _Proj2> + template <input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr merge_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>, _OutIter> - operator()( - _Range1&& __range1, - _Range2&& __range2, - _OutIter __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { return __merge::__merge_impl( ranges::begin(__range1), ranges::end(__range1), @@ -131,12 +122,12 @@ struct __fn { } // namespace __merge inline namespace __cpo { - inline constexpr auto merge = __merge::__fn{}; +inline constexpr auto merge = __merge::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MERGE_H diff --git a/libcxx/include/__algorithm/ranges_min.h b/libcxx/include/__algorithm/ranges_min.h index 0e31f57fb8dd..be15b4536734 100644 --- a/libcxx/include/__algorithm/ranges_min.h +++ b/libcxx/include/__algorithm/ranges_min.h @@ -20,48 +20,53 @@ #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> +#include <__type_traits/is_trivially_copyable.h> #include <initializer_list> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_PUSH_MACROS -#include <__undef_macros> +# include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __min { struct __fn { - template <class _Tp, class _Proj = identity, + template <class _Tp, + class _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& + operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, + _LIBCPP_LIFETIMEBOUND const _Tp& __b, + _Comp __comp = {}, + _Proj __proj = {}) const { return std::invoke(__comp, std::invoke(__proj, __b), std::invoke(__proj, __a)) ? __b : __a; } - template <copyable _Tp, class _Proj = identity, + template <copyable _Tp, + class _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { - _LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list must contain at least one element"); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp + operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT_UNCATEGORIZED(__il.begin() != __il.end(), "initializer_list must contain at least one element"); return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp, __proj); } - template <input_range _Rp, class _Proj = identity, + template <input_range _Rp, + class _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<_Rp>, range_value_t<_Rp>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> + operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - - _LIBCPP_ASSERT(__first != __last, "range must contain at least one element"); - - if constexpr (forward_range<_Rp>) { + auto __last = ranges::end(__r); + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __last, "range must contain at least one element"); + if constexpr (forward_range<_Rp> && !__is_cheap_to_copy<range_value_t<_Rp>>) { return *ranges::__min_element_impl(__first, __last, __comp, __proj); } else { range_value_t<_Rp> __result = *__first; @@ -76,7 +81,7 @@ struct __fn { } // namespace __min inline namespace __cpo { - inline constexpr auto min = __min::__fn{}; +inline constexpr auto min = __min::__fn{}; } // namespace __cpo } // namespace ranges @@ -84,6 +89,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP_STD_VER > 17 && +#endif // _LIBCPP_STD_VER >= 20 && #endif // _LIBCPP___ALGORITHM_RANGES_MIN_H diff --git a/libcxx/include/__algorithm/ranges_min_element.h b/libcxx/include/__algorithm/ranges_min_element.h index 1751874d03bb..07826a0e6b81 100644 --- a/libcxx/include/__algorithm/ranges_min_element.h +++ b/libcxx/include/__algorithm/ranges_min_element.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -32,8 +32,7 @@ namespace ranges { // TODO(ranges): `ranges::min_element` can now simply delegate to `std::__min_element`. template <class _Ip, class _Sp, class _Proj, class _Comp> -_LIBCPP_HIDE_FROM_ABI static constexpr -_Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr _Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) { if (__first == __last) return __first; @@ -46,29 +45,32 @@ _Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) { namespace __min_element { struct __fn { - template <forward_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity, + template <forward_iterator _Ip, + sentinel_for<_Ip> _Sp, + class _Proj = identity, indirect_strict_weak_order<projected<_Ip, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Ip + operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__min_element_impl(__first, __last, __comp, __proj); } - template <forward_range _Rp, class _Proj = identity, + template <forward_range _Rp, + class _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp> + operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; } // namespace __min_element inline namespace __cpo { - inline constexpr auto min_element = __min_element::__fn{}; +inline constexpr auto min_element = __min_element::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MIN_ELEMENT_H diff --git a/libcxx/include/__algorithm/ranges_minmax.h b/libcxx/include/__algorithm/ranges_minmax.h index f82e00551e47..a5b5cf9bd0ab 100644 --- a/libcxx/include/__algorithm/ranges_minmax.h +++ b/libcxx/include/__algorithm/ranges_minmax.h @@ -13,14 +13,18 @@ #include <__algorithm/minmax_element.h> #include <__assert> #include <__concepts/copyable.h> +#include <__concepts/same_as.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> +#include <__iterator/next.h> #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -30,10 +34,10 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_PUSH_MACROS -#include <__undef_macros> +# include <__undef_macros> _LIBCPP_BEGIN_NAMESPACE_STD @@ -43,46 +47,67 @@ using minmax_result = min_max_result<_T1>; namespace __minmax { struct __fn { - template <class _Type, class _Proj = identity, + template <class _Type, + class _Proj = identity, indirect_strict_weak_order<projected<const _Type*, _Proj>> _Comp = ranges::less> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<const _Type&> - operator()(const _Type& __a, const _Type& __b, _Comp __comp = {}, _Proj __proj = {}) const { + operator()(_LIBCPP_LIFETIMEBOUND const _Type& __a, + _LIBCPP_LIFETIMEBOUND const _Type& __b, + _Comp __comp = {}, + _Proj __proj = {}) const { if (std::invoke(__comp, std::invoke(__proj, __b), std::invoke(__proj, __a))) return {__b, __a}; return {__a, __b}; } - template <copyable _Type, class _Proj = identity, + template <copyable _Type, + class _Proj = identity, indirect_strict_weak_order<projected<const _Type*, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - ranges::minmax_result<_Type> operator()(initializer_list<_Type> __il, _Comp __comp = {}, _Proj __proj = {}) const { - _LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list has to contain at least one element"); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<_Type> + operator()(initializer_list<_Type> __il, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_ASSERT_UNCATEGORIZED(__il.begin() != __il.end(), "initializer_list has to contain at least one element"); auto __iters = std::__minmax_element_impl(__il.begin(), __il.end(), __comp, __proj); - return ranges::minmax_result<_Type> { *__iters.first, *__iters.second }; + return ranges::minmax_result<_Type>{*__iters.first, *__iters.second}; } - template <input_range _Range, class _Proj = identity, + template <input_range _Range, + class _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<_Range>, range_value_t<_Range>*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - ranges::minmax_result<range_value_t<_Range>> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { - auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<range_value_t<_Range>> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); using _ValueT = range_value_t<_Range>; - _LIBCPP_ASSERT(__first != __last, "range has to contain at least one element"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __last, "range has to contain at least one element"); if constexpr (forward_range<_Range>) { + // Special-case the one element case. Avoid repeatedly initializing objects from the result of an iterator + // dereference when doing so might not be idempotent. The `if constexpr` avoids the extra branch in cases where + // it's not needed. + if constexpr (!same_as<remove_cvref_t<range_reference_t<_Range>>, _ValueT> || + is_rvalue_reference_v<range_reference_t<_Range>>) { + if (ranges::next(__first) == __last) { + // During initialization, members are allowed to refer to already initialized members + // (see http://eel.is/c++draft/dcl.init.aggr#6) + minmax_result<_ValueT> __result = {*__first, __result.min}; + return __result; + } + } auto __result = std::__minmax_element_impl(__first, __last, __comp, __proj); return {*__result.first, *__result.second}; } else { // input_iterators can't be copied, so the implementation for input_iterators has to store // the values instead of a pointer to the correct values auto __less = [&](auto&& __a, auto&& __b) -> bool { - return std::invoke(__comp, std::invoke(__proj, std::forward<decltype(__a)>(__a)), - std::invoke(__proj, std::forward<decltype(__b)>(__b))); + return std::invoke(__comp, + std::invoke(__proj, std::forward<decltype(__a)>(__a)), + std::invoke(__proj, std::forward<decltype(__b)>(__b))); }; + // During initialization, members are allowed to refer to already initialized members + // (see http://eel.is/c++draft/dcl.init.aggr#6) ranges::minmax_result<_ValueT> __result = {*__first, __result.min}; if (__first == __last || ++__first == __last) return __result; @@ -121,7 +146,7 @@ struct __fn { } // namespace __minmax inline namespace __cpo { - inline constexpr auto minmax = __minmax::__fn{}; +inline constexpr auto minmax = __minmax::__fn{}; } // namespace __cpo } // namespace ranges @@ -129,6 +154,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MINMAX_H diff --git a/libcxx/include/__algorithm/ranges_minmax_element.h b/libcxx/include/__algorithm/ranges_minmax_element.h index 6699f9626e1b..a52319f6b5d3 100644 --- a/libcxx/include/__algorithm/ranges_minmax_element.h +++ b/libcxx/include/__algorithm/ranges_minmax_element.h @@ -23,13 +23,12 @@ #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,18 +39,20 @@ using minmax_element_result = min_max_result<_T1>; namespace __minmax_element { struct __fn { - template <forward_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity, + template <forward_iterator _Ip, + sentinel_for<_Ip> _Sp, + class _Proj = identity, indirect_strict_weak_order<projected<_Ip, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - ranges::minmax_element_result<_Ip> operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result<_Ip> + operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__minmax_element_impl(std::move(__first), std::move(__last), __comp, __proj); return {__ret.first, __ret.second}; } - template <forward_range _Rp, class _Proj = identity, + template <forward_range _Rp, + class _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - ranges::minmax_element_result<borrowed_iterator_t<_Rp>> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_element_result<borrowed_iterator_t<_Rp>> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__minmax_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); return {__ret.first, __ret.second}; @@ -60,13 +61,13 @@ struct __fn { } // namespace __minmax_element inline namespace __cpo { - inline constexpr auto minmax_element = __minmax_element::__fn{}; +inline constexpr auto minmax_element = __minmax_element::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MINMAX_H diff --git a/libcxx/include/__algorithm/ranges_mismatch.h b/libcxx/include/__algorithm/ranges_mismatch.h index 4fd051792838..db9bfc8e87db 100644 --- a/libcxx/include/__algorithm/ranges_mismatch.h +++ b/libcxx/include/__algorithm/ranges_mismatch.h @@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -36,12 +36,9 @@ using mismatch_result = in_in_result<_I1, _I2>; namespace __mismatch { struct __fn { - template <class _I1, class _S1, class _I2, class _S2, - class _Pred, class _Proj1, class _Proj2> - static _LIBCPP_HIDE_FROM_ABI constexpr - mismatch_result<_I1, _I2> - __go(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, - _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + template <class _I1, class _S1, class _I2, class _S2, class _Pred, class _Proj1, class _Proj2> + static _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> + __go(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { while (__first1 != __last1 && __first2 != __last2) { if (!std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) break; @@ -51,34 +48,41 @@ struct __fn { return {std::move(__first1), std::move(__first2)}; } - template <input_iterator _I1, sentinel_for<_I1> _S1, - input_iterator _I2, sentinel_for<_I2> _S2, - class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> + template <input_iterator _I1, + sentinel_for<_I1> _S1, + input_iterator _I2, + sentinel_for<_I2> _S2, + class _Pred = ranges::equal_to, + class _Proj1 = identity, + class _Proj2 = identity> requires indirectly_comparable<_I1, _I2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - mismatch_result<_I1, _I2> operator()(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> operator()( + _I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + const { return __go(std::move(__first1), __last1, std::move(__first2), __last2, __pred, __proj1, __proj2); } - template <input_range _R1, input_range _R2, - class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> + template <input_range _R1, + input_range _R2, + class _Pred = ranges::equal_to, + class _Proj1 = identity, + class _Proj2 = identity> requires indirectly_comparable<iterator_t<_R1>, iterator_t<_R2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - mismatch_result<borrowed_iterator_t<_R1>, borrowed_iterator_t<_R2>> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<borrowed_iterator_t<_R1>, + borrowed_iterator_t<_R2>> operator()(_R1&& __r1, _R2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - return __go(ranges::begin(__r1), ranges::end(__r1), ranges::begin(__r2), ranges::end(__r2), - __pred, __proj1, __proj2); + return __go( + ranges::begin(__r1), ranges::end(__r1), ranges::begin(__r2), ranges::end(__r2), __pred, __proj1, __proj2); } }; } // namespace __mismatch inline namespace __cpo { - constexpr inline auto mismatch = __mismatch::__fn{}; +constexpr inline auto mismatch = __mismatch::__fn{}; } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/ranges_move.h b/libcxx/include/__algorithm/ranges_move.h index 46a0970f834a..8bd2409f891c 100644 --- a/libcxx/include/__algorithm/ranges_move.h +++ b/libcxx/include/__algorithm/ranges_move.h @@ -23,7 +23,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -34,38 +34,36 @@ using move_result = in_out_result<_InIter, _OutIter>; namespace __move { struct __fn { - template <class _InIter, class _Sent, class _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr static - move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { + _LIBCPP_HIDE_FROM_ABI constexpr static move_result<_InIter, _OutIter> + __move_impl(_InIter __first, _Sent __last, _OutIter __result) { auto __ret = std::__move<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } template <input_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter> requires indirectly_movable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - move_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr move_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { return __move_impl(std::move(__first), std::move(__last), std::move(__result)); } template <input_range _Range, weakly_incrementable _OutIter> requires indirectly_movable<iterator_t<_Range>, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - move_result<borrowed_iterator_t<_Range>, _OutIter> operator()(_Range&& __range, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr move_result<borrowed_iterator_t<_Range>, _OutIter> + operator()(_Range&& __range, _OutIter __result) const { return __move_impl(ranges::begin(__range), ranges::end(__range), std::move(__result)); } - }; } // namespace __move inline namespace __cpo { - inline constexpr auto move = __move::__fn{}; +inline constexpr auto move = __move::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MOVE_H diff --git a/libcxx/include/__algorithm/ranges_move_backward.h b/libcxx/include/__algorithm/ranges_move_backward.h index d4e8eb1a5008..ee390a40e489 100644 --- a/libcxx/include/__algorithm/ranges_move_backward.h +++ b/libcxx/include/__algorithm/ranges_move_backward.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -36,38 +36,36 @@ using move_backward_result = in_out_result<_InIter, _OutIter>; namespace __move_backward { struct __fn { - template <class _InIter, class _Sent, class _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr static - move_backward_result<_InIter, _OutIter> __move_backward_impl(_InIter __first, _Sent __last, _OutIter __result) { + _LIBCPP_HIDE_FROM_ABI constexpr static move_backward_result<_InIter, _OutIter> + __move_backward_impl(_InIter __first, _Sent __last, _OutIter __result) { auto __ret = std::__move_backward<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } template <bidirectional_iterator _InIter, sentinel_for<_InIter> _Sent, bidirectional_iterator _OutIter> requires indirectly_movable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - move_backward_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr move_backward_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { return __move_backward_impl(std::move(__first), std::move(__last), std::move(__result)); } template <bidirectional_range _Range, bidirectional_iterator _Iter> requires indirectly_movable<iterator_t<_Range>, _Iter> - _LIBCPP_HIDE_FROM_ABI constexpr - move_backward_result<borrowed_iterator_t<_Range>, _Iter> operator()(_Range&& __range, _Iter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr move_backward_result<borrowed_iterator_t<_Range>, _Iter> + operator()(_Range&& __range, _Iter __result) const { return __move_backward_impl(ranges::begin(__range), ranges::end(__range), std::move(__result)); } - }; } // namespace __move_backward inline namespace __cpo { - inline constexpr auto move_backward = __move_backward::__fn{}; +inline constexpr auto move_backward = __move_backward::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_MOVE_BACKWARD_H diff --git a/libcxx/include/__algorithm/ranges_next_permutation.h b/libcxx/include/__algorithm/ranges_next_permutation.h index 6c8e8e1529f2..9ebab3ea7c13 100644 --- a/libcxx/include/__algorithm/ranges_next_permutation.h +++ b/libcxx/include/__algorithm/ranges_next_permutation.h @@ -28,7 +28,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -68,6 +68,6 @@ constexpr inline auto next_permutation = __next_permutation::__fn{}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H diff --git a/libcxx/include/__algorithm/ranges_none_of.h b/libcxx/include/__algorithm/ranges_none_of.h index b39e570fd33a..b0d363895e00 100644 --- a/libcxx/include/__algorithm/ranges_none_of.h +++ b/libcxx/include/__algorithm/ranges_none_of.h @@ -22,17 +22,16 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __none_of { struct __fn { - template <class _Iter, class _Sent, class _Proj, class _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr static - bool __none_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static bool + __none_of_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) return false; @@ -40,29 +39,32 @@ struct __fn { return true; } - template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, + template <input_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { return __none_of_impl(std::move(__first), std::move(__last), __pred, __proj); } - template <input_range _Range, class _Proj = identity, + template <input_range _Range, + class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __none_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } }; } // namespace __none_of inline namespace __cpo { - inline constexpr auto none_of = __none_of::__fn{}; +inline constexpr auto none_of = __none_of::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_NONE_OF_H diff --git a/libcxx/include/__algorithm/ranges_nth_element.h b/libcxx/include/__algorithm/ranges_nth_element.h index d9ec4f13825b..7abdbd0889e0 100644 --- a/libcxx/include/__algorithm/ranges_nth_element.h +++ b/libcxx/include/__algorithm/ranges_nth_element.h @@ -31,7 +31,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,8 +40,8 @@ namespace __nth_element { struct __fn { template <class _Iter, class _Sent, class _Comp, class _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __nth_element_fn_impl(_Iter __first, _Iter __nth, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __nth_element_fn_impl(_Iter __first, _Iter __nth, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = std::__make_projected(__comp, __proj); @@ -52,16 +52,15 @@ struct __fn { template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Iter __nth, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Iter __nth, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __nth_element_fn_impl(std::move(__first), std::move(__nth), std::move(__last), __comp, __proj); } template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity> requires sortable<iterator_t<_Range>, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, iterator_t<_Range> __nth, _Comp __comp = {}, - _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __nth, _Comp __comp = {}, _Proj __proj = {}) const { return __nth_element_fn_impl(ranges::begin(__r), std::move(__nth), ranges::end(__r), __comp, __proj); } }; @@ -69,12 +68,12 @@ struct __fn { } // namespace __nth_element inline namespace __cpo { - inline constexpr auto nth_element = __nth_element::__fn{}; +inline constexpr auto nth_element = __nth_element::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H diff --git a/libcxx/include/__algorithm/ranges_partial_sort.h b/libcxx/include/__algorithm/ranges_partial_sort.h index 3ea0a7fb44b5..9ec8882097d7 100644 --- a/libcxx/include/__algorithm/ranges_partial_sort.h +++ b/libcxx/include/__algorithm/ranges_partial_sort.h @@ -33,7 +33,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,24 +42,23 @@ namespace __partial_sort { struct __fn { template <class _Iter, class _Sent, class _Comp, class _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __partial_sort_fn_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __partial_sort_fn_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp& __comp, _Proj& __proj) { auto&& __projected_comp = std::__make_projected(__comp, __proj); return std::__partial_sort<_RangeAlgPolicy>(std::move(__first), std::move(__middle), __last, __projected_comp); } template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __partial_sort_fn_impl(std::move(__first), std::move(__middle), std::move(__last), __comp, __proj); } template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity> requires sortable<iterator_t<_Range>, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, iterator_t<_Range> __middle, _Comp __comp = {}, - _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const { return __partial_sort_fn_impl(ranges::begin(__r), std::move(__middle), ranges::end(__r), __comp, __proj); } }; @@ -67,12 +66,12 @@ struct __fn { } // namespace __partial_sort inline namespace __cpo { - inline constexpr auto partial_sort = __partial_sort::__fn{}; +inline constexpr auto partial_sort = __partial_sort::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_H diff --git a/libcxx/include/__algorithm/ranges_partial_sort_copy.h b/libcxx/include/__algorithm/ranges_partial_sort_copy.h index 212db555a8d3..eba7d9ac4165 100644 --- a/libcxx/include/__algorithm/ranges_partial_sort_copy.h +++ b/libcxx/include/__algorithm/ranges_partial_sort_copy.h @@ -30,7 +30,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,51 +42,68 @@ using partial_sort_copy_result = in_out_result<_InIter, _OutIter>; namespace __partial_sort_copy { struct __fn { - - template <input_iterator _Iter1, sentinel_for<_Iter1> _Sent1, - random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Comp = ranges::less, class _Proj1 = identity, class _Proj2 = identity> - requires indirectly_copyable<_Iter1, _Iter2> && sortable<_Iter2, _Comp, _Proj2> && - indirect_strict_weak_order<_Comp, projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> - _LIBCPP_HIDE_FROM_ABI constexpr - partial_sort_copy_result<_Iter1, _Iter2> - operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result_first, _Sent2 __result_last, - _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + template <input_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + random_access_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_copyable<_Iter1, _Iter2> && sortable<_Iter2, _Comp, _Proj2> && + indirect_strict_weak_order<_Comp, projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> + _LIBCPP_HIDE_FROM_ABI constexpr partial_sort_copy_result<_Iter1, _Iter2> operator()( + _Iter1 __first, + _Sent1 __last, + _Iter2 __result_first, + _Sent2 __result_last, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __result = std::__partial_sort_copy<_RangeAlgPolicy>( - std::move(__first), std::move(__last), std::move(__result_first), std::move(__result_last), - __comp, __proj1, __proj2 - ); + std::move(__first), + std::move(__last), + std::move(__result_first), + std::move(__result_last), + __comp, + __proj1, + __proj2); return {std::move(__result.first), std::move(__result.second)}; } - template <input_range _Range1, random_access_range _Range2, class _Comp = ranges::less, - class _Proj1 = identity, class _Proj2 = identity> - requires indirectly_copyable<iterator_t<_Range1>, iterator_t<_Range2>> && - sortable<iterator_t<_Range2>, _Comp, _Proj2> && - indirect_strict_weak_order<_Comp, projected<iterator_t<_Range1>, _Proj1>, - projected<iterator_t<_Range2>, _Proj2>> - _LIBCPP_HIDE_FROM_ABI constexpr - partial_sort_copy_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>> - operator()(_Range1&& __range, _Range2&& __result_range, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + template <input_range _Range1, + random_access_range _Range2, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_copyable<iterator_t<_Range1>, iterator_t<_Range2>> && + sortable<iterator_t<_Range2>, _Comp, _Proj2> && + indirect_strict_weak_order<_Comp, + projected<iterator_t<_Range1>, _Proj1>, + projected<iterator_t<_Range2>, _Proj2>> + _LIBCPP_HIDE_FROM_ABI constexpr partial_sort_copy_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>> + operator()( + _Range1&& __range, _Range2&& __result_range, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __result = std::__partial_sort_copy<_RangeAlgPolicy>( - ranges::begin(__range), ranges::end(__range), ranges::begin(__result_range), ranges::end(__result_range), - __comp, __proj1, __proj2 - ); + ranges::begin(__range), + ranges::end(__range), + ranges::begin(__result_range), + ranges::end(__result_range), + __comp, + __proj1, + __proj2); return {std::move(__result.first), std::move(__result.second)}; } - }; } // namespace __partial_sort_copy inline namespace __cpo { - inline constexpr auto partial_sort_copy = __partial_sort_copy::__fn{}; +inline constexpr auto partial_sort_copy = __partial_sort_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_COPY_H diff --git a/libcxx/include/__algorithm/ranges_partition.h b/libcxx/include/__algorithm/ranges_partition.h index 8b3aae5c250d..89d192b51fd3 100644 --- a/libcxx/include/__algorithm/ranges_partition.h +++ b/libcxx/include/__algorithm/ranges_partition.h @@ -27,13 +27,12 @@ #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,43 +40,44 @@ namespace ranges { namespace __partition { struct __fn { - template <class _Iter, class _Sent, class _Proj, class _Pred> - _LIBCPP_HIDE_FROM_ABI static constexpr - subrange<__remove_cvref_t<_Iter>> __partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { + _LIBCPP_HIDE_FROM_ABI static constexpr subrange<__remove_cvref_t<_Iter>> + __partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { auto&& __projected_pred = std::__make_projected(__pred, __proj); - auto __result = std::__partition<_RangeAlgPolicy>( + auto __result = std::__partition<_RangeAlgPolicy>( std::move(__first), std::move(__last), __projected_pred, __iterator_concept<_Iter>()); return {std::move(__result.first), std::move(__result.second)}; } - template <permutable _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, + template <permutable _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __partition_fn_impl(__first, __last, __pred, __proj); } - template <forward_range _Range, class _Proj = identity, + template <forward_range _Range, + class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - requires permutable<iterator_t<_Range>> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + requires permutable<iterator_t<_Range>> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } - }; } // namespace __partition inline namespace __cpo { - inline constexpr auto partition = __partition::__fn{}; +inline constexpr auto partition = __partition::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_H diff --git a/libcxx/include/__algorithm/ranges_partition_copy.h b/libcxx/include/__algorithm/ranges_partition_copy.h index e7a9a347df5a..6a16b02db3e5 100644 --- a/libcxx/include/__algorithm/ranges_partition_copy.h +++ b/libcxx/include/__algorithm/ranges_partition_copy.h @@ -19,14 +19,14 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> +#include <__type_traits/remove_cvref.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -38,14 +38,18 @@ using partition_copy_result = in_out_out_result<_InIter, _OutIter1, _OutIter2>; namespace __partition_copy { struct __fn { - // TODO(ranges): delegate to the classic algorithm. template <class _InIter, class _Sent, class _OutIter1, class _OutIter2, class _Proj, class _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr - static partition_copy_result< - __remove_cvref_t<_InIter>, __remove_cvref_t<_OutIter1>, __remove_cvref_t<_OutIter2> - > __partition_copy_fn_impl( _InIter&& __first, _Sent&& __last, _OutIter1&& __out_true, _OutIter2&& __out_false, - _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static partition_copy_result<__remove_cvref_t<_InIter>, + __remove_cvref_t<_OutIter1>, + __remove_cvref_t<_OutIter2> > + __partition_copy_fn_impl( + _InIter&& __first, + _Sent&& __last, + _OutIter1&& __out_true, + _OutIter2&& __out_false, + _Pred& __pred, + _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) { *__out_true = *__first; @@ -60,39 +64,42 @@ struct __fn { return {std::move(__first), std::move(__out_true), std::move(__out_false)}; } - template <input_iterator _InIter, sentinel_for<_InIter> _Sent, - weakly_incrementable _OutIter1, weakly_incrementable _OutIter2, - class _Proj = identity, indirect_unary_predicate<projected<_InIter, _Proj>> _Pred> - requires indirectly_copyable<_InIter, _OutIter1> && indirectly_copyable<_InIter, _OutIter2> - _LIBCPP_HIDE_FROM_ABI constexpr - partition_copy_result<_InIter, _OutIter1, _OutIter2> - operator()(_InIter __first, _Sent __last, _OutIter1 __out_true, _OutIter2 __out_false, - _Pred __pred, _Proj __proj = {}) const { + template <input_iterator _InIter, + sentinel_for<_InIter> _Sent, + weakly_incrementable _OutIter1, + weakly_incrementable _OutIter2, + class _Proj = identity, + indirect_unary_predicate<projected<_InIter, _Proj>> _Pred> + requires indirectly_copyable<_InIter, _OutIter1> && indirectly_copyable<_InIter, _OutIter2> + _LIBCPP_HIDE_FROM_ABI constexpr partition_copy_result<_InIter, _OutIter1, _OutIter2> operator()( + _InIter __first, _Sent __last, _OutIter1 __out_true, _OutIter2 __out_false, _Pred __pred, _Proj __proj = {}) + const { return __partition_copy_fn_impl( std::move(__first), std::move(__last), std::move(__out_true), std::move(__out_false), __pred, __proj); } - template <input_range _Range, weakly_incrementable _OutIter1, weakly_incrementable _OutIter2, - class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - requires indirectly_copyable<iterator_t<_Range>, _OutIter1> && indirectly_copyable<iterator_t<_Range>, _OutIter2> - _LIBCPP_HIDE_FROM_ABI constexpr - partition_copy_result<borrowed_iterator_t<_Range>, _OutIter1, _OutIter2> + template <input_range _Range, + weakly_incrementable _OutIter1, + weakly_incrementable _OutIter2, + class _Proj = identity, + indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> + requires indirectly_copyable<iterator_t<_Range>, _OutIter1> && indirectly_copyable<iterator_t<_Range>, _OutIter2> + _LIBCPP_HIDE_FROM_ABI constexpr partition_copy_result<borrowed_iterator_t<_Range>, _OutIter1, _OutIter2> operator()(_Range&& __range, _OutIter1 __out_true, _OutIter2 __out_false, _Pred __pred, _Proj __proj = {}) const { return __partition_copy_fn_impl( ranges::begin(__range), ranges::end(__range), std::move(__out_true), std::move(__out_false), __pred, __proj); } - }; } // namespace __partition_copy inline namespace __cpo { - inline constexpr auto partition_copy = __partition_copy::__fn{}; +inline constexpr auto partition_copy = __partition_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_COPY_H diff --git a/libcxx/include/__algorithm/ranges_partition_point.h b/libcxx/include/__algorithm/ranges_partition_point.h index 2bd118d4def0..6fc20e7d00e9 100644 --- a/libcxx/include/__algorithm/ranges_partition_point.h +++ b/libcxx/include/__algorithm/ranges_partition_point.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,16 +35,15 @@ namespace ranges { namespace __partition_point { struct __fn { - // TODO(ranges): delegate to the classic algorithm. template <class _Iter, class _Sent, class _Proj, class _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr - static _Iter __partition_point_fn_impl(_Iter&& __first, _Sent&& __last, _Pred& __pred, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __partition_point_fn_impl(_Iter&& __first, _Sent&& __last, _Pred& __pred, _Proj& __proj) { auto __len = ranges::distance(__first, __last); while (__len != 0) { auto __half_len = std::__half_positive(__len); - auto __mid = ranges::next(__first, __half_len); + auto __mid = ranges::next(__first, __half_len); if (std::invoke(__pred, std::invoke(__proj, *__mid))) { __first = ++__mid; @@ -58,31 +57,32 @@ struct __fn { return __first; } - template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, + template <forward_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __partition_point_fn_impl(std::move(__first), std::move(__last), __pred, __proj); } - template <forward_range _Range, class _Proj = identity, + template <forward_range _Range, + class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __partition_point_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } - }; } // namespace __partition_point inline namespace __cpo { - inline constexpr auto partition_point = __partition_point::__fn{}; +inline constexpr auto partition_point = __partition_point::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H diff --git a/libcxx/include/__algorithm/ranges_pop_heap.h b/libcxx/include/__algorithm/ranges_pop_heap.h index 65beec886441..364cfe94b161 100644 --- a/libcxx/include/__algorithm/ranges_pop_heap.h +++ b/libcxx/include/__algorithm/ranges_pop_heap.h @@ -32,7 +32,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,10 +41,10 @@ namespace __pop_heap { struct __fn { template <class _Iter, class _Sent, class _Comp, class _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __pop_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __pop_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); - auto __len = __last_iter - __first; + auto __len = __last_iter - __first; auto&& __projected_comp = std::__make_projected(__comp, __proj); std::__pop_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp, __len); @@ -54,15 +54,15 @@ struct __fn { template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __pop_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity> requires sortable<iterator_t<_Range>, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __pop_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -70,12 +70,12 @@ struct __fn { } // namespace __pop_heap inline namespace __cpo { - inline constexpr auto pop_heap = __pop_heap::__fn{}; +inline constexpr auto pop_heap = __pop_heap::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_POP_HEAP_H diff --git a/libcxx/include/__algorithm/ranges_prev_permutation.h b/libcxx/include/__algorithm/ranges_prev_permutation.h index 6866d90cf484..ae7a68cce5fd 100644 --- a/libcxx/include/__algorithm/ranges_prev_permutation.h +++ b/libcxx/include/__algorithm/ranges_prev_permutation.h @@ -28,7 +28,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,9 +40,7 @@ using prev_permutation_result = in_found_result<_InIter>; namespace __prev_permutation { struct __fn { - - template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, - class _Comp = ranges::less, class _Proj = identity> + template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { @@ -51,8 +49,7 @@ struct __fn { return {std::move(__result.first), std::move(__result.second)}; } - template <bidirectional_range _Range, - class _Comp = ranges::less, class _Proj = identity> + template <bidirectional_range _Range, class _Comp = ranges::less, class _Proj = identity> requires sortable<iterator_t<_Range>, _Comp, _Proj> _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result<borrowed_iterator_t<_Range>> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { @@ -60,7 +57,6 @@ struct __fn { ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); return {std::move(__result.first), std::move(__result.second)}; } - }; } // namespace __prev_permutation @@ -72,6 +68,6 @@ constexpr inline auto prev_permutation = __prev_permutation::__fn{}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H diff --git a/libcxx/include/__algorithm/ranges_push_heap.h b/libcxx/include/__algorithm/ranges_push_heap.h index a1f434741762..1ed9c953f54c 100644 --- a/libcxx/include/__algorithm/ranges_push_heap.h +++ b/libcxx/include/__algorithm/ranges_push_heap.h @@ -32,7 +32,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,8 +41,8 @@ namespace __push_heap { struct __fn { template <class _Iter, class _Sent, class _Comp, class _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __push_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __push_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = std::__make_projected(__comp, __proj); @@ -53,15 +53,15 @@ struct __fn { template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __push_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity> requires sortable<iterator_t<_Range>, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __push_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -69,12 +69,12 @@ struct __fn { } // namespace __push_heap inline namespace __cpo { - inline constexpr auto push_heap = __push_heap::__fn{}; +inline constexpr auto push_heap = __push_heap::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_PUSH_HEAP_H diff --git a/libcxx/include/__algorithm/ranges_remove.h b/libcxx/include/__algorithm/ranges_remove.h index dd5c5fb4536a..bf0928df599c 100644 --- a/libcxx/include/__algorithm/ranges_remove.h +++ b/libcxx/include/__algorithm/ranges_remove.h @@ -25,27 +25,26 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __remove { struct __fn { - template <permutable _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity> requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __other) { return __value == __other; }; return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); } template <forward_range _Range, class _Type, class _Proj = identity> - requires permutable<iterator_t<_Range>> - && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type*> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) const { + requires permutable<iterator_t<_Range>> && + indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type*> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) const { auto __pred = [&](auto&& __other) { return __value == __other; }; return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } @@ -53,12 +52,12 @@ struct __fn { } // namespace __remove inline namespace __cpo { - inline constexpr auto remove = __remove::__fn{}; +inline constexpr auto remove = __remove::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_H diff --git a/libcxx/include/__algorithm/ranges_remove_copy.h b/libcxx/include/__algorithm/ranges_remove_copy.h index 210222866759..457d593957ad 100644 --- a/libcxx/include/__algorithm/ranges_remove_copy.h +++ b/libcxx/include/__algorithm/ranges_remove_copy.h @@ -26,7 +26,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -37,40 +37,40 @@ using remove_copy_result = in_out_result<_InIter, _OutIter>; namespace __remove_copy { - struct __fn { - template <input_iterator _InIter, - sentinel_for<_InIter> _Sent, - weakly_incrementable _OutIter, - class _Type, - class _Proj = identity> - requires indirectly_copyable<_InIter, _OutIter> && - indirect_binary_predicate<ranges::equal_to, projected<_InIter, _Proj>, const _Type*> - _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result<_InIter, _OutIter> - operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { - auto __pred = [&](auto&& __val) { return __value == __val; }; - return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); - } +struct __fn { + template <input_iterator _InIter, + sentinel_for<_InIter> _Sent, + weakly_incrementable _OutIter, + class _Type, + class _Proj = identity> + requires indirectly_copyable<_InIter, _OutIter> && + indirect_binary_predicate<ranges::equal_to, projected<_InIter, _Proj>, const _Type*> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __val) { return __value == __val; }; + return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); + } - template <input_range _Range, weakly_incrementable _OutIter, class _Type, class _Proj = identity> - requires indirectly_copyable<iterator_t<_Range>, _OutIter> && - indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type*> - _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result<borrowed_iterator_t<_Range>, _OutIter> - operator()(_Range&& __range, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { - auto __pred = [&](auto&& __val) { return __value == __val; }; - return ranges::__remove_copy_if_impl( - ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); - } - }; + template <input_range _Range, weakly_incrementable _OutIter, class _Type, class _Proj = identity> + requires indirectly_copyable<iterator_t<_Range>, _OutIter> && + indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type*> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result<borrowed_iterator_t<_Range>, _OutIter> + operator()(_Range&& __range, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { + auto __pred = [&](auto&& __val) { return __value == __val; }; + return ranges::__remove_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); + } +}; } // namespace __remove_copy inline namespace __cpo { - inline constexpr auto remove_copy = __remove_copy::__fn{}; +inline constexpr auto remove_copy = __remove_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_H diff --git a/libcxx/include/__algorithm/ranges_remove_copy_if.h b/libcxx/include/__algorithm/ranges_remove_copy_if.h index 4fc67454b926..c07b4813d7d0 100644 --- a/libcxx/include/__algorithm/ranges_remove_copy_if.h +++ b/libcxx/include/__algorithm/ranges_remove_copy_if.h @@ -29,7 +29,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -52,39 +52,39 @@ __remove_copy_if_impl(_InIter __first, _Sent __last, _OutIter __result, _Pred& _ namespace __remove_copy_if { - struct __fn { - template <input_iterator _InIter, - sentinel_for<_InIter> _Sent, - weakly_incrementable _OutIter, - class _Proj = identity, - indirect_unary_predicate<projected<_InIter, _Proj>> _Pred> - requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result<_InIter, _OutIter> - operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { - return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); - } +struct __fn { + template <input_iterator _InIter, + sentinel_for<_InIter> _Sent, + weakly_incrementable _OutIter, + class _Proj = identity, + indirect_unary_predicate<projected<_InIter, _Proj>> _Pred> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { + return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj); + } - template <input_range _Range, - weakly_incrementable _OutIter, - class _Proj = identity, - indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - requires indirectly_copyable<iterator_t<_Range>, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result<borrowed_iterator_t<_Range>, _OutIter> - operator()(_Range&& __range, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { - return ranges::__remove_copy_if_impl( - ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); - } - }; + template <input_range _Range, + weakly_incrementable _OutIter, + class _Proj = identity, + indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> + requires indirectly_copyable<iterator_t<_Range>, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result<borrowed_iterator_t<_Range>, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { + return ranges::__remove_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj); + } +}; } // namespace __remove_copy_if inline namespace __cpo { - inline constexpr auto remove_copy_if = __remove_copy_if::__fn{}; +inline constexpr auto remove_copy_if = __remove_copy_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_IF_H diff --git a/libcxx/include/__algorithm/ranges_remove_if.h b/libcxx/include/__algorithm/ranges_remove_if.h index 1f17467fc43e..4b7aa2d2be78 100644 --- a/libcxx/include/__algorithm/ranges_remove_if.h +++ b/libcxx/include/__algorithm/ranges_remove_if.h @@ -27,15 +27,15 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template <class _Iter, class _Sent, class _Proj, class _Pred> -_LIBCPP_HIDE_FROM_ABI constexpr -subrange<_Iter> __remove_if_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> +__remove_if_impl(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) { auto __new_end = ranges::__find_if_impl(__first, __last, __pred, __proj); if (__new_end == __last) return {__new_end, __new_end}; @@ -52,12 +52,12 @@ subrange<_Iter> __remove_if_impl(_Iter __first, _Sent __last, _Pred& __pred, _Pr namespace __remove_if { struct __fn { - - template <permutable _Iter, sentinel_for<_Iter> _Sent, + template <permutable _Iter, + sentinel_for<_Iter> _Sent, class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj); } @@ -65,21 +65,20 @@ struct __fn { class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> requires permutable<iterator_t<_Range>> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } - }; } // namespace __remove_if inline namespace __cpo { - inline constexpr auto remove_if = __remove_if::__fn{}; +inline constexpr auto remove_if = __remove_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_IF_H diff --git a/libcxx/include/__algorithm/ranges_replace.h b/libcxx/include/__algorithm/ranges_replace.h index 8b12beacb715..714fd5c7b089 100644 --- a/libcxx/include/__algorithm/ranges_replace.h +++ b/libcxx/include/__algorithm/ranges_replace.h @@ -24,51 +24,40 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __replace { struct __fn { - - template <input_iterator _Iter, sentinel_for<_Iter> _Sent, - class _Type1, - class _Type2, - class _Proj = identity> - requires indirectly_writable<_Iter, const _Type2&> - && indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Type1*> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, - const _Type1& __old_value, - const _Type2& __new_value, - _Proj __proj = {}) const { + template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Type1, class _Type2, class _Proj = identity> + requires indirectly_writable<_Iter, const _Type2&> && + indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Type1*> + _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()( + _Iter __first, _Sent __last, const _Type1& __old_value, const _Type2& __new_value, _Proj __proj = {}) const { auto __pred = [&](const auto& __val) { return __val == __old_value; }; return ranges::__replace_if_impl(std::move(__first), std::move(__last), __pred, __new_value, __proj); } - template <input_range _Range, - class _Type1, - class _Type2, - class _Proj = identity> - requires indirectly_writable<iterator_t<_Range>, const _Type2&> - && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type1*> + template <input_range _Range, class _Type1, class _Type2, class _Proj = identity> + requires indirectly_writable<iterator_t<_Range>, const _Type2&> && + indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type1*> _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range, const _Type1& __old_value, const _Type2& __new_value, _Proj __proj = {}) const { auto __pred = [&](auto&& __val) { return __val == __old_value; }; return ranges::__replace_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __new_value, __proj); } - }; } // namespace __replace inline namespace __cpo { - inline constexpr auto replace = __replace::__fn{}; +inline constexpr auto replace = __replace::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_H diff --git a/libcxx/include/__algorithm/ranges_replace_copy.h b/libcxx/include/__algorithm/ranges_replace_copy.h index f87a236fbd0d..124ff8f2c559 100644 --- a/libcxx/include/__algorithm/ranges_replace_copy.h +++ b/libcxx/include/__algorithm/ranges_replace_copy.h @@ -26,7 +26,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -37,55 +37,52 @@ using replace_copy_result = in_out_result<_InIter, _OutIter>; namespace __replace_copy { - struct __fn { - template <input_iterator _InIter, - sentinel_for<_InIter> _Sent, - class _OldType, - class _NewType, - output_iterator<const _NewType&> _OutIter, - class _Proj = identity> - requires indirectly_copyable<_InIter, _OutIter> && - indirect_binary_predicate<ranges::equal_to, projected<_InIter, _Proj>, const _OldType*> - _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result<_InIter, _OutIter> - operator()(_InIter __first, - _Sent __last, - _OutIter __result, - const _OldType& __old_value, - const _NewType& __new_value, - _Proj __proj = {}) const { - auto __pred = [&](const auto& __value) { return __value == __old_value; }; - return ranges::__replace_copy_if_impl( - std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); - } +struct __fn { + template <input_iterator _InIter, + sentinel_for<_InIter> _Sent, + class _OldType, + class _NewType, + output_iterator<const _NewType&> _OutIter, + class _Proj = identity> + requires indirectly_copyable<_InIter, _OutIter> && + indirect_binary_predicate<ranges::equal_to, projected<_InIter, _Proj>, const _OldType*> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result<_InIter, _OutIter> + operator()(_InIter __first, + _Sent __last, + _OutIter __result, + const _OldType& __old_value, + const _NewType& __new_value, + _Proj __proj = {}) const { + auto __pred = [&](const auto& __value) { return __value == __old_value; }; + return ranges::__replace_copy_if_impl( + std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); + } - template <input_range _Range, - class _OldType, - class _NewType, - output_iterator<const _NewType&> _OutIter, - class _Proj = identity> - requires indirectly_copyable<iterator_t<_Range>, _OutIter> && - indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _OldType*> - _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result<borrowed_iterator_t<_Range>, _OutIter> - operator()(_Range&& __range, - _OutIter __result, - const _OldType& __old_value, - const _NewType& __new_value, - _Proj __proj = {}) const { - auto __pred = [&](const auto& __value) { return __value == __old_value; }; - return ranges::__replace_copy_if_impl( - ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); - } - }; + template <input_range _Range, + class _OldType, + class _NewType, + output_iterator<const _NewType&> _OutIter, + class _Proj = identity> + requires indirectly_copyable<iterator_t<_Range>, _OutIter> && + indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _OldType*> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result<borrowed_iterator_t<_Range>, _OutIter> operator()( + _Range&& __range, _OutIter __result, const _OldType& __old_value, const _NewType& __new_value, _Proj __proj = {}) + const { + auto __pred = [&](const auto& __value) { return __value == __old_value; }; + return ranges::__replace_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); + } +}; } // namespace __replace_copy inline namespace __cpo { - inline constexpr auto replace_copy = __replace_copy::__fn{}; +inline constexpr auto replace_copy = __replace_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_H diff --git a/libcxx/include/__algorithm/ranges_replace_copy_if.h b/libcxx/include/__algorithm/ranges_replace_copy_if.h index b8741ec7be5e..10ed1fda6c5c 100644 --- a/libcxx/include/__algorithm/ranges_replace_copy_if.h +++ b/libcxx/include/__algorithm/ranges_replace_copy_if.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -51,43 +51,43 @@ _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> __repl namespace __replace_copy_if { - struct __fn { - template <input_iterator _InIter, - sentinel_for<_InIter> _Sent, - class _Type, - output_iterator<const _Type&> _OutIter, - class _Proj = identity, - indirect_unary_predicate<projected<_InIter, _Proj>> _Pred> - requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> operator()( - _InIter __first, _Sent __last, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) - const { - return ranges::__replace_copy_if_impl( - std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); - } - - template <input_range _Range, - class _Type, - output_iterator<const _Type&> _OutIter, - class _Proj = identity, - indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - requires indirectly_copyable<iterator_t<_Range>, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<borrowed_iterator_t<_Range>, _OutIter> - operator()(_Range&& __range, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { - return ranges::__replace_copy_if_impl( - ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); - } - }; +struct __fn { + template <input_iterator _InIter, + sentinel_for<_InIter> _Sent, + class _Type, + output_iterator<const _Type&> _OutIter, + class _Proj = identity, + indirect_unary_predicate<projected<_InIter, _Proj>> _Pred> + requires indirectly_copyable<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> operator()( + _InIter __first, _Sent __last, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) + const { + return ranges::__replace_copy_if_impl( + std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj); + } + + template <input_range _Range, + class _Type, + output_iterator<const _Type&> _OutIter, + class _Proj = identity, + indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> + requires indirectly_copyable<iterator_t<_Range>, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<borrowed_iterator_t<_Range>, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { + return ranges::__replace_copy_if_impl( + ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj); + } +}; } // namespace __replace_copy_if inline namespace __cpo { - inline constexpr auto replace_copy_if = __replace_copy_if::__fn{}; +inline constexpr auto replace_copy_if = __replace_copy_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_IF_H diff --git a/libcxx/include/__algorithm/ranges_replace_if.h b/libcxx/include/__algorithm/ranges_replace_if.h index 65be3c7d76d5..519fa32029ac 100644 --- a/libcxx/include/__algorithm/ranges_replace_if.h +++ b/libcxx/include/__algorithm/ranges_replace_if.h @@ -23,15 +23,15 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { template <class _Iter, class _Sent, class _Type, class _Proj, class _Pred> -_LIBCPP_HIDE_FROM_ABI constexpr -_Iter __replace_if_impl(_Iter __first, _Sent __last, _Pred& __pred, const _Type& __new_value, _Proj& __proj) { +_LIBCPP_HIDE_FROM_ABI constexpr _Iter +__replace_if_impl(_Iter __first, _Sent __last, _Pred& __pred, const _Type& __new_value, _Proj& __proj) { for (; __first != __last; ++__first) { if (std::invoke(__pred, std::invoke(__proj, *__first))) *__first = __new_value; @@ -41,14 +41,14 @@ _Iter __replace_if_impl(_Iter __first, _Sent __last, _Pred& __pred, const _Type& namespace __replace_if { struct __fn { - - template <input_iterator _Iter, sentinel_for<_Iter> _Sent, + template <input_iterator _Iter, + sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> requires indirectly_writable<_Iter, const _Type&> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { return ranges::__replace_if_impl(std::move(__first), std::move(__last), __pred, __new_value, __proj); } @@ -61,17 +61,16 @@ struct __fn { operator()(_Range&& __range, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { return ranges::__replace_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __new_value, __proj); } - }; } // namespace __replace_if inline namespace __cpo { - inline constexpr auto replace_if = __replace_if::__fn{}; +inline constexpr auto replace_if = __replace_if::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_IF_H diff --git a/libcxx/include/__algorithm/ranges_reverse.h b/libcxx/include/__algorithm/ranges_reverse.h index e2a5d9a8250d..9ec865995b4a 100644 --- a/libcxx/include/__algorithm/ranges_reverse.h +++ b/libcxx/include/__algorithm/ranges_reverse.h @@ -22,18 +22,16 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __reverse { struct __fn { - template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent> requires permutable<_Iter> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter operator()(_Iter __first, _Sent __last) const { if constexpr (random_access_iterator<_Iter>) { if (__first == __last) return __first; @@ -63,21 +61,19 @@ struct __fn { template <bidirectional_range _Range> requires permutable<iterator_t<_Range>> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __range) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> operator()(_Range&& __range) const { return (*this)(ranges::begin(__range), ranges::end(__range)); } - }; } // namespace __reverse inline namespace __cpo { - inline constexpr auto reverse = __reverse::__fn{}; +inline constexpr auto reverse = __reverse::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REVERSE_H diff --git a/libcxx/include/__algorithm/ranges_reverse_copy.h b/libcxx/include/__algorithm/ranges_reverse_copy.h index a84b1ad78050..35b9edba0bfb 100644 --- a/libcxx/include/__algorithm/ranges_reverse_copy.h +++ b/libcxx/include/__algorithm/ranges_reverse_copy.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -36,32 +36,30 @@ using reverse_copy_result = in_out_result<_InIter, _OutIter>; namespace __reverse_copy { struct __fn { - template <bidirectional_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter> requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - reverse_copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr reverse_copy_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result) const { return (*this)(subrange(std::move(__first), std::move(__last)), std::move(__result)); } template <bidirectional_range _Range, weakly_incrementable _OutIter> requires indirectly_copyable<iterator_t<_Range>, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - reverse_copy_result<borrowed_iterator_t<_Range>, _OutIter> operator()(_Range&& __range, _OutIter __result) const { + _LIBCPP_HIDE_FROM_ABI constexpr reverse_copy_result<borrowed_iterator_t<_Range>, _OutIter> + operator()(_Range&& __range, _OutIter __result) const { auto __ret = ranges::copy(std::__reverse_range(__range), std::move(__result)); return {ranges::next(ranges::begin(__range), ranges::end(__range)), std::move(__ret.out)}; } - }; } // namespace __reverse_copy inline namespace __cpo { - inline constexpr auto reverse_copy = __reverse_copy::__fn{}; +inline constexpr auto reverse_copy = __reverse_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_REVERSE_COPY_H diff --git a/libcxx/include/__algorithm/ranges_rotate.h b/libcxx/include/__algorithm/ranges_rotate.h index 91ed4027df2b..ebed9bbd5426 100644 --- a/libcxx/include/__algorithm/ranges_rotate.h +++ b/libcxx/include/__algorithm/ranges_rotate.h @@ -25,7 +25,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -33,39 +33,34 @@ namespace ranges { namespace __rotate { struct __fn { - template <class _Iter, class _Sent> - _LIBCPP_HIDE_FROM_ABI constexpr - static subrange<_Iter> __rotate_fn_impl(_Iter __first, _Iter __middle, _Sent __last) { - auto __ret = std::__rotate<_RangeAlgPolicy>( - std::move(__first), std::move(__middle), std::move(__last)); + _LIBCPP_HIDE_FROM_ABI constexpr static subrange<_Iter> __rotate_fn_impl(_Iter __first, _Iter __middle, _Sent __last) { + auto __ret = std::__rotate<_RangeAlgPolicy>(std::move(__first), std::move(__middle), std::move(__last)); return {std::move(__ret.first), std::move(__ret.second)}; } template <permutable _Iter, sentinel_for<_Iter> _Sent> - _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Iter __middle, _Sent __last) const { + _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> operator()(_Iter __first, _Iter __middle, _Sent __last) const { return __rotate_fn_impl(std::move(__first), std::move(__middle), std::move(__last)); } template <forward_range _Range> - requires permutable<iterator_t<_Range>> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle) const { + requires permutable<iterator_t<_Range>> + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, iterator_t<_Range> __middle) const { return __rotate_fn_impl(ranges::begin(__range), std::move(__middle), ranges::end(__range)); } - }; } // namespace __rotate inline namespace __cpo { - inline constexpr auto rotate = __rotate::__fn{}; +inline constexpr auto rotate = __rotate::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_H diff --git a/libcxx/include/__algorithm/ranges_rotate_copy.h b/libcxx/include/__algorithm/ranges_rotate_copy.h index 52f403c16a80..301672707f72 100644 --- a/libcxx/include/__algorithm/ranges_rotate_copy.h +++ b/libcxx/include/__algorithm/ranges_rotate_copy.h @@ -23,7 +23,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -34,11 +34,9 @@ using rotate_copy_result = in_out_result<_InIter, _OutIter>; namespace __rotate_copy { struct __fn { - template <bidirectional_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter> requires indirectly_copyable<_InIter, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - rotate_copy_result<_InIter, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr rotate_copy_result<_InIter, _OutIter> operator()(_InIter __first, _InIter __middle, _Sent __last, _OutIter __result) const { auto __res1 = ranges::copy(__middle, __last, std::move(__result)); auto __res2 = ranges::copy(__first, __middle, std::move(__res1.out)); @@ -47,22 +45,20 @@ struct __fn { template <bidirectional_range _Range, weakly_incrementable _OutIter> requires indirectly_copyable<iterator_t<_Range>, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - rotate_copy_result<borrowed_iterator_t<_Range>, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr rotate_copy_result<borrowed_iterator_t<_Range>, _OutIter> operator()(_Range&& __range, iterator_t<_Range> __middle, _OutIter __result) const { return (*this)(ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__result)); } - }; } // namespace __rotate_copy inline namespace __cpo { - inline constexpr auto rotate_copy = __rotate_copy::__fn{}; +inline constexpr auto rotate_copy = __rotate_copy::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_COPY_H diff --git a/libcxx/include/__algorithm/ranges_sample.h b/libcxx/include/__algorithm/ranges_sample.h index a37cb64fa2bf..d347d82205a8 100644 --- a/libcxx/include/__algorithm/ranges_sample.h +++ b/libcxx/include/__algorithm/ranges_sample.h @@ -19,15 +19,15 @@ #include <__random/uniform_random_bit_generator.h> #include <__ranges/access.h> #include <__ranges/concepts.h> +#include <__type_traits/remove_reference.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,40 +35,35 @@ namespace ranges { namespace __sample { struct __fn { - template <input_iterator _Iter, sentinel_for<_Iter> _Sent, weakly_incrementable _OutIter, class _Gen> - requires (forward_iterator<_Iter> || random_access_iterator<_OutIter>) && - indirectly_copyable<_Iter, _OutIter> && - uniform_random_bit_generator<remove_reference_t<_Gen>> - _LIBCPP_HIDE_FROM_ABI - _OutIter operator()(_Iter __first, _Sent __last, - _OutIter __out_first, iter_difference_t<_Iter> __n, _Gen&& __gen) const { + requires(forward_iterator<_Iter> || random_access_iterator<_OutIter>) && indirectly_copyable<_Iter, _OutIter> && + uniform_random_bit_generator<remove_reference_t<_Gen>> + _LIBCPP_HIDE_FROM_ABI _OutIter + operator()(_Iter __first, _Sent __last, _OutIter __out_first, iter_difference_t<_Iter> __n, _Gen&& __gen) const { _ClassicGenAdaptor<_Gen> __adapted_gen(__gen); return std::__sample<_RangeAlgPolicy>( std::move(__first), std::move(__last), std::move(__out_first), __n, __adapted_gen); } template <input_range _Range, weakly_incrementable _OutIter, class _Gen> - requires (forward_range<_Range> || random_access_iterator<_OutIter>) && - indirectly_copyable<iterator_t<_Range>, _OutIter> && - uniform_random_bit_generator<remove_reference_t<_Gen>> - _LIBCPP_HIDE_FROM_ABI - _OutIter operator()(_Range&& __range, _OutIter __out_first, range_difference_t<_Range> __n, _Gen&& __gen) const { - return (*this)(ranges::begin(__range), ranges::end(__range), - std::move(__out_first), __n, std::forward<_Gen>(__gen)); + requires(forward_range<_Range> || random_access_iterator<_OutIter>) && + indirectly_copyable<iterator_t<_Range>, _OutIter> && uniform_random_bit_generator<remove_reference_t<_Gen>> + _LIBCPP_HIDE_FROM_ABI _OutIter + operator()(_Range&& __range, _OutIter __out_first, range_difference_t<_Range> __n, _Gen&& __gen) const { + return (*this)( + ranges::begin(__range), ranges::end(__range), std::move(__out_first), __n, std::forward<_Gen>(__gen)); } - }; } // namespace __sample inline namespace __cpo { - inline constexpr auto sample = __sample::__fn{}; +inline constexpr auto sample = __sample::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SAMPLE_H diff --git a/libcxx/include/__algorithm/ranges_search.h b/libcxx/include/__algorithm/ranges_search.h index 388d5afa499d..ca2326e9ab27 100644 --- a/libcxx/include/__algorithm/ranges_search.h +++ b/libcxx/include/__algorithm/ranges_search.h @@ -28,7 +28,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -69,33 +69,33 @@ struct __fn { return {__ret.first, __ret.second}; } - template <forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - class _Pred = ranges::equal_to, + template <forward_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + forward_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter1> operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter1> operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { return __ranges_search_impl(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2); } template <forward_range _Range1, forward_range _Range2, - class _Pred = ranges::equal_to, + class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range1> operator()(_Range1&& __range1, - _Range2&& __range2, - _Pred __pred = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range1> operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { auto __first1 = ranges::begin(__range1); if constexpr (sized_range<_Range2>) { auto __size2 = ranges::size(__range2); @@ -119,17 +119,16 @@ struct __fn { __proj1, __proj2); } - }; } // namespace __search inline namespace __cpo { - inline constexpr auto search = __search::__fn{}; +inline constexpr auto search = __search::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SEARCH_H diff --git a/libcxx/include/__algorithm/ranges_search_n.h b/libcxx/include/__algorithm/ranges_search_n.h index 56ec8f33d431..4e53f30f71f9 100644 --- a/libcxx/include/__algorithm/ranges_search_n.h +++ b/libcxx/include/__algorithm/ranges_search_n.h @@ -31,14 +31,13 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __search_n { struct __fn { - template <class _Iter1, class _Sent1, class _SizeT, class _Type, class _Pred, class _Proj> _LIBCPP_HIDE_FROM_ABI static constexpr subrange<_Iter1> __ranges_search_n_impl( _Iter1 __first, _Sent1 __last, _SizeT __count, const _Type& __value, _Pred& __pred, _Proj& __proj) { @@ -59,36 +58,31 @@ struct __fn { } } - auto __ret = std::__search_n_forward_impl<_RangeAlgPolicy>(__first, __last, - __count, - __value, - __pred, - __proj); + auto __ret = std::__search_n_forward_impl<_RangeAlgPolicy>(__first, __last, __count, __value, __pred, __proj); return {std::move(__ret.first), std::move(__ret.second)}; } - template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, + template <forward_iterator _Iter, + sentinel_for<_Iter> _Sent, class _Type, class _Pred = ranges::equal_to, class _Proj = identity> requires indirectly_comparable<_Iter, const _Type*, _Pred, _Proj> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - subrange<_Iter> operator()(_Iter __first, _Sent __last, - iter_difference_t<_Iter> __count, - const _Type& __value, - _Pred __pred = {}, - _Proj __proj = _Proj{}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, + _Sent __last, + iter_difference_t<_Iter> __count, + const _Type& __value, + _Pred __pred = {}, + _Proj __proj = _Proj{}) const { return __ranges_search_n_impl(__first, __last, __count, __value, __pred, __proj); } template <forward_range _Range, class _Type, class _Pred = ranges::equal_to, class _Proj = identity> requires indirectly_comparable<iterator_t<_Range>, const _Type*, _Pred, _Proj> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_subrange_t<_Range> operator()(_Range&& __range, - range_difference_t<_Range> __count, - const _Type& __value, - _Pred __pred = {}, - _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> operator()( + _Range&& __range, range_difference_t<_Range> __count, const _Type& __value, _Pred __pred = {}, _Proj __proj = {}) + const { auto __first = ranges::begin(__range); if (__count <= 0) return {__first, __first}; @@ -106,12 +100,12 @@ struct __fn { } // namespace __search_n inline namespace __cpo { - inline constexpr auto search_n = __search_n::__fn{}; +inline constexpr auto search_n = __search_n::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SEARCH_N_H diff --git a/libcxx/include/__algorithm/ranges_set_difference.h b/libcxx/include/__algorithm/ranges_set_difference.h index 607dd687a5de..a9453ed336f5 100644 --- a/libcxx/include/__algorithm/ranges_set_difference.h +++ b/libcxx/include/__algorithm/ranges_set_difference.h @@ -30,7 +30,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,15 +42,14 @@ using set_difference_result = in_out_result<_InIter, _OutIter>; namespace __set_difference { struct __fn { - template < - input_iterator _InIter1, - sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, - sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> + template <input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_difference_result<_InIter1, _OutIter> operator()( _InIter1 __first1, @@ -66,22 +65,20 @@ struct __fn { return {std::move(__ret.first), std::move(__ret.second)}; } - template < - input_range _Range1, - input_range _Range2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> + template <input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_difference_result<borrowed_iterator_t<_Range1>, _OutIter> - operator()( - _Range1&& __range1, - _Range2&& __range2, - _OutIter __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __ret = std::__set_difference<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), @@ -96,11 +93,11 @@ struct __fn { } // namespace __set_difference inline namespace __cpo { - inline constexpr auto set_difference = __set_difference::__fn{}; +inline constexpr auto set_difference = __set_difference::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SET_DIFFERENCE_H diff --git a/libcxx/include/__algorithm/ranges_set_intersection.h b/libcxx/include/__algorithm/ranges_set_intersection.h index aa9fd24ced09..4cdcbb75051a 100644 --- a/libcxx/include/__algorithm/ranges_set_intersection.h +++ b/libcxx/include/__algorithm/ranges_set_intersection.h @@ -28,7 +28,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,15 +40,14 @@ using set_intersection_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; namespace __set_intersection { struct __fn { - template < - input_iterator _InIter1, - sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, - sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> + template <input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_intersection_result<_InIter1, _InIter2, _OutIter> operator()( _InIter1 __first1, @@ -69,30 +68,22 @@ struct __fn { return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; } - template < - input_range _Range1, - input_range _Range2, - weakly_incrementable _OutIter, - class _Comp = less, - class _Proj1 = identity, - class _Proj2 = identity> - requires mergeable< - iterator_t<_Range1>, - iterator_t<_Range2>, - _OutIter, - _Comp, - _Proj1, - _Proj2> - _LIBCPP_HIDE_FROM_ABI constexpr set_intersection_result<borrowed_iterator_t<_Range1>, - borrowed_iterator_t<_Range2>, - _OutIter> - operator()( - _Range1&& __range1, - _Range2&& __range2, - _OutIter __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + template <input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_intersection_result<borrowed_iterator_t<_Range1>, + borrowed_iterator_t<_Range2>, + _OutIter> + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __ret = std::__set_intersection<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), @@ -107,11 +98,11 @@ struct __fn { } // namespace __set_intersection inline namespace __cpo { - inline constexpr auto set_intersection = __set_intersection::__fn{}; +inline constexpr auto set_intersection = __set_intersection::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SET_INTERSECTION_H diff --git a/libcxx/include/__algorithm/ranges_set_symmetric_difference.h b/libcxx/include/__algorithm/ranges_set_symmetric_difference.h index bc4a9065503b..d8710a1c47b0 100644 --- a/libcxx/include/__algorithm/ranges_set_symmetric_difference.h +++ b/libcxx/include/__algorithm/ranges_set_symmetric_difference.h @@ -28,7 +28,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,15 +40,14 @@ using set_symmetric_difference_result = in_in_out_result<_InIter1, _InIter2, _Ou namespace __set_symmetric_difference { struct __fn { - template < - input_iterator _InIter1, - sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, - sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, - class _Comp = ranges::less, - class _Proj1 = identity, - class _Proj2 = identity> + template <input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_symmetric_difference_result<_InIter1, _InIter2, _OutIter> operator()( _InIter1 __first1, @@ -69,30 +68,22 @@ struct __fn { return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; } - template < - input_range _Range1, - input_range _Range2, - weakly_incrementable _OutIter, - class _Comp = ranges::less, - class _Proj1 = identity, - class _Proj2 = identity> - requires mergeable< - iterator_t<_Range1>, - iterator_t<_Range2>, - _OutIter, - _Comp, - _Proj1, - _Proj2> + template <input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_symmetric_difference_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>, _OutIter> - operator()( - _Range1&& __range1, - _Range2&& __range2, - _OutIter __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), @@ -107,11 +98,11 @@ struct __fn { } // namespace __set_symmetric_difference inline namespace __cpo { - inline constexpr auto set_symmetric_difference = __set_symmetric_difference::__fn{}; +inline constexpr auto set_symmetric_difference = __set_symmetric_difference::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H diff --git a/libcxx/include/__algorithm/ranges_set_union.h b/libcxx/include/__algorithm/ranges_set_union.h index f8cd45ca0e33..c627166fffed 100644 --- a/libcxx/include/__algorithm/ranges_set_union.h +++ b/libcxx/include/__algorithm/ranges_set_union.h @@ -31,7 +31,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -43,15 +43,14 @@ using set_union_result = in_in_out_result<_InIter1, _InIter2, _OutIter>; namespace __set_union { struct __fn { - template < - input_iterator _InIter1, - sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, - sentinel_for<_InIter2> _Sent2, - weakly_incrementable _OutIter, - class _Comp = ranges::less, - class _Proj1 = identity, - class _Proj2 = identity> + template <input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2> _LIBCPP_HIDE_FROM_ABI constexpr set_union_result<_InIter1, _InIter2, _OutIter> operator()( _InIter1 __first1, @@ -72,30 +71,20 @@ struct __fn { return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)}; } - template < - input_range _Range1, - input_range _Range2, - weakly_incrementable _OutIter, - class _Comp = ranges::less, - class _Proj1 = identity, - class _Proj2 = identity> - requires mergeable< - iterator_t<_Range1>, - iterator_t<_Range2>, - _OutIter, - _Comp, - _Proj1, - _Proj2> - _LIBCPP_HIDE_FROM_ABI constexpr set_union_result<borrowed_iterator_t<_Range1>, - borrowed_iterator_t<_Range2>, - _OutIter> - operator()( - _Range1&& __range1, - _Range2&& __range2, - _OutIter __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + template <input_range _Range1, + input_range _Range2, + weakly_incrementable _OutIter, + class _Comp = ranges::less, + class _Proj1 = identity, + class _Proj2 = identity> + requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2> + _LIBCPP_HIDE_FROM_ABI constexpr set_union_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>, _OutIter> + operator()(_Range1&& __range1, + _Range2&& __range2, + _OutIter __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { auto __ret = std::__set_union<_RangeAlgPolicy>( ranges::begin(__range1), ranges::end(__range1), @@ -110,12 +99,12 @@ struct __fn { } // namespace __set_union inline namespace __cpo { - inline constexpr auto set_union = __set_union::__fn{}; +inline constexpr auto set_union = __set_union::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SET_UNION_H diff --git a/libcxx/include/__algorithm/ranges_shuffle.h b/libcxx/include/__algorithm/ranges_shuffle.h index a2f2c0edded6..fca420058dec 100644 --- a/libcxx/include/__algorithm/ranges_shuffle.h +++ b/libcxx/include/__algorithm/ranges_shuffle.h @@ -23,15 +23,15 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> +#include <__type_traits/remove_reference.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -39,33 +39,29 @@ namespace ranges { namespace __shuffle { struct __fn { - template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Gen> - requires permutable<_Iter> && uniform_random_bit_generator<remove_reference_t<_Gen>> - _LIBCPP_HIDE_FROM_ABI - _Iter operator()(_Iter __first, _Sent __last, _Gen&& __gen) const { + requires permutable<_Iter> && uniform_random_bit_generator<remove_reference_t<_Gen>> + _LIBCPP_HIDE_FROM_ABI _Iter operator()(_Iter __first, _Sent __last, _Gen&& __gen) const { _ClassicGenAdaptor<_Gen> __adapted_gen(__gen); return std::__shuffle<_RangeAlgPolicy>(std::move(__first), std::move(__last), __adapted_gen); } - template<random_access_range _Range, class _Gen> - requires permutable<iterator_t<_Range>> && uniform_random_bit_generator<remove_reference_t<_Gen>> - _LIBCPP_HIDE_FROM_ABI - borrowed_iterator_t<_Range> operator()(_Range&& __range, _Gen&& __gen) const { + template <random_access_range _Range, class _Gen> + requires permutable<iterator_t<_Range>> && uniform_random_bit_generator<remove_reference_t<_Gen>> + _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> operator()(_Range&& __range, _Gen&& __gen) const { return (*this)(ranges::begin(__range), ranges::end(__range), std::forward<_Gen>(__gen)); } - }; } // namespace __shuffle inline namespace __cpo { - inline constexpr auto shuffle = __shuffle::__fn{}; +inline constexpr auto shuffle = __shuffle::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H diff --git a/libcxx/include/__algorithm/ranges_sort.h b/libcxx/include/__algorithm/ranges_sort.h index 32391df5f6d9..2ad0e0c233be 100644 --- a/libcxx/include/__algorithm/ranges_sort.h +++ b/libcxx/include/__algorithm/ranges_sort.h @@ -31,7 +31,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,8 +40,8 @@ namespace __sort { struct __fn { template <class _Iter, class _Sent, class _Comp, class _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = std::__make_projected(__comp, __proj); @@ -52,15 +52,15 @@ struct __fn { template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __sort_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity> requires sortable<iterator_t<_Range>, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __sort_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -68,12 +68,12 @@ struct __fn { } // namespace __sort inline namespace __cpo { - inline constexpr auto sort = __sort::__fn{}; +inline constexpr auto sort = __sort::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SORT_H diff --git a/libcxx/include/__algorithm/ranges_sort_heap.h b/libcxx/include/__algorithm/ranges_sort_heap.h index 9feb0f609b25..365c7dba6156 100644 --- a/libcxx/include/__algorithm/ranges_sort_heap.h +++ b/libcxx/include/__algorithm/ranges_sort_heap.h @@ -32,7 +32,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,8 +41,8 @@ namespace __sort_heap { struct __fn { template <class _Iter, class _Sent, class _Comp, class _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr static - _Iter __sort_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI constexpr static _Iter + __sort_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = std::__make_projected(__comp, __proj); @@ -53,15 +53,15 @@ struct __fn { template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __sort_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity> requires sortable<iterator_t<_Range>, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __sort_heap_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -69,12 +69,12 @@ struct __fn { } // namespace __sort_heap inline namespace __cpo { - inline constexpr auto sort_heap = __sort_heap::__fn{}; +inline constexpr auto sort_heap = __sort_heap::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SORT_HEAP_H diff --git a/libcxx/include/__algorithm/ranges_stable_partition.h b/libcxx/include/__algorithm/ranges_stable_partition.h index c3469f17c7d7..44937fa58990 100644 --- a/libcxx/include/__algorithm/ranges_stable_partition.h +++ b/libcxx/include/__algorithm/ranges_stable_partition.h @@ -26,15 +26,15 @@ #include <__ranges/concepts.h> #include <__ranges/dangling.h> #include <__ranges/subrange.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,47 +42,46 @@ namespace ranges { namespace __stable_partition { struct __fn { - template <class _Iter, class _Sent, class _Proj, class _Pred> - _LIBCPP_HIDE_FROM_ABI static - subrange<__remove_cvref_t<_Iter>> __stable_partition_fn_impl( - _Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { + _LIBCPP_HIDE_FROM_ABI static subrange<__remove_cvref_t<_Iter>> + __stable_partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { auto __last_iter = ranges::next(__first, __last); auto&& __projected_pred = std::__make_projected(__pred, __proj); - auto __result = std::__stable_partition<_RangeAlgPolicy>( + auto __result = std::__stable_partition<_RangeAlgPolicy>( std::move(__first), __last_iter, __projected_pred, __iterator_concept<_Iter>()); return {std::move(__result), std::move(__last_iter)}; } - template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity, + template <bidirectional_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - requires permutable<_Iter> - _LIBCPP_HIDE_FROM_ABI - subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + requires permutable<_Iter> + _LIBCPP_HIDE_FROM_ABI subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __stable_partition_fn_impl(__first, __last, __pred, __proj); } - template <bidirectional_range _Range, class _Proj = identity, + template <bidirectional_range _Range, + class _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - requires permutable<iterator_t<_Range>> - _LIBCPP_HIDE_FROM_ABI - borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { + requires permutable<iterator_t<_Range>> + _LIBCPP_HIDE_FROM_ABI borrowed_subrange_t<_Range> + operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __stable_partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } - }; } // namespace __stable_partition inline namespace __cpo { - inline constexpr auto stable_partition = __stable_partition::__fn{}; +inline constexpr auto stable_partition = __stable_partition::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_STABLE_PARTITION_H diff --git a/libcxx/include/__algorithm/ranges_stable_sort.h b/libcxx/include/__algorithm/ranges_stable_sort.h index d3c48ddb9b8e..a4eed3836356 100644 --- a/libcxx/include/__algorithm/ranges_stable_sort.h +++ b/libcxx/include/__algorithm/ranges_stable_sort.h @@ -31,7 +31,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -40,8 +40,7 @@ namespace __stable_sort { struct __fn { template <class _Iter, class _Sent, class _Comp, class _Proj> - _LIBCPP_HIDE_FROM_ABI - static _Iter __stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { + _LIBCPP_HIDE_FROM_ABI static _Iter __stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) { auto __last_iter = ranges::next(__first, __last); auto&& __projected_comp = std::__make_projected(__comp, __proj); @@ -52,15 +51,14 @@ struct __fn { template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI - _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __stable_sort_fn_impl(std::move(__first), std::move(__last), __comp, __proj); } template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity> requires sortable<iterator_t<_Range>, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI - borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return __stable_sort_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj); } }; @@ -68,12 +66,12 @@ struct __fn { } // namespace __stable_sort inline namespace __cpo { - inline constexpr auto stable_sort = __stable_sort::__fn{}; +inline constexpr auto stable_sort = __stable_sort::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_STABLE_SORT_H diff --git a/libcxx/include/__algorithm/ranges_starts_with.h b/libcxx/include/__algorithm/ranges_starts_with.h new file mode 100644 index 000000000000..7da78001d814 --- /dev/null +++ b/libcxx/include/__algorithm/ranges_starts_with.h @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_RANGES_STARTS_WITH_H +#define _LIBCPP___ALGORITHM_RANGES_STARTS_WITH_H + +#include <__algorithm/in_in_result.h> +#include <__algorithm/ranges_mismatch.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/indirectly_comparable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __starts_with { +struct __fn { + template <input_iterator _Iter1, + sentinel_for<_Iter1> _Sent1, + input_iterator _Iter2, + sentinel_for<_Iter2> _Sent2, + class _Pred = ranges::equal_to, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Iter1 __first1, + _Sent1 __last1, + _Iter2 __first2, + _Sent2 __last2, + _Pred __pred = {}, + _Proj1 __proj1 = {}, + _Proj2 __proj2 = {}) const { + return __mismatch::__fn::__go( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + __pred, + __proj1, + __proj2) + .in2 == __last2; + } + + template <input_range _Range1, + input_range _Range2, + class _Pred = ranges::equal_to, + class _Proj1 = identity, + class _Proj2 = identity> + requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + return __mismatch::__fn::__go( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + __pred, + __proj1, + __proj2) + .in2 == ranges::end(__range2); + } +}; +} // namespace __starts_with +inline namespace __cpo { +inline constexpr auto starts_with = __starts_with::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___ALGORITHM_RANGES_STARTS_WITH_H diff --git a/libcxx/include/__algorithm/ranges_swap_ranges.h b/libcxx/include/__algorithm/ranges_swap_ranges.h index 552fd55ff88f..1d0ebc0d5221 100644 --- a/libcxx/include/__algorithm/ranges_swap_ranges.h +++ b/libcxx/include/__algorithm/ranges_swap_ranges.h @@ -24,7 +24,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,8 +35,7 @@ using swap_ranges_result = in_in_result<_I1, _I2>; namespace __swap_ranges { struct __fn { - template <input_iterator _I1, sentinel_for<_I1> _S1, - input_iterator _I2, sentinel_for<_I2> _S2> + template <input_iterator _I1, sentinel_for<_I1> _S1, input_iterator _I2, sentinel_for<_I2> _S2> requires indirectly_swappable<_I1, _I2> _LIBCPP_HIDE_FROM_ABI constexpr swap_ranges_result<_I1, _I2> operator()(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2) const { @@ -47,22 +46,20 @@ struct __fn { template <input_range _R1, input_range _R2> requires indirectly_swappable<iterator_t<_R1>, iterator_t<_R2>> - _LIBCPP_HIDE_FROM_ABI constexpr - swap_ranges_result<borrowed_iterator_t<_R1>, borrowed_iterator_t<_R2>> + _LIBCPP_HIDE_FROM_ABI constexpr swap_ranges_result<borrowed_iterator_t<_R1>, borrowed_iterator_t<_R2>> operator()(_R1&& __r1, _R2&& __r2) const { - return operator()(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2)); + return operator()(ranges::begin(__r1), ranges::end(__r1), ranges::begin(__r2), ranges::end(__r2)); } }; } // namespace __swap_ranges inline namespace __cpo { - inline constexpr auto swap_ranges = __swap_ranges::__fn{}; +inline constexpr auto swap_ranges = __swap_ranges::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_SWAP_RANGES_H diff --git a/libcxx/include/__algorithm/ranges_transform.h b/libcxx/include/__algorithm/ranges_transform.h index c0981a04a9bb..f66a07ac026e 100644 --- a/libcxx/include/__algorithm/ranges_transform.h +++ b/libcxx/include/__algorithm/ranges_transform.h @@ -26,7 +26,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,15 +41,9 @@ using binary_transform_result = in_in_out_result<_I1, _I2, _O1>; namespace __transform { struct __fn { private: - template <class _InIter, class _Sent, - class _OutIter, - class _Func, - class _Proj> - _LIBCPP_HIDE_FROM_ABI static constexpr - unary_transform_result<_InIter, _OutIter> __unary(_InIter __first, _Sent __last, - _OutIter __result, - _Func& __operation, - _Proj& __projection) { + template <class _InIter, class _Sent, class _OutIter, class _Func, class _Proj> + _LIBCPP_HIDE_FROM_ABI static constexpr unary_transform_result<_InIter, _OutIter> + __unary(_InIter __first, _Sent __last, _OutIter __result, _Func& __operation, _Proj& __projection) { while (__first != __last) { *__result = std::invoke(__operation, std::invoke(__projection, *__first)); ++__first; @@ -59,76 +53,80 @@ private: return {std::move(__first), std::move(__result)}; } - template <class _InIter1, class _Sent1, - class _InIter2, class _Sent2, + template <class _InIter1, + class _Sent1, + class _InIter2, + class _Sent2, class _OutIter, class _Func, class _Proj1, class _Proj2> _LIBCPP_HIDE_FROM_ABI static constexpr binary_transform_result<_InIter1, _InIter2, _OutIter> - __binary(_InIter1 __first1, _Sent1 __last1, - _InIter2 __first2, _Sent2 __last2, + __binary(_InIter1 __first1, + _Sent1 __last1, + _InIter2 __first2, + _Sent2 __last2, _OutIter __result, _Func& __binary_operation, _Proj1& __projection1, _Proj2& __projection2) { while (__first1 != __last1 && __first2 != __last2) { - *__result = std::invoke(__binary_operation, std::invoke(__projection1, *__first1), - std::invoke(__projection2, *__first2)); + *__result = + std::invoke(__binary_operation, std::invoke(__projection1, *__first1), std::invoke(__projection2, *__first2)); ++__first1; ++__first2; ++__result; } return {std::move(__first1), std::move(__first2), std::move(__result)}; } + public: - template <input_iterator _InIter, sentinel_for<_InIter> _Sent, + template <input_iterator _InIter, + sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter, copy_constructible _Func, class _Proj = identity> requires indirectly_writable<_OutIter, indirect_result_t<_Func&, projected<_InIter, _Proj>>> - _LIBCPP_HIDE_FROM_ABI constexpr - unary_transform_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, - _OutIter __result, - _Func __operation, - _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr unary_transform_result<_InIter, _OutIter> + operator()(_InIter __first, _Sent __last, _OutIter __result, _Func __operation, _Proj __proj = {}) const { return __unary(std::move(__first), std::move(__last), std::move(__result), __operation, __proj); } - template <input_range _Range, - weakly_incrementable _OutIter, - copy_constructible _Func, - class _Proj = identity> + template <input_range _Range, weakly_incrementable _OutIter, copy_constructible _Func, class _Proj = identity> requires indirectly_writable<_OutIter, indirect_result_t<_Func, projected<iterator_t<_Range>, _Proj>>> - _LIBCPP_HIDE_FROM_ABI constexpr - unary_transform_result<borrowed_iterator_t<_Range>, _OutIter> operator()(_Range&& __range, - _OutIter __result, - _Func __operation, - _Proj __projection = {}) const { + _LIBCPP_HIDE_FROM_ABI constexpr unary_transform_result<borrowed_iterator_t<_Range>, _OutIter> + operator()(_Range&& __range, _OutIter __result, _Func __operation, _Proj __projection = {}) const { return __unary(ranges::begin(__range), ranges::end(__range), std::move(__result), __operation, __projection); } - template <input_iterator _InIter1, sentinel_for<_InIter1> _Sent1, - input_iterator _InIter2, sentinel_for<_InIter2> _Sent2, + template <input_iterator _InIter1, + sentinel_for<_InIter1> _Sent1, + input_iterator _InIter2, + sentinel_for<_InIter2> _Sent2, weakly_incrementable _OutIter, copy_constructible _Func, class _Proj1 = identity, class _Proj2 = identity> - requires indirectly_writable<_OutIter, indirect_result_t<_Func&, projected<_InIter1, _Proj1>, - projected<_InIter2, _Proj2>>> - _LIBCPP_HIDE_FROM_ABI constexpr - binary_transform_result<_InIter1, _InIter2, _OutIter> operator()(_InIter1 __first1, _Sent1 __last1, - _InIter2 __first2, _Sent2 __last2, - _OutIter __result, - _Func __binary_operation, - _Proj1 __projection1 = {}, - _Proj2 __projection2 = {}) const { - return __binary(std::move(__first1), std::move(__last1), - std::move(__first2), std::move(__last2), - std::move(__result), - __binary_operation, - __projection1, - __projection2); + requires indirectly_writable<_OutIter, + indirect_result_t<_Func&, projected<_InIter1, _Proj1>, projected<_InIter2, _Proj2>>> + _LIBCPP_HIDE_FROM_ABI constexpr binary_transform_result<_InIter1, _InIter2, _OutIter> operator()( + _InIter1 __first1, + _Sent1 __last1, + _InIter2 __first2, + _Sent2 __last2, + _OutIter __result, + _Func __binary_operation, + _Proj1 __projection1 = {}, + _Proj2 __projection2 = {}) const { + return __binary( + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__last2), + std::move(__result), + __binary_operation, + __projection1, + __projection2); } template <input_range _Range1, @@ -137,34 +135,38 @@ public: copy_constructible _Func, class _Proj1 = identity, class _Proj2 = identity> - requires indirectly_writable<_OutIter, indirect_result_t<_Func&, projected<iterator_t<_Range1>, _Proj1>, - projected<iterator_t<_Range2>, _Proj2>>> - _LIBCPP_HIDE_FROM_ABI constexpr - binary_transform_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>, _OutIter> + requires indirectly_writable< + _OutIter, + indirect_result_t<_Func&, projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>>> + _LIBCPP_HIDE_FROM_ABI constexpr binary_transform_result<borrowed_iterator_t<_Range1>, + borrowed_iterator_t<_Range2>, + _OutIter> operator()(_Range1&& __range1, _Range2&& __range2, _OutIter __result, _Func __binary_operation, _Proj1 __projection1 = {}, _Proj2 __projection2 = {}) const { - return __binary(ranges::begin(__range1), ranges::end(__range1), - ranges::begin(__range2), ranges::end(__range2), - std::move(__result), - __binary_operation, - __projection1, - __projection2); + return __binary( + ranges::begin(__range1), + ranges::end(__range1), + ranges::begin(__range2), + ranges::end(__range2), + std::move(__result), + __binary_operation, + __projection1, + __projection2); } - }; } // namespace __transform inline namespace __cpo { - inline constexpr auto transform = __transform::__fn{}; +inline constexpr auto transform = __transform::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_TRANSFORM_H diff --git a/libcxx/include/__algorithm/ranges_unique.h b/libcxx/include/__algorithm/ranges_unique.h index be427ccf7fad..b17e01fc5057 100644 --- a/libcxx/include/__algorithm/ranges_unique.h +++ b/libcxx/include/__algorithm/ranges_unique.h @@ -32,48 +32,46 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __unique { - struct __fn { - template < - permutable _Iter, - sentinel_for<_Iter> _Sent, - class _Proj = identity, - indirect_equivalence_relation<projected<_Iter, _Proj>> _Comp = ranges::equal_to> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> - operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__unique<_RangeAlgPolicy>( - std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); - return {std::move(__ret.first), std::move(__ret.second)}; - } +struct __fn { + template <permutable _Iter, + sentinel_for<_Iter> _Sent, + class _Proj = identity, + indirect_equivalence_relation<projected<_Iter, _Proj>> _Comp = ranges::equal_to> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = + std::__unique<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + return {std::move(__ret.first), std::move(__ret.second)}; + } - template < - forward_range _Range, - class _Proj = identity, - indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to> - requires permutable<iterator_t<_Range>> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> - operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { - auto __ret = std::__unique<_RangeAlgPolicy>( - ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); - return {std::move(__ret.first), std::move(__ret.second)}; - } - }; + template <forward_range _Range, + class _Proj = identity, + indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to> + requires permutable<iterator_t<_Range>> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __ret = std::__unique<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); + return {std::move(__ret.first), std::move(__ret.second)}; + } +}; } // namespace __unique inline namespace __cpo { - inline constexpr auto unique = __unique::__fn{}; +inline constexpr auto unique = __unique::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_UNIQUE_H diff --git a/libcxx/include/__algorithm/ranges_unique_copy.h b/libcxx/include/__algorithm/ranges_unique_copy.h index 3ad47b06f5db..7e89f9d97af7 100644 --- a/libcxx/include/__algorithm/ranges_unique_copy.h +++ b/libcxx/include/__algorithm/ranges_unique_copy.h @@ -21,7 +21,6 @@ #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__iterator/projected.h> -#include <__iterator/readable_traits.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> @@ -33,7 +32,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -87,9 +86,9 @@ struct __fn { class _Proj = identity, indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to> requires indirectly_copyable<iterator_t<_Range>, _OutIter> && - (forward_iterator<iterator_t<_Range>> || - (input_iterator<_OutIter> && same_as<range_value_t<_Range>, iter_value_t<_OutIter>>) || - indirectly_copyable_storable<iterator_t<_Range>, _OutIter>) + (forward_iterator<iterator_t<_Range>> || + (input_iterator<_OutIter> && same_as<range_value_t<_Range>, iter_value_t<_OutIter>>) || + indirectly_copyable_storable<iterator_t<_Range>, _OutIter>) _LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result<borrowed_iterator_t<_Range>, _OutIter> operator()(_Range&& __range, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const { auto __ret = std::__unique_copy<_RangeAlgPolicy>( @@ -111,6 +110,6 @@ inline constexpr auto unique_copy = __unique_copy::__fn{}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H diff --git a/libcxx/include/__algorithm/ranges_upper_bound.h b/libcxx/include/__algorithm/ranges_upper_bound.h index a1340809048c..a12a0e39b084 100644 --- a/libcxx/include/__algorithm/ranges_upper_bound.h +++ b/libcxx/include/__algorithm/ranges_upper_bound.h @@ -25,51 +25,50 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __upper_bound { struct __fn { - template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity, + template <forward_iterator _Iter, + sentinel_for<_Iter> _Sent, + class _Type, + class _Proj = identity, indirect_strict_weak_order<const _Type*, projected<_Iter, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - _Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Iter + operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) { return !std::invoke(__comp, __rhs, __lhs); }; - return std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp_lhs_rhs_swapped, __proj); + return std::__lower_bound<_RangeAlgPolicy>(__first, __last, __value, __comp_lhs_rhs_swapped, __proj); } - template <forward_range _Range, class _Type, class _Proj = identity, + template <forward_range _Range, + class _Type, + class _Proj = identity, indirect_strict_weak_order<const _Type*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr - borrowed_iterator_t<_Range> operator()(_Range&& __r, - const _Type& __value, - _Comp __comp = {}, - _Proj __proj = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const { auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) { return !std::invoke(__comp, __rhs, __lhs); }; - return std::__lower_bound_impl<_RangeAlgPolicy>(ranges::begin(__r), - ranges::end(__r), - __value, - __comp_lhs_rhs_swapped, - __proj); + return std::__lower_bound<_RangeAlgPolicy>( + ranges::begin(__r), ranges::end(__r), __value, __comp_lhs_rhs_swapped, __proj); } }; } // namespace __upper_bound inline namespace __cpo { - inline constexpr auto upper_bound = __upper_bound::__fn{}; +inline constexpr auto upper_bound = __upper_bound::__fn{}; } // namespace __cpo } // namespace ranges _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_UPPER_BOUND_H diff --git a/libcxx/include/__algorithm/rotate.h b/libcxx/include/__algorithm/rotate.h index 8934ce095bbc..7ed6f18628c7 100644 --- a/libcxx/include/__algorithm/rotate.h +++ b/libcxx/include/__algorithm/rotate.h @@ -15,9 +15,9 @@ #include <__algorithm/swap_ranges.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_trivially_move_assignable.h> #include <__utility/move.h> #include <__utility/pair.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__algorithm/sample.h b/libcxx/include/__algorithm/sample.h index f403ba612580..c7a1898e5308 100644 --- a/libcxx/include/__algorithm/sample.h +++ b/libcxx/include/__algorithm/sample.h @@ -16,8 +16,8 @@ #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__random/uniform_int_distribution.h> +#include <__type_traits/common_type.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -77,7 +77,7 @@ _LIBCPP_INLINE_VISIBILITY _SampleIterator __sample(_PopulationIterator __first, _PopulationSentinel __last, _SampleIterator __output_iter, _Distance __n, _UniformRandomNumberGenerator& __g) { - _LIBCPP_ASSERT(__n >= 0, "N must be a positive number."); + _LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0, "N must be a positive number."); using _PopIterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_PopulationIterator>; using _Difference = typename _IterOps<_AlgPolicy>::template __difference_type<_PopulationIterator>; @@ -88,22 +88,22 @@ _SampleIterator __sample(_PopulationIterator __first, __g, _PopIterCategory()); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _PopulationIterator, class _SampleIterator, class _Distance, class _UniformRandomNumberGenerator> inline _LIBCPP_INLINE_VISIBILITY _SampleIterator sample(_PopulationIterator __first, _PopulationIterator __last, _SampleIterator __output_iter, _Distance __n, _UniformRandomNumberGenerator&& __g) { - static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value || - __is_cpp17_random_access_iterator<_SampleIterator>::value, + static_assert(__has_forward_iterator_category<_PopulationIterator>::value || + __has_random_access_iterator_category<_SampleIterator>::value, "SampleIterator must meet the requirements of RandomAccessIterator"); return std::__sample<_ClassicAlgPolicy>( std::move(__first), std::move(__last), std::move(__output_iter), __n, __g); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/search.h b/libcxx/include/__algorithm/search.h index 93771be39e35..5882a04808ba 100644 --- a/libcxx/include/__algorithm/search.h +++ b/libcxx/include/__algorithm/search.h @@ -14,12 +14,13 @@ #include <__algorithm/iterator_operations.h> #include <__config> #include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/advance.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/enable_if.h> #include <__type_traits/is_callable.h> #include <__utility/pair.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -126,8 +127,8 @@ pair<_Iter1, _Iter1> __search_impl(_Iter1 __first1, _Sent1 __last1, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2, - __enable_if_t<__is_cpp17_random_access_iterator<_Iter1>::value - && __is_cpp17_random_access_iterator<_Iter2>::value>* = nullptr) { + __enable_if_t<__has_random_access_iterator_category<_Iter1>::value + && __has_random_access_iterator_category<_Iter2>::value>* = nullptr) { auto __size2 = __last2 - __first2; if (__size2 == 0) @@ -158,10 +159,10 @@ pair<_Iter1, _Iter1> __search_impl(_Iter1 __first1, _Sent1 __last1, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2, - __enable_if_t<__is_cpp17_forward_iterator<_Iter1>::value - && __is_cpp17_forward_iterator<_Iter2>::value - && !(__is_cpp17_random_access_iterator<_Iter1>::value - && __is_cpp17_random_access_iterator<_Iter2>::value)>* = nullptr) { + __enable_if_t<__has_forward_iterator_category<_Iter1>::value + && __has_forward_iterator_category<_Iter2>::value + && !(__has_random_access_iterator_category<_Iter1>::value + && __has_random_access_iterator_category<_Iter2>::value)>* = nullptr) { return std::__search_forward_impl<_ClassicAlgPolicy>(__first1, __last1, __first2, __last2, __pred, @@ -187,7 +188,7 @@ _ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, return std::search(__first1, __last1, __first2, __last2, __equal_to()); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _ForwardIterator, class _Searcher> _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher& __s) { diff --git a/libcxx/include/__algorithm/search_n.h b/libcxx/include/__algorithm/search_n.h index 60a073565156..7e3ddf48a2b6 100644 --- a/libcxx/include/__algorithm/search_n.h +++ b/libcxx/include/__algorithm/search_n.h @@ -14,14 +14,15 @@ #include <__algorithm/iterator_operations.h> #include <__config> #include <__functional/identity.h> +#include <__functional/invoke.h> #include <__iterator/advance.h> #include <__iterator/concepts.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__ranges/concepts.h> +#include <__type_traits/is_callable.h> #include <__utility/convert_to_integral.h> #include <__utility/pair.h> -#include <type_traits> // __convert_to_integral #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -129,7 +130,7 @@ pair<_Iter, _Iter> __search_n_impl(_Iter __first, _Sent __last, const _Type& __value, _Pred& __pred, _Proj& __proj, - __enable_if_t<__is_cpp17_random_access_iterator<_Iter>::value>* = nullptr) { + __enable_if_t<__has_random_access_iterator_category<_Iter>::value>* = nullptr) { return std::__search_n_random_access_impl<_ClassicAlgPolicy>(__first, __last, __count, __value, @@ -149,8 +150,8 @@ pair<_Iter1, _Iter1> __search_n_impl(_Iter1 __first, _Sent1 __last, const _Type& __value, _Pred& __pred, _Proj& __proj, - __enable_if_t<__is_cpp17_forward_iterator<_Iter1>::value - && !__is_cpp17_random_access_iterator<_Iter1>::value>* = nullptr) { + __enable_if_t<__has_forward_iterator_category<_Iter1>::value + && !__has_random_access_iterator_category<_Iter1>::value>* = nullptr) { return std::__search_n_forward_impl<_ClassicAlgPolicy>(__first, __last, __count, __value, diff --git a/libcxx/include/__algorithm/set_difference.h b/libcxx/include/__algorithm/set_difference.h index cffdc8fc4fc0..26a300092c91 100644 --- a/libcxx/include/__algorithm/set_difference.h +++ b/libcxx/include/__algorithm/set_difference.h @@ -17,9 +17,9 @@ #include <__functional/identity.h> #include <__functional/invoke.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/remove_cvref.h> #include <__utility/move.h> #include <__utility/pair.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -66,14 +66,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_d _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) { - return std::__set_difference<_ClassicAlgPolicy>( - __first1, - __last1, - __first2, - __last2, - __result, - __less<typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>()).second; + return std::__set_difference<_ClassicAlgPolicy>(__first1, __last1, __first2, __last2, __result, __less<>()).second; } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/set_intersection.h b/libcxx/include/__algorithm/set_intersection.h index 9fa7799aee62..f2603fe1365a 100644 --- a/libcxx/include/__algorithm/set_intersection.h +++ b/libcxx/include/__algorithm/set_intersection.h @@ -89,8 +89,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_i std::move(__first2), std::move(__last2), std::move(__result), - __less<typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>()) + __less<>()) .__out_; } diff --git a/libcxx/include/__algorithm/set_symmetric_difference.h b/libcxx/include/__algorithm/set_symmetric_difference.h index bcb09587032b..832c3979bfd7 100644 --- a/libcxx/include/__algorithm/set_symmetric_difference.h +++ b/libcxx/include/__algorithm/set_symmetric_difference.h @@ -96,8 +96,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_symmetri std::move(__first2), std::move(__last2), std::move(__result), - __less<typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>()); + __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/set_union.h b/libcxx/include/__algorithm/set_union.h index 4d154b81e092..cf48adae03be 100644 --- a/libcxx/include/__algorithm/set_union.h +++ b/libcxx/include/__algorithm/set_union.h @@ -92,8 +92,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_union( std::move(__first2), std::move(__last2), std::move(__result), - __less<typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>()); + __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/shift_left.h b/libcxx/include/__algorithm/shift_left.h index 33f06d57e23a..023b56dcfcae 100644 --- a/libcxx/include/__algorithm/shift_left.h +++ b/libcxx/include/__algorithm/shift_left.h @@ -12,7 +12,6 @@ #include <__algorithm/move.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _ForwardIterator> inline _LIBCPP_INLINE_VISIBILITY constexpr @@ -33,7 +32,7 @@ shift_left(_ForwardIterator __first, _ForwardIterator __last, } _ForwardIterator __m = __first; - if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { + if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) { if (__n >= __last - __first) { return __first; } @@ -49,7 +48,7 @@ shift_left(_ForwardIterator __first, _ForwardIterator __last, return _VSTD::move(__m, __last, __first); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/shift_right.h b/libcxx/include/__algorithm/shift_right.h index 14bc761598b2..70aff45fe572 100644 --- a/libcxx/include/__algorithm/shift_right.h +++ b/libcxx/include/__algorithm/shift_right.h @@ -15,7 +15,6 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/swap.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _ForwardIterator> inline _LIBCPP_INLINE_VISIBILITY constexpr @@ -35,14 +34,14 @@ shift_right(_ForwardIterator __first, _ForwardIterator __last, return __first; } - if constexpr (__is_cpp17_random_access_iterator<_ForwardIterator>::value) { + if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) { decltype(__n) __d = __last - __first; if (__n >= __d) { return __last; } _ForwardIterator __m = __first + (__d - __n); return _VSTD::move_backward(__first, __m, __last); - } else if constexpr (__is_cpp17_bidirectional_iterator<_ForwardIterator>::value) { + } else if constexpr (__has_bidirectional_iterator_category<_ForwardIterator>::value) { _ForwardIterator __m = __last; for (; __n > 0; --__n) { if (__m == __first) { @@ -95,7 +94,7 @@ shift_right(_ForwardIterator __first, _ForwardIterator __last, } } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/shuffle.h b/libcxx/include/__algorithm/shuffle.h index f7bce68697b5..6fee88ca6ff2 100644 --- a/libcxx/include/__algorithm/shuffle.h +++ b/libcxx/include/__algorithm/shuffle.h @@ -11,7 +11,6 @@ #include <__algorithm/iterator_operations.h> #include <__config> -#include <__debug> #include <__iterator/iterator_traits.h> #include <__random/uniform_int_distribution.h> #include <__utility/forward.h> @@ -29,9 +28,9 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -class _LIBCPP_TYPE_VIS __libcpp_debug_randomizer { +class _LIBCPP_EXPORTED_FROM_ABI __libcpp_debug_randomizer { public: - __libcpp_debug_randomizer() { + _LIBCPP_HIDE_FROM_ABI __libcpp_debug_randomizer() { __state_ = __seed(); __inc_ = __state_ + 0xda3e39cb94b95bdbULL; __inc_ = (__inc_ << 1) | 1; @@ -65,11 +64,11 @@ private: #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_RANDOM_SHUFFLE) \ || defined(_LIBCPP_BUILDING_LIBRARY) -class _LIBCPP_TYPE_VIS __rs_default; +class _LIBCPP_EXPORTED_FROM_ABI __rs_default; -_LIBCPP_FUNC_VIS __rs_default __rs_get(); +_LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); -class _LIBCPP_TYPE_VIS __rs_default +class _LIBCPP_EXPORTED_FROM_ABI __rs_default { static unsigned __c_; @@ -85,13 +84,13 @@ public: result_type operator()(); - static _LIBCPP_CONSTEXPR result_type min() {return _Min;} - static _LIBCPP_CONSTEXPR result_type max() {return _Max;} + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type min() {return _Min;} + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() {return _Max;} - friend _LIBCPP_FUNC_VIS __rs_default __rs_get(); + friend _LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); }; -_LIBCPP_FUNC_VIS __rs_default __rs_get(); +_LIBCPP_EXPORTED_FROM_ABI __rs_default __rs_get(); template <class _RandomAccessIterator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void diff --git a/libcxx/include/__algorithm/sift_down.h b/libcxx/include/__algorithm/sift_down.h index e3972fb6f46e..20f0b0275dd9 100644 --- a/libcxx/include/__algorithm/sift_down.h +++ b/libcxx/include/__algorithm/sift_down.h @@ -19,6 +19,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> @@ -83,7 +86,7 @@ __floyd_sift_down(_RandomAccessIterator __first, _Compare&& __comp, typename iterator_traits<_RandomAccessIterator>::difference_type __len) { using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; - _LIBCPP_ASSERT(__len >= 2, "shouldn't be called unless __len >= 2"); + _LIBCPP_ASSERT_UNCATEGORIZED(__len >= 2, "shouldn't be called unless __len >= 2"); _RandomAccessIterator __hole = __first; _RandomAccessIterator __child_i = __first; @@ -111,4 +114,6 @@ __floyd_sift_down(_RandomAccessIterator __first, _Compare&& __comp, _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_SIFT_DOWN_H diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h index a7d2d55a06f8..3b594fa4d2a8 100644 --- a/libcxx/include/__algorithm/sort.h +++ b/libcxx/include/__algorithm/sort.h @@ -21,15 +21,15 @@ #include <__bit/countl.h> #include <__bit/countr.h> #include <__config> -#include <__debug> #include <__debug_utils/randomize_range.h> +#include <__debug_utils/strict_weak_ordering_check.h> #include <__functional/operations.h> #include <__functional/ranges_operations.h> #include <__iterator/iterator_traits.h> -#include <__memory/destruct_n.h> -#include <__memory/unique_ptr.h> #include <__type_traits/conditional.h> +#include <__type_traits/disjunction.h> #include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_constant_evaluated.h> #include <__utility/move.h> #include <__utility/pair.h> #include <climits> @@ -41,52 +41,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD -// Wraps an algorithm policy tag and a comparator in a single struct, used to pass the policy tag around without -// changing the number of template arguments (to keep the ABI stable). This is only used for the "range" policy tag. -// -// To create an object of this type, use `_WrapAlgPolicy<T, C>::type` -- see the specialization below for the rationale. -template <class _PolicyT, class _CompT, class = void> -struct _WrapAlgPolicy { - using type = _WrapAlgPolicy; - - using _AlgPolicy = _PolicyT; - using _Comp = _CompT; - _Comp& __comp; - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - _WrapAlgPolicy(_Comp& __c) : __comp(__c) {} -}; - -// Specialization for the "classic" policy tag that avoids creating a struct and simply defines an alias for the -// comparator. When unwrapping, a pristine comparator is always considered to have the "classic" tag attached. Passing -// the pristine comparator where possible allows using template instantiations from the dylib. -template <class _PolicyT, class _CompT> -struct _WrapAlgPolicy<_PolicyT, _CompT, __enable_if_t<std::is_same<_PolicyT, _ClassicAlgPolicy>::value> > { - using type = _CompT; -}; - -// Unwraps a pristine functor (e.g. `std::less`) as if it were wrapped using `_WrapAlgPolicy`. The policy tag is always -// set to "classic". -template <class _CompT> -struct _UnwrapAlgPolicy { - using _AlgPolicy = _ClassicAlgPolicy; - using _Comp = _CompT; - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static - _Comp __get_comp(_Comp __comp) { return __comp; } -}; - -// Unwraps a `_WrapAlgPolicy` struct. -template <class... _Ts> -struct _UnwrapAlgPolicy<_WrapAlgPolicy<_Ts...> > { - using _Wrapped = _WrapAlgPolicy<_Ts...>; - using _AlgPolicy = typename _Wrapped::_AlgPolicy; - using _Comp = typename _Wrapped::_Comp; - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static - _Comp __get_comp(_Wrapped& __w) { return __w.__comp; } -}; - // stable, 2-3 compares, 0-2 swaps template <class _AlgPolicy, class _Compare, class _ForwardIterator> @@ -130,77 +84,53 @@ _LIBCPP_CONSTEXPR_SINCE_CXX14 unsigned __sort3(_ForwardIterator __x, _ForwardIte template <class _AlgPolicy, class _Compare, class _ForwardIterator> _LIBCPP_HIDE_FROM_ABI -unsigned __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, +void __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _Compare __c) { using _Ops = _IterOps<_AlgPolicy>; - unsigned __r = std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c); + std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c); if (__c(*__x4, *__x3)) { _Ops::iter_swap(__x3, __x4); - ++__r; if (__c(*__x3, *__x2)) { _Ops::iter_swap(__x2, __x3); - ++__r; if (__c(*__x2, *__x1)) { _Ops::iter_swap(__x1, __x2); - ++__r; } } } - return __r; } // stable, 4-10 compares, 0-9 swaps -template <class _WrappedComp, class _ForwardIterator> -_LIBCPP_HIDDEN unsigned __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, - _ForwardIterator __x4, _ForwardIterator __x5, _WrappedComp __wrapped_comp) { - using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; - using _AlgPolicy = typename _Unwrap::_AlgPolicy; +template <class _AlgPolicy, class _Comp, class _ForwardIterator> +_LIBCPP_HIDE_FROM_ABI void __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, + _ForwardIterator __x4, _ForwardIterator __x5, _Comp __comp) { using _Ops = _IterOps<_AlgPolicy>; - using _Compare = typename _Unwrap::_Comp; - _Compare __c = _Unwrap::__get_comp(__wrapped_comp); - - unsigned __r = std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c); - if (__c(*__x5, *__x4)) { + std::__sort4<_AlgPolicy, _Comp>(__x1, __x2, __x3, __x4, __comp); + if (__comp(*__x5, *__x4)) { _Ops::iter_swap(__x4, __x5); - ++__r; - if (__c(*__x4, *__x3)) { + if (__comp(*__x4, *__x3)) { _Ops::iter_swap(__x3, __x4); - ++__r; - if (__c(*__x3, *__x2)) { + if (__comp(*__x3, *__x2)) { _Ops::iter_swap(__x2, __x3); - ++__r; - if (__c(*__x2, *__x1)) { + if (__comp(*__x2, *__x1)) { _Ops::iter_swap(__x1, __x2); - ++__r; } } } } - return __r; -} - -template <class _AlgPolicy, class _Compare, class _ForwardIterator> -_LIBCPP_HIDE_FROM_ABI unsigned __sort5_wrap_policy( - _ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _ForwardIterator __x5, - _Compare __c) { - using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type; - _WrappedComp __wrapped_comp(__c); - return std::__sort5<_WrappedComp, _ForwardIterator>( - std::move(__x1), std::move(__x2), std::move(__x3), std::move(__x4), std::move(__x5), __wrapped_comp); } // The comparator being simple is a prerequisite for using the branchless optimization. template <class _Tp> struct __is_simple_comparator : false_type {}; -template <class _Tp> -struct __is_simple_comparator<__less<_Tp>&> : true_type {}; +template <> +struct __is_simple_comparator<__less<>&> : true_type {}; template <class _Tp> struct __is_simple_comparator<less<_Tp>&> : true_type {}; template <class _Tp> struct __is_simple_comparator<greater<_Tp>&> : true_type {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <> struct __is_simple_comparator<ranges::less&> : true_type {}; template <> @@ -209,7 +139,7 @@ struct __is_simple_comparator<ranges::greater&> : true_type {}; template <class _Compare, class _Iter, class _Tp = typename iterator_traits<_Iter>::value_type> using __use_branchless_sort = - integral_constant<bool, __is_cpp17_contiguous_iterator<_Iter>::value && sizeof(_Tp) <= sizeof(void*) && + integral_constant<bool, __libcpp_is_contiguous_iterator<_Iter>::value && sizeof(_Tp) <= sizeof(void*) && is_arithmetic<_Tp>::value && __is_simple_comparator<_Compare>::value>; namespace __detail { @@ -299,7 +229,8 @@ template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void> __sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) { - std::__sort5_wrap_policy<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __x5, __c); + std::__sort5<_AlgPolicy, _Compare, _RandomAccessIterator>( + std::move(__x1), std::move(__x2), std::move(__x3), std::move(__x4), std::move(__x5), __c); } // Assumes size > 0 @@ -344,17 +275,18 @@ void __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __l // Sort the iterator range [__first, __last) using the comparator __comp using // the insertion sort algorithm. Insertion sort has two loops, outer and inner. -// The implementation below has not bounds check (unguarded) for the inner loop. +// The implementation below has no bounds check (unguarded) for the inner loop. // Assumes that there is an element in the position (__first - 1) and that each // element in the input range is greater or equal to the element at __first - 1. template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> _LIBCPP_HIDE_FROM_ABI void -__insertion_sort_unguarded(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { +__insertion_sort_unguarded(_RandomAccessIterator const __first, _RandomAccessIterator __last, _Compare __comp) { using _Ops = _IterOps<_AlgPolicy>; typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; if (__first == __last) return; + const _RandomAccessIterator __leftmost = __first - difference_type(1); (void)__leftmost; // can be unused when assertions are disabled for (_RandomAccessIterator __i = __first + difference_type(1); __i != __last; ++__i) { _RandomAccessIterator __j = __i - difference_type(1); if (__comp(*__i, *__j)) { @@ -364,22 +296,20 @@ __insertion_sort_unguarded(_RandomAccessIterator __first, _RandomAccessIterator do { *__j = _Ops::__iter_move(__k); __j = __k; + _LIBCPP_ASSERT_UNCATEGORIZED( + __k != __leftmost, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); } while (__comp(__t, *--__k)); // No need for bounds check due to the assumption stated above. *__j = std::move(__t); } } } -template <class _WrappedComp, class _RandomAccessIterator> -_LIBCPP_HIDDEN bool __insertion_sort_incomplete( - _RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { - using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; - using _AlgPolicy = typename _Unwrap::_AlgPolicy; +template <class _AlgPolicy, class _Comp, class _RandomAccessIterator> +_LIBCPP_HIDE_FROM_ABI bool __insertion_sort_incomplete( + _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) { using _Ops = _IterOps<_AlgPolicy>; - using _Compare = typename _Unwrap::_Comp; - _Compare __comp = _Unwrap::__get_comp(__wrapped_comp); - typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; switch (__last - __first) { case 0: @@ -390,21 +320,21 @@ _LIBCPP_HIDDEN bool __insertion_sort_incomplete( _Ops::iter_swap(__first, __last); return true; case 3: - std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp); + std::__sort3_maybe_branchless<_AlgPolicy, _Comp>(__first, __first + difference_type(1), --__last, __comp); return true; case 4: - std::__sort4_maybe_branchless<_AlgPolicy, _Compare>( + std::__sort4_maybe_branchless<_AlgPolicy, _Comp>( __first, __first + difference_type(1), __first + difference_type(2), --__last, __comp); return true; case 5: - std::__sort5_maybe_branchless<_AlgPolicy, _Compare>( + std::__sort5_maybe_branchless<_AlgPolicy, _Comp>( __first, __first + difference_type(1), __first + difference_type(2), __first + difference_type(3), --__last, __comp); return true; } typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; _RandomAccessIterator __j = __first + difference_type(2); - std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), __j, __comp); + std::__sort3_maybe_branchless<_AlgPolicy, _Comp>(__first, __first + difference_type(1), __j, __comp); const unsigned __limit = 8; unsigned __count = 0; for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) { @@ -425,37 +355,6 @@ _LIBCPP_HIDDEN bool __insertion_sort_incomplete( return true; } -template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> -_LIBCPP_HIDE_FROM_ABI -void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __last1, - typename iterator_traits<_BidirectionalIterator>::value_type* __first2, _Compare __comp) { - using _Ops = _IterOps<_AlgPolicy>; - - typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; - if (__first1 != __last1) { - __destruct_n __d(0); - unique_ptr<value_type, __destruct_n&> __h(__first2, __d); - value_type* __last2 = __first2; - ::new ((void*)__last2) value_type(_Ops::__iter_move(__first1)); - __d.template __incr<value_type>(); - for (++__last2; ++__first1 != __last1; ++__last2) { - value_type* __j2 = __last2; - value_type* __i2 = __j2; - if (__comp(*__first1, *--__i2)) { - ::new ((void*)__j2) value_type(std::move(*__i2)); - __d.template __incr<value_type>(); - for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2) - *__j2 = std::move(*__i2); - *__j2 = _Ops::__iter_move(__first1); - } else { - ::new ((void*)__j2) value_type(_Ops::__iter_move(__first1)); - __d.template __incr<value_type>(); - } - } - __h.release(); - } -} - template <class _AlgPolicy, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos( _RandomAccessIterator __first, _RandomAccessIterator __last, uint64_t& __left_bitset, uint64_t& __right_bitset) { @@ -464,11 +363,11 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos( // Swap one pair on each iteration as long as both bitsets have at least one // element for swapping. while (__left_bitset != 0 && __right_bitset != 0) { - difference_type tz_left = __libcpp_ctz(__left_bitset); - __left_bitset = __libcpp_blsr(__left_bitset); - difference_type tz_right = __libcpp_ctz(__right_bitset); - __right_bitset = __libcpp_blsr(__right_bitset); - _Ops::iter_swap(__first + tz_left, __last - tz_right); + difference_type __tz_left = __libcpp_ctz(__left_bitset); + __left_bitset = __libcpp_blsr(__left_bitset); + difference_type __tz_right = __libcpp_ctz(__right_bitset); + __right_bitset = __libcpp_blsr(__right_bitset); + _Ops::iter_swap(__first + __tz_left, __last - __tz_right); } } @@ -533,9 +432,9 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks( // Record the comparison outcomes for the elements currently on the left side. if (__left_bitset == 0) { _RandomAccessIterator __iter = __first; - for (int j = 0; j < __l_size; j++) { + for (int __j = 0; __j < __l_size; __j++) { bool __comp_result = !__comp(*__iter, __pivot); - __left_bitset |= (static_cast<uint64_t>(__comp_result) << j); + __left_bitset |= (static_cast<uint64_t>(__comp_result) << __j); ++__iter; } } @@ -543,9 +442,9 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks( // side. if (__right_bitset == 0) { _RandomAccessIterator __iter = __lm1; - for (int j = 0; j < __r_size; j++) { + for (int __j = 0; __j < __r_size; __j++) { bool __comp_result = __comp(*__iter, __pivot); - __right_bitset |= (static_cast<uint64_t>(__comp_result) << j); + __right_bitset |= (static_cast<uint64_t>(__comp_result) << __j); --__iter; } } @@ -565,9 +464,9 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within( while (__left_bitset != 0) { difference_type __tz_left = __detail::__block_size - 1 - __libcpp_clz(__left_bitset); __left_bitset &= (static_cast<uint64_t>(1) << __tz_left) - 1; - _RandomAccessIterator it = __first + __tz_left; - if (it != __lm1) { - _Ops::iter_swap(it, __lm1); + _RandomAccessIterator __it = __first + __tz_left; + if (__it != __lm1) { + _Ops::iter_swap(__it, __lm1); } --__lm1; } @@ -578,9 +477,9 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within( while (__right_bitset != 0) { difference_type __tz_right = __detail::__block_size - 1 - __libcpp_clz(__right_bitset); __right_bitset &= (static_cast<uint64_t>(1) << __tz_right) - 1; - _RandomAccessIterator it = __lm1 - __tz_right; - if (it != __first) { - _Ops::iter_swap(it, __first); + _RandomAccessIterator __it = __lm1 - __tz_right; + if (__it != __first) { + _Ops::iter_swap(__it, __first); } ++__first; } @@ -601,15 +500,20 @@ __bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, using _Ops = _IterOps<_AlgPolicy>; typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type; - _LIBCPP_ASSERT(__last - __first >= difference_type(3), ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__last - __first >= difference_type(3), ""); + const _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around + const _RandomAccessIterator __end = __last; (void)__end; // - _RandomAccessIterator __begin = __first; value_type __pivot(_Ops::__iter_move(__first)); // Find the first element greater than the pivot. if (__comp(__pivot, *(__last - difference_type(1)))) { // Not guarded since we know the last element is greater than the pivot. - while (!__comp(__pivot, *++__first)) { - } + do { + ++__first; + _LIBCPP_ASSERT_UNCATEGORIZED( + __first != __end, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (!__comp(__pivot, *__first)); } else { while (++__first < __last && !__comp(__pivot, *__first)) { } @@ -618,8 +522,12 @@ __bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, if (__first < __last) { // It will be always guarded because __introsort will do the median-of-three // before calling this. - while (__comp(__pivot, *--__last)) { - } + do { + _LIBCPP_ASSERT_UNCATEGORIZED( + __last != __begin, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + --__last; + } while (__comp(__pivot, *__last)); } // If the first element greater than the pivot is at or after the // last element less than or equal to the pivot, then we have covered the @@ -683,14 +591,19 @@ __partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIte using _Ops = _IterOps<_AlgPolicy>; typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; - _LIBCPP_ASSERT(__last - __first >= difference_type(3), ""); - _RandomAccessIterator __begin = __first; + _LIBCPP_ASSERT_UNCATEGORIZED(__last - __first >= difference_type(3), ""); + const _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around + const _RandomAccessIterator __end = __last; (void)__end; // value_type __pivot(_Ops::__iter_move(__first)); // Find the first element greater or equal to the pivot. It will be always // guarded because __introsort will do the median-of-three before calling // this. - while (__comp(*++__first, __pivot)) - ; + do { + ++__first; + _LIBCPP_ASSERT_UNCATEGORIZED( + __first != __end, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (__comp(*__first, __pivot)); // Find the last element less than the pivot. if (__begin == __first - difference_type(1)) { @@ -698,8 +611,12 @@ __partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIte ; } else { // Guarded. - while (!__comp(*--__last, __pivot)) - ; + do { + _LIBCPP_ASSERT_UNCATEGORIZED( + __last != __begin, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + --__last; + } while (!__comp(*__last, __pivot)); } // If the first element greater than or equal to the pivot is at or after the @@ -711,10 +628,18 @@ __partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIte // correct side of the pivot. while (__first < __last) { _Ops::iter_swap(__first, __last); - while (__comp(*++__first, __pivot)) - ; - while (!__comp(*--__last, __pivot)) - ; + do { + ++__first; + _LIBCPP_ASSERT_UNCATEGORIZED( + __first != __end, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (__comp(*__first, __pivot)); + do { + _LIBCPP_ASSERT_UNCATEGORIZED( + __last != __begin, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + --__last; + } while (!__comp(*__last, __pivot)); } // Move the pivot to its correct position. _RandomAccessIterator __pivot_pos = __first - difference_type(1); @@ -733,12 +658,18 @@ __partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIter using _Ops = _IterOps<_AlgPolicy>; typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type; - _RandomAccessIterator __begin = __first; + // TODO(LLVM18): Make __begin const, see https://reviews.llvm.org/D147089#4349748 + _RandomAccessIterator __begin = __first; // used for bounds checking, those are not moved around + const _RandomAccessIterator __end = __last; (void)__end; // value_type __pivot(_Ops::__iter_move(__first)); if (__comp(__pivot, *(__last - difference_type(1)))) { // Guarded. - while (!__comp(__pivot, *++__first)) { - } + do { + ++__first; + _LIBCPP_ASSERT_UNCATEGORIZED( + __first != __end, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (!__comp(__pivot, *__first)); } else { while (++__first < __last && !__comp(__pivot, *__first)) { } @@ -747,15 +678,27 @@ __partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIter if (__first < __last) { // It will be always guarded because __introsort will do the // median-of-three before calling this. - while (__comp(__pivot, *--__last)) { - } + do { + _LIBCPP_ASSERT_UNCATEGORIZED( + __last != __begin, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + --__last; + } while (__comp(__pivot, *__last)); } while (__first < __last) { _Ops::iter_swap(__first, __last); - while (!__comp(__pivot, *++__first)) - ; - while (__comp(__pivot, *--__last)) - ; + do { + ++__first; + _LIBCPP_ASSERT_UNCATEGORIZED( + __first != __end, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + } while (!__comp(__pivot, *__first)); + do { + _LIBCPP_ASSERT_UNCATEGORIZED( + __last != __begin, + "Would read out of bounds, does your comparator satisfy the strict-weak ordering requirement?"); + --__last; + } while (__comp(__pivot, *__last)); } _RandomAccessIterator __pivot_pos = __first - difference_type(1); if (__begin != __pivot_pos) { @@ -862,10 +805,8 @@ void __introsort(_RandomAccessIterator __first, // [__first, __i) < *__i and *__i <= [__i+1, __last) // If we were given a perfect partition, see if insertion sort is quick... if (__ret.second) { - using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type; - _WrappedComp __wrapped_comp(__comp); - bool __fs = std::__insertion_sort_incomplete<_WrappedComp>(__first, __i, __wrapped_comp); - if (std::__insertion_sort_incomplete<_WrappedComp>(__i + difference_type(1), __last, __wrapped_comp)) { + bool __fs = std::__insertion_sort_incomplete<_AlgPolicy, _Compare>(__first, __i, __comp); + if (std::__insertion_sort_incomplete<_AlgPolicy, _Compare>(__i + difference_type(1), __last, __comp)) { if (__fs) return; __last = __i; @@ -904,84 +845,107 @@ inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) { return __log2; } -template <class _WrappedComp, class _RandomAccessIterator> -_LIBCPP_HIDDEN void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) { +template <class _Comp, class _RandomAccessIterator> +void __sort(_RandomAccessIterator, _RandomAccessIterator, _Comp); + +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<char>&, char*>(char*, char*, __less<char>&); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); +#endif +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<short>&, short*>(short*, short*, __less<short>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<int>&, int*>(int*, int*, __less<int>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<long>&, long*>(long*, long*, __less<long>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<long long>&, long long*>(long long*, long long*, __less<long long>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<float>&, float*>(float*, float*, __less<float>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<double>&, double*>(double*, double*, __less<double>&); +extern template _LIBCPP_EXPORTED_FROM_ABI void __sort<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); + +template <class _AlgPolicy, class _RandomAccessIterator, class _Comp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void +__sort_dispatch(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; difference_type __depth_limit = 2 * std::__log2i(__last - __first); - using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>; - using _AlgPolicy = typename _Unwrap::_AlgPolicy; - using _Compare = typename _Unwrap::_Comp; - _Compare __comp = _Unwrap::__get_comp(__wrapped_comp); // Only use bitset partitioning for arithmetic types. We should also check // that the default comparator is in use so that we are sure that there are no // branches in the comparator. std::__introsort<_AlgPolicy, - _Compare, + _Comp&, _RandomAccessIterator, - __use_branchless_sort<_Compare, _RandomAccessIterator>::value>( + __use_branchless_sort<_Comp, _RandomAccessIterator>::value>( __first, __last, __comp, __depth_limit); } -template <class _Compare, class _Tp> -inline _LIBCPP_INLINE_VISIBILITY void __sort(_Tp** __first, _Tp** __last, __less<_Tp*>&) { - __less<uintptr_t> __comp; - std::__sort<__less<uintptr_t>&, uintptr_t*>((uintptr_t*)__first, (uintptr_t*)__last, __comp); -} +template <class _Type, class... _Options> +using __is_any_of = _Or<is_same<_Type, _Options>...>; -extern template _LIBCPP_FUNC_VIS void __sort<__less<char>&, char*>(char*, char*, __less<char>&); +template <class _Type> +using __sort_is_specialized_in_library = __is_any_of< + _Type, + char, #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -extern template _LIBCPP_FUNC_VIS void __sort<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); + wchar_t, #endif -extern template _LIBCPP_FUNC_VIS void __sort<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<short>&, short*>(short*, short*, __less<short>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<int>&, int*>(int*, int*, __less<int>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<long>&, long*>(long*, long*, __less<long>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<long long>&, long long*>(long long*, long long*, __less<long long>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<float>&, float*>(float*, float*, __less<float>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<double>&, double*>(double*, double*, __less<double>&); -extern template _LIBCPP_FUNC_VIS void __sort<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); - -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<char>&, char*>(char*, char*, __less<char>&); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); + signed char, + unsigned char, + short, + unsigned short, + int, + unsigned int, + long, + unsigned long, + long long, + unsigned long long, + float, + double, + long double>; + +template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, __less<>&) { + __less<_Type> __comp; + std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); +} + +template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, less<_Type>&) { + __less<_Type> __comp; + std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); +} + +#if _LIBCPP_STD_VER >= 14 +template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, less<>&) { + __less<_Type> __comp; + std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); +} +#endif + +#if _LIBCPP_STD_VER >= 20 +template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, ranges::less&) { + __less<_Type> __comp; + std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp); +} #endif -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<short>&, short*>(short*, short*, __less<short>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<int>&, int*>(int*, int*, __less<int>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long>&, long*>(long*, long*, __less<long>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long long>&, long long*>(long long*, long long*, __less<long long>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<float>&, float*>(float*, float*, __less<float>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<double>&, double*>(double*, double*, __less<double>&); -extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); - -extern template _LIBCPP_FUNC_VIS unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&); template <class _AlgPolicy, class _RandomAccessIterator, class _Comp> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { std::__debug_randomize_range<_AlgPolicy>(__first, __last); - using _Comp_ref = __comp_ref_type<_Comp>; if (__libcpp_is_constant_evaluated()) { - std::__partial_sort<_AlgPolicy>(__first, __last, __last, __comp); - + std::__partial_sort<_AlgPolicy>( + std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__last), __comp); } else { - using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Comp_ref>::type; - _Comp_ref __comp_ref(__comp); - _WrappedComp __wrapped_comp(__comp_ref); - std::__sort<_WrappedComp>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __wrapped_comp); + std::__sort_dispatch<_AlgPolicy>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp); } + std::__check_strict_weak_ordering_sorted(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp); } template <class _RandomAccessIterator, class _Comp> @@ -993,7 +957,7 @@ void sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __c template <class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void sort(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::sort(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); + std::sort(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/sort_heap.h b/libcxx/include/__algorithm/sort_heap.h index 8249407b5509..a82926ed1cca 100644 --- a/libcxx/include/__algorithm/sort_heap.h +++ b/libcxx/include/__algorithm/sort_heap.h @@ -14,9 +14,11 @@ #include <__algorithm/iterator_operations.h> #include <__algorithm/pop_heap.h> #include <__config> +#include <__debug_utils/strict_weak_ordering_check.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -27,11 +29,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _AlgPolicy, class _Compare, class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) { + _RandomAccessIterator __saved_last = __last; __comp_ref_type<_Compare> __comp_ref = __comp; using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type; for (difference_type __n = __last - __first; __n > 1; --__last, (void) --__n) std::__pop_heap<_AlgPolicy>(__first, __last, __comp_ref, __n); + std::__check_strict_weak_ordering_sorted(__first, __saved_last, __comp_ref); } template <class _RandomAccessIterator, class _Compare> @@ -46,8 +50,7 @@ void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com template <class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::sort_heap(std::move(__first), std::move(__last), - __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); + std::sort_heap(std::move(__first), std::move(__last), __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/stable_partition.h b/libcxx/include/__algorithm/stable_partition.h index a49de6dbb0ef..38fa9ce37d00 100644 --- a/libcxx/include/__algorithm/stable_partition.h +++ b/libcxx/include/__algorithm/stable_partition.h @@ -21,7 +21,6 @@ #include <__utility/move.h> #include <__utility/pair.h> #include <new> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -123,7 +122,10 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) { - const unsigned __alloc_limit = 3; // might want to make this a function of trivial assignment + typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; + typedef typename iterator_traits<_ForwardIterator>::value_type value_type; + + const difference_type __alloc_limit = 3; // might want to make this a function of trivial assignment // Either prove all true and return __first or point to first false while (true) { @@ -135,8 +137,6 @@ __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Pred } // We now have a reduced range [__first, __last) // *__first is known to be false - typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; - typedef typename iterator_traits<_ForwardIterator>::value_type value_type; difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last); pair<value_type*, ptrdiff_t> __p(0, 0); unique_ptr<value_type, __return_temporary_buffer> __h; diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h index 8e70978ab61c..dc24218b74dd 100644 --- a/libcxx/include/__algorithm/stable_sort.h +++ b/libcxx/include/__algorithm/stable_sort.h @@ -15,14 +15,15 @@ #include <__algorithm/iterator_operations.h> #include <__algorithm/sort.h> #include <__config> +#include <__debug_utils/strict_weak_ordering_check.h> #include <__iterator/iterator_traits.h> #include <__memory/destruct_n.h> #include <__memory/temporary_buffer.h> #include <__memory/unique_ptr.h> +#include <__type_traits/is_trivially_copy_assignable.h> #include <__utility/move.h> #include <__utility/pair.h> #include <new> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -30,6 +31,37 @@ _LIBCPP_BEGIN_NAMESPACE_STD +template <class _AlgPolicy, class _Compare, class _BidirectionalIterator> +_LIBCPP_HIDE_FROM_ABI +void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __last1, + typename iterator_traits<_BidirectionalIterator>::value_type* __first2, _Compare __comp) { + using _Ops = _IterOps<_AlgPolicy>; + + typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; + if (__first1 != __last1) { + __destruct_n __d(0); + unique_ptr<value_type, __destruct_n&> __h(__first2, __d); + value_type* __last2 = __first2; + ::new ((void*)__last2) value_type(_Ops::__iter_move(__first1)); + __d.template __incr<value_type>(); + for (++__last2; ++__first1 != __last1; ++__last2) { + value_type* __j2 = __last2; + value_type* __i2 = __j2; + if (__comp(*__first1, *--__i2)) { + ::new ((void*)__j2) value_type(std::move(*__i2)); + __d.template __incr<value_type>(); + for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2) + *__j2 = std::move(*__i2); + *__j2 = _Ops::__iter_move(__first1); + } else { + ::new ((void*)__j2) value_type(_Ops::__iter_move(__first1)); + __d.template __incr<value_type>(); + } + } + __h.release(); + } +} + template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2> _LIBCPP_HIDE_FROM_ABI void __merge_move_construct(_InputIterator1 __first1, _InputIterator1 __last1, @@ -228,6 +260,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP } std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __last, __comp, __len, __buf.first, __buf.second); + std::__check_strict_weak_ordering_sorted(__first, __last, __comp); } template <class _RandomAccessIterator, class _Compare> @@ -239,7 +272,7 @@ void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C template <class _RandomAccessIterator> inline _LIBCPP_HIDE_FROM_ABI void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) { - std::stable_sort(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>()); + std::stable_sort(__first, __last, __less<>()); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/three_way_comp_ref_type.h b/libcxx/include/__algorithm/three_way_comp_ref_type.h new file mode 100644 index 000000000000..19c102f4c96c --- /dev/null +++ b/libcxx/include/__algorithm/three_way_comp_ref_type.h @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ALGORITHM_THREE_WAY_COMP_REF_TYPE_H +#define _LIBCPP___ALGORITHM_THREE_WAY_COMP_REF_TYPE_H + +#include <__compare/ordering.h> +#include <__config> +#include <__utility/declval.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <class _Comp> +struct __debug_three_way_comp { + _Comp& __comp_; + _LIBCPP_HIDE_FROM_ABI constexpr __debug_three_way_comp(_Comp& __c) : __comp_(__c) {} + + template <class _Tp, class _Up> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(const _Tp& __x, const _Up& __y) { + auto __r = __comp_(__x, __y); + if constexpr (__comparison_category<decltype(__comp_(__x, __y))>) + __do_compare_assert(__y, __x, __r); + return __r; + } + + template <class _Tp, class _Up> + _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __x, _Up& __y) { + auto __r = __comp_(__x, __y); + if constexpr (__comparison_category<decltype(__comp_(__x, __y))>) + __do_compare_assert(__y, __x, __r); + return __r; + } + + template <class _LHS, class _RHS, class _Order> + _LIBCPP_HIDE_FROM_ABI constexpr void __do_compare_assert(_LHS& __l, _RHS& __r, _Order __o) { + _Order __expected = __o; + if (__o == _Order::less) + __expected = _Order::greater; + if (__o == _Order::greater) + __expected = _Order::less; + _LIBCPP_ASSERT(__comp_(__l, __r) == __expected, "Comparator does not induce a strict weak ordering"); + (void)__l; + (void)__r; + } +}; + +// Pass the comparator by lvalue reference. Or in debug mode, using a +// debugging wrapper that stores a reference. +# if _LIBCPP_ENABLE_DEBUG_MODE +template <class _Comp> +using __three_way_comp_ref_type = __debug_three_way_comp<_Comp>; +# else +template <class _Comp> +using __three_way_comp_ref_type = _Comp&; +# endif + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ALGORITHM_THREE_WAY_COMP_REF_TYPE_H diff --git a/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h b/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h index 1e86074b3dbd..1f2039949d74 100644 --- a/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h +++ b/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h @@ -11,13 +11,13 @@ #include <__config> #include <__functional/invoke.h> -#include <type_traits> +#include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_PUSH_MACROS #include <__undef_macros> @@ -57,6 +57,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H diff --git a/libcxx/include/__algorithm/unwrap_iter.h b/libcxx/include/__algorithm/unwrap_iter.h index 0f661e10a74d..91346e3c1bd2 100644 --- a/libcxx/include/__algorithm/unwrap_iter.h +++ b/libcxx/include/__algorithm/unwrap_iter.h @@ -21,24 +21,27 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // TODO: Change the name of __unwrap_iter_impl to something more appropriate // The job of __unwrap_iter is to remove iterator wrappers (like reverse_iterator or __wrap_iter), // to reduce the number of template instantiations and to enable pointer-based optimizations e.g. in std::copy. -// In debug mode, we don't do this. // // Some algorithms (e.g. std::copy, but not std::sort) need to convert an // "unwrapped" result back into the original iterator type. Doing that is the job of __rewrap_iter. // Default case - we can't unwrap anything -template <class _Iter, bool = __is_cpp17_contiguous_iterator<_Iter>::value> +template <class _Iter, bool = __libcpp_is_contiguous_iterator<_Iter>::value> struct __unwrap_iter_impl { static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap(_Iter, _Iter __iter) { return __iter; } static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __unwrap(_Iter __i) _NOEXCEPT { return __i; } }; -#ifndef _LIBCPP_ENABLE_DEBUG_MODE +// TODO(hardening): make sure that the following unwrapping doesn't unexpectedly turn hardened iterators into raw +// pointers. // It's a contiguous iterator, so we can use a raw pointer instead template <class _Iter> @@ -54,8 +57,6 @@ struct __unwrap_iter_impl<_Iter, true> { } }; -#endif // !_LIBCPP_ENABLE_DEBUG_MODE - template<class _Iter, class _Impl = __unwrap_iter_impl<_Iter>, __enable_if_t<is_copy_constructible<_Iter>::value, int> = 0> @@ -64,6 +65,14 @@ decltype(_Impl::__unwrap(std::declval<_Iter>())) __unwrap_iter(_Iter __i) _NOEXC return _Impl::__unwrap(__i); } +// Allow input_iterators to be passed to __unwrap_iter (but not __rewrap_iter) +#if _LIBCPP_STD_VER >= 20 +template <class _Iter, __enable_if_t<!is_copy_constructible<_Iter>::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI constexpr _Iter __unwrap_iter(_Iter __i) noexcept { + return __i; +} +#endif + template <class _OrigIter, class _Iter, class _Impl = __unwrap_iter_impl<_OrigIter> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _OrigIter __rewrap_iter(_OrigIter __orig_iter, _Iter __iter) _NOEXCEPT { return _Impl::__rewrap(std::move(__orig_iter), std::move(__iter)); @@ -71,4 +80,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _OrigIter __rewrap_iter(_OrigIter __orig _LIBCPP_END_NAMESPACE_STD +_LIBCPP_PUSH_MACROS + #endif // _LIBCPP___ALGORITHM_UNWRAP_ITER_H diff --git a/libcxx/include/__algorithm/unwrap_range.h b/libcxx/include/__algorithm/unwrap_range.h index 2c5d23e69f10..2c75c8f49de9 100644 --- a/libcxx/include/__algorithm/unwrap_range.h +++ b/libcxx/include/__algorithm/unwrap_range.h @@ -28,7 +28,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // __unwrap_iter and __rewrap_iter don't work for this, because they assume that the iterator and sentinel have // the same type. __unwrap_range tries to get two iterators and then forward to __unwrap_iter. -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Iter, class _Sent> struct __unwrap_range_impl { _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __sent) @@ -43,7 +43,7 @@ struct __unwrap_range_impl { } _LIBCPP_HIDE_FROM_ABI static constexpr auto - __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter) + __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(std::move(__orig_iter))) __iter) requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter> { return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); @@ -80,7 +80,7 @@ template < _LIBCPP_HIDE_FROM_ABI constexpr _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) { return __unwrap_range_impl<_Iter, _Sent>::__rewrap(std::move(__orig_iter), std::move(__iter)); } -#else // _LIBCPP_STD_VER > 17 +#else // _LIBCPP_STD_VER >= 20 template <class _Iter, class _Unwrapped = decltype(std::__unwrap_iter(std::declval<_Iter>()))> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair<_Unwrapped, _Unwrapped> __unwrap_range(_Iter __first, _Iter __last) { return std::make_pair(std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))); @@ -90,7 +90,7 @@ template <class _Iter, class _Unwrapped = decltype(std::__unwrap_iter(std::declv _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) { return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter)); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/upper_bound.h b/libcxx/include/__algorithm/upper_bound.h index 96552ce1f8ac..f499f7a80aa6 100644 --- a/libcxx/include/__algorithm/upper_bound.h +++ b/libcxx/include/__algorithm/upper_bound.h @@ -25,6 +25,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _AlgPolicy, class _Compare, class _Iter, class _Sent, class _Tp, class _Proj> @@ -47,8 +50,7 @@ __upper_bound(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp template <class _ForwardIterator, class _Tp, class _Compare> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) { - static_assert(is_copy_constructible<_ForwardIterator>::value, - "Iterator has to be copy constructible"); + static_assert(is_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible"); return std::__upper_bound<_ClassicAlgPolicy>( std::move(__first), std::move(__last), __value, std::move(__comp), std::__identity()); } @@ -56,13 +58,11 @@ upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu template <class _ForwardIterator, class _Tp> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { - return std::upper_bound( - std::move(__first), - std::move(__last), - __value, - __less<_Tp, typename iterator_traits<_ForwardIterator>::value_type>()); + return std::upper_bound(std::move(__first), std::move(__last), __value, __less<>()); } _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_UPPER_BOUND_H diff --git a/libcxx/include/__assert b/libcxx/include/__assert index 9c0cd1b1192a..d4af7e6c7192 100644 --- a/libcxx/include/__assert +++ b/libcxx/include/__assert @@ -17,39 +17,21 @@ # pragma GCC system_header #endif -// TODO: Remove in LLVM 17. -#if defined(_LIBCPP_DEBUG) -# error "Defining _LIBCPP_DEBUG is not supported anymore. Please use _LIBCPP_ENABLE_DEBUG_MODE instead." -#endif - -// Automatically enable assertions when the debug mode is enabled. -#if defined(_LIBCPP_ENABLE_DEBUG_MODE) -# ifndef _LIBCPP_ENABLE_ASSERTIONS -# define _LIBCPP_ENABLE_ASSERTIONS 1 -# endif -#endif - -#ifndef _LIBCPP_ENABLE_ASSERTIONS -# define _LIBCPP_ENABLE_ASSERTIONS _LIBCPP_ENABLE_ASSERTIONS_DEFAULT -#endif - -#if _LIBCPP_ENABLE_ASSERTIONS != 0 && _LIBCPP_ENABLE_ASSERTIONS != 1 -# error "_LIBCPP_ENABLE_ASSERTIONS must be set to 0 or 1" -#endif - -#if _LIBCPP_ENABLE_ASSERTIONS -# define _LIBCPP_ASSERT(expression, message) \ - (__builtin_expect(static_cast<bool>(expression), 1) ? \ - (void)0 : \ - _LIBCPP_VERBOSE_ABORT("%s:%d: assertion %s failed: %s", __FILE__, __LINE__, #expression, message)) -#elif !defined(_LIBCPP_ASSERTIONS_DISABLE_ASSUME) && __has_builtin(__builtin_assume) -# define _LIBCPP_ASSERT(expression, message) \ - (_LIBCPP_DIAGNOSTIC_PUSH \ - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wassume") \ - __builtin_assume(static_cast<bool>(expression)) \ - _LIBCPP_DIAGNOSTIC_POP) +#define _LIBCPP_ASSERT(expression, message) \ + (__builtin_expect(static_cast<bool>(expression), 1) \ + ? (void)0 \ + : _LIBCPP_VERBOSE_ABORT( \ + "%s:%d: assertion %s failed: %s\n", __builtin_FILE(), __builtin_LINE(), #expression, message)) + +// TODO: __builtin_assume can currently inhibit optimizations. Until this has been fixed and we can add +// assumptions without a clear optimization intent, disable that to avoid worsening the code generation. +// See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a discussion. +#if 0 && __has_builtin(__builtin_assume) +# define _LIBCPP_ASSUME(expression) \ + (_LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wassume") \ + __builtin_assume(static_cast<bool>(expression)) _LIBCPP_DIAGNOSTIC_POP) #else -# define _LIBCPP_ASSERT(expression, message) ((void)0) +# define _LIBCPP_ASSUME(expression) ((void)0) #endif #endif // _LIBCPP___ASSERT diff --git a/libcxx/include/__atomic/aliases.h b/libcxx/include/__atomic/aliases.h new file mode 100644 index 000000000000..e2f9fae4094e --- /dev/null +++ b/libcxx/include/__atomic/aliases.h @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_ALIASES_H +#define _LIBCPP___ATOMIC_ALIASES_H + +#include <__atomic/atomic.h> +#include <__atomic/atomic_lock_free.h> +#include <__atomic/contention_t.h> +#include <__atomic/is_always_lock_free.h> +#include <__config> +#include <__type_traits/conditional.h> +#include <cstddef> +#include <cstdint> +#include <cstdlib> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +using atomic_bool = atomic<bool>; +using atomic_char = atomic<char>; +using atomic_schar = atomic<signed char>; +using atomic_uchar = atomic<unsigned char>; +using atomic_short = atomic<short>; +using atomic_ushort = atomic<unsigned short>; +using atomic_int = atomic<int>; +using atomic_uint = atomic<unsigned int>; +using atomic_long = atomic<long>; +using atomic_ulong = atomic<unsigned long>; +using atomic_llong = atomic<long long>; +using atomic_ullong = atomic<unsigned long long>; +#ifndef _LIBCPP_HAS_NO_CHAR8_T +using atomic_char8_t = atomic<char8_t>; +#endif +using atomic_char16_t = atomic<char16_t>; +using atomic_char32_t = atomic<char32_t>; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using atomic_wchar_t = atomic<wchar_t>; +#endif + +using atomic_int_least8_t = atomic<int_least8_t>; +using atomic_uint_least8_t = atomic<uint_least8_t>; +using atomic_int_least16_t = atomic<int_least16_t>; +using atomic_uint_least16_t = atomic<uint_least16_t>; +using atomic_int_least32_t = atomic<int_least32_t>; +using atomic_uint_least32_t = atomic<uint_least32_t>; +using atomic_int_least64_t = atomic<int_least64_t>; +using atomic_uint_least64_t = atomic<uint_least64_t>; + +using atomic_int_fast8_t = atomic<int_fast8_t>; +using atomic_uint_fast8_t = atomic<uint_fast8_t>; +using atomic_int_fast16_t = atomic<int_fast16_t>; +using atomic_uint_fast16_t = atomic<uint_fast16_t>; +using atomic_int_fast32_t = atomic<int_fast32_t>; +using atomic_uint_fast32_t = atomic<uint_fast32_t>; +using atomic_int_fast64_t = atomic<int_fast64_t>; +using atomic_uint_fast64_t = atomic<uint_fast64_t>; + +using atomic_int8_t = atomic< int8_t>; +using atomic_uint8_t = atomic<uint8_t>; +using atomic_int16_t = atomic< int16_t>; +using atomic_uint16_t = atomic<uint16_t>; +using atomic_int32_t = atomic< int32_t>; +using atomic_uint32_t = atomic<uint32_t>; +using atomic_int64_t = atomic< int64_t>; +using atomic_uint64_t = atomic<uint64_t>; + +using atomic_intptr_t = atomic<intptr_t>; +using atomic_uintptr_t = atomic<uintptr_t>; +using atomic_size_t = atomic<size_t>; +using atomic_ptrdiff_t = atomic<ptrdiff_t>; +using atomic_intmax_t = atomic<intmax_t>; +using atomic_uintmax_t = atomic<uintmax_t>; + +// atomic_*_lock_free : prefer the contention type most highly, then the largest lock-free type + +#if _LIBCPP_STD_VER >= 17 +# define _LIBCPP_CONTENTION_LOCK_FREE ::std::__libcpp_is_always_lock_free<__cxx_contention_t>::__value +#else +# define _LIBCPP_CONTENTION_LOCK_FREE false +#endif + +#if ATOMIC_LLONG_LOCK_FREE == 2 +using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, long long>; +using __libcpp_unsigned_lock_free = + __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned long long>; +#elif ATOMIC_INT_LOCK_FREE == 2 +using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, int>; +using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned int>; +#elif ATOMIC_SHORT_LOCK_FREE == 2 +using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, short>; +using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned short>; +#elif ATOMIC_CHAR_LOCK_FREE == 2 +using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, char>; +using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned char>; +#else +// No signed/unsigned lock-free types +# define _LIBCPP_NO_LOCK_FREE_TYPES +#endif + +#if !defined(_LIBCPP_NO_LOCK_FREE_TYPES) +using atomic_signed_lock_free = atomic<__libcpp_signed_lock_free>; +using atomic_unsigned_lock_free = atomic<__libcpp_unsigned_lock_free>; +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_ALIASES_H diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h new file mode 100644 index 000000000000..68df7f12c1e5 --- /dev/null +++ b/libcxx/include/__atomic/atomic.h @@ -0,0 +1,664 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_ATOMIC_H +#define _LIBCPP___ATOMIC_ATOMIC_H + +#include <__atomic/atomic_base.h> +#include <__atomic/check_memory_order.h> +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/memory_order.h> +#include <__config> +#include <__memory/addressof.h> +#include <__type_traits/is_function.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_pointer.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp> +struct atomic + : public __atomic_base<_Tp> +{ + using __base = __atomic_base<_Tp>; + using value_type = _Tp; + using difference_type = value_type; + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI + atomic() = default; +#else + _LIBCPP_HIDE_FROM_ABI + atomic() _NOEXCEPT = default; +#endif + + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {} + + _LIBCPP_HIDE_FROM_ABI + _Tp operator=(_Tp __d) volatile _NOEXCEPT + {__base::store(__d); return __d;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator=(_Tp __d) _NOEXCEPT + {__base::store(__d); return __d;} + + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; +}; + +// atomic<T*> + +template <class _Tp> +struct atomic<_Tp*> + : public __atomic_base<_Tp*> +{ + using __base = __atomic_base<_Tp*>; + using value_type = _Tp*; + using difference_type = ptrdiff_t; + + _LIBCPP_HIDE_FROM_ABI + atomic() _NOEXCEPT = default; + + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {} + + _LIBCPP_HIDE_FROM_ABI + _Tp* operator=(_Tp* __d) volatile _NOEXCEPT + {__base::store(__d); return __d;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator=(_Tp* __d) _NOEXCEPT + {__base::store(__d); return __d;} + + _LIBCPP_HIDE_FROM_ABI + _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + // __atomic_fetch_add accepts function pointers, guard against them. + static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI + _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + // __atomic_fetch_add accepts function pointers, guard against them. + static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI + _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + // __atomic_fetch_add accepts function pointers, guard against them. + static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI + _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + // __atomic_fetch_add accepts function pointers, guard against them. + static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI + _Tp* operator++(int) volatile _NOEXCEPT {return fetch_add(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator++(int) _NOEXCEPT {return fetch_add(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator--(int) volatile _NOEXCEPT {return fetch_sub(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator--(int) _NOEXCEPT {return fetch_sub(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator++() volatile _NOEXCEPT {return fetch_add(1) + 1;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator++() _NOEXCEPT {return fetch_add(1) + 1;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator--() volatile _NOEXCEPT {return fetch_sub(1) - 1;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator--() _NOEXCEPT {return fetch_sub(1) - 1;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT {return fetch_add(__op) + __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT {return fetch_sub(__op) - __op;} + + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; +}; + +// atomic_is_lock_free + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool +atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT +{ + return __o->is_lock_free(); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool +atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT +{ + return __o->is_lock_free(); +} + +// atomic_init + +template <class _Tp> +_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI +void +atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + std::__cxx_atomic_init(std::addressof(__o->__a_), __d); +} + +template <class _Tp> +_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI +void +atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + std::__cxx_atomic_init(std::addressof(__o->__a_), __d); +} + +// atomic_store + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +void +atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + __o->store(__d); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +void +atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + __o->store(__d); +} + +// atomic_store_explicit + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +void +atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) +{ + __o->store(__d, __m); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +void +atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) +{ + __o->store(__d, __m); +} + +// atomic_load + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT +{ + return __o->load(); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_load(const atomic<_Tp>* __o) _NOEXCEPT +{ + return __o->load(); +} + +// atomic_load_explicit + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) +{ + return __o->load(__m); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) +{ + return __o->load(__m); +} + +// atomic_exchange + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->exchange(__d); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->exchange(__d); +} + +// atomic_exchange_explicit + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT +{ + return __o->exchange(__d, __m); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT +{ + return __o->exchange(__d, __m); +} + +// atomic_compare_exchange_weak + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->compare_exchange_weak(*__e, __d); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_weak(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->compare_exchange_weak(*__e, __d); +} + +// atomic_compare_exchange_strong + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->compare_exchange_strong(*__e, __d); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_strong(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT +{ + return __o->compare_exchange_strong(*__e, __d); +} + +// atomic_compare_exchange_weak_explicit + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, + typename atomic<_Tp>::value_type __d, + memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) +{ + return __o->compare_exchange_weak(*__e, __d, __s, __f); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_weak_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, + memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) +{ + return __o->compare_exchange_weak(*__e, __d, __s, __f); +} + +// atomic_compare_exchange_strong_explicit + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_strong_explicit(volatile atomic<_Tp>* __o, + typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, + memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) +{ + return __o->compare_exchange_strong(*__e, __d, __s, __f); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool +atomic_compare_exchange_strong_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, + typename atomic<_Tp>::value_type __d, + memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) +{ + return __o->compare_exchange_strong(*__e, __d, __s, __f); +} + +// atomic_wait + +template <class _Tp> +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_wait(const volatile atomic<_Tp>* __o, + typename atomic<_Tp>::value_type __v) _NOEXCEPT +{ + return __o->wait(__v); +} + +template <class _Tp> +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_wait(const atomic<_Tp>* __o, + typename atomic<_Tp>::value_type __v) _NOEXCEPT +{ + return __o->wait(__v); +} + +// atomic_wait_explicit + +template <class _Tp> +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_wait_explicit(const volatile atomic<_Tp>* __o, + typename atomic<_Tp>::value_type __v, + memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) +{ + return __o->wait(__v, __m); +} + +template <class _Tp> +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_wait_explicit(const atomic<_Tp>* __o, + typename atomic<_Tp>::value_type __v, + memory_order __m) _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) +{ + return __o->wait(__v, __m); +} + +// atomic_notify_one + +template <class _Tp> +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT +{ + __o->notify_one(); +} +template <class _Tp> +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT +{ + __o->notify_one(); +} + +// atomic_notify_all + +template <class _Tp> +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT +{ + __o->notify_all(); +} +template <class _Tp> +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI +void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT +{ + __o->notify_all(); +} + +// atomic_fetch_add + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT +{ + return __o->fetch_add(__op); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp +atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT +{ + return __o->fetch_add(__op); +} + +// atomic_fetch_add_explicit + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_add_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_add(__op, __m); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_add(__op, __m); +} + +// atomic_fetch_sub + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT +{ + return __o->fetch_sub(__op); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT +{ + return __o->fetch_sub(__op); +} + +// atomic_fetch_sub_explicit + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_sub_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_sub(__op, __m); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_sub(__op, __m); +} + +// atomic_fetch_and + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_and(__op); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_and(__op); +} + +// atomic_fetch_and_explicit + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_and_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_and(__op, __m); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_and(__op, __m); +} + +// atomic_fetch_or + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_or(__op); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_or(__op); +} + +// atomic_fetch_or_explicit + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_or(__op, __m); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_or(__op, __m); +} + +// atomic_fetch_xor + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_xor(__op); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT +{ + return __o->fetch_xor(__op); +} + +// atomic_fetch_xor_explicit + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_xor_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_xor(__op, __m); +} + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +typename enable_if +< + is_integral<_Tp>::value && !is_same<_Tp, bool>::value, + _Tp +>::type +atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT +{ + return __o->fetch_xor(__op, __m); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_ATOMIC_H diff --git a/libcxx/include/__atomic/atomic_base.h b/libcxx/include/__atomic/atomic_base.h new file mode 100644 index 000000000000..87100ba5d8a5 --- /dev/null +++ b/libcxx/include/__atomic/atomic_base.h @@ -0,0 +1,232 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_ATOMIC_BASE_H +#define _LIBCPP___ATOMIC_ATOMIC_BASE_H + +#include <__atomic/atomic_sync.h> +#include <__atomic/check_memory_order.h> +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/is_always_lock_free.h> +#include <__atomic/memory_order.h> +#include <__availability> +#include <__config> +#include <__memory/addressof.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_same.h> +#include <version> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp, bool = is_integral<_Tp>::value && !is_same<_Tp, bool>::value> +struct __atomic_base // false +{ + mutable __cxx_atomic_impl<_Tp> __a_; + +#if _LIBCPP_STD_VER >= 17 + static _LIBCPP_CONSTEXPR bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value; +#endif + + _LIBCPP_HIDE_FROM_ABI + bool is_lock_free() const volatile _NOEXCEPT + {return __cxx_atomic_is_lock_free(sizeof(_Tp));} + _LIBCPP_HIDE_FROM_ABI + bool is_lock_free() const _NOEXCEPT + {return static_cast<__atomic_base const volatile*>(this)->is_lock_free();} + _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { + std::__cxx_atomic_store(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { + std::__cxx_atomic_store(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { + return std::__cxx_atomic_load(std::addressof(__a_), __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { + return std::__cxx_atomic_load(std::addressof(__a_), __m); + } + _LIBCPP_HIDE_FROM_ABI + operator _Tp() const volatile _NOEXCEPT {return load();} + _LIBCPP_HIDE_FROM_ABI + operator _Tp() const _NOEXCEPT {return load();} + _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const + volatile _NOEXCEPT { + std::__cxx_atomic_wait(std::addressof(__a_), __v, __m); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void + wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT { + std::__cxx_atomic_wait(std::addressof(__a_), __v, __m); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { + std::__cxx_atomic_notify_one(std::addressof(__a_)); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { + std::__cxx_atomic_notify_one(std::addressof(__a_)); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { + std::__cxx_atomic_notify_all(std::addressof(__a_)); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { + std::__cxx_atomic_notify_all(std::addressof(__a_)); + } + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI constexpr + __atomic_base() noexcept(is_nothrow_default_constructible_v<_Tp>) : __a_(_Tp()) {} +#else + _LIBCPP_HIDE_FROM_ABI + __atomic_base() _NOEXCEPT = default; +#endif + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR + __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {} + + __atomic_base(const __atomic_base&) = delete; +}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp, bool __b> +_LIBCPP_CONSTEXPR bool __atomic_base<_Tp, __b>::is_always_lock_free; +#endif + +// atomic<Integral> + +template <class _Tp> +struct __atomic_base<_Tp, true> + : public __atomic_base<_Tp, false> +{ + using __base = __atomic_base<_Tp, false>; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + __atomic_base() _NOEXCEPT = default; + + _LIBCPP_HIDE_FROM_ABI + _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {} + + _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI + _Tp operator++(int) volatile _NOEXCEPT {return fetch_add(_Tp(1));} + _LIBCPP_HIDE_FROM_ABI + _Tp operator++(int) _NOEXCEPT {return fetch_add(_Tp(1));} + _LIBCPP_HIDE_FROM_ABI + _Tp operator--(int) volatile _NOEXCEPT {return fetch_sub(_Tp(1));} + _LIBCPP_HIDE_FROM_ABI + _Tp operator--(int) _NOEXCEPT {return fetch_sub(_Tp(1));} + _LIBCPP_HIDE_FROM_ABI + _Tp operator++() volatile _NOEXCEPT {return fetch_add(_Tp(1)) + _Tp(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp operator++() _NOEXCEPT {return fetch_add(_Tp(1)) + _Tp(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp operator--() volatile _NOEXCEPT {return fetch_sub(_Tp(1)) - _Tp(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp operator--() _NOEXCEPT {return fetch_sub(_Tp(1)) - _Tp(1);} + _LIBCPP_HIDE_FROM_ABI + _Tp operator+=(_Tp __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator+=(_Tp __op) _NOEXCEPT {return fetch_add(__op) + __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator-=(_Tp __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator-=(_Tp __op) _NOEXCEPT {return fetch_sub(__op) - __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator&=(_Tp __op) volatile _NOEXCEPT {return fetch_and(__op) & __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator&=(_Tp __op) _NOEXCEPT {return fetch_and(__op) & __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator|=(_Tp __op) volatile _NOEXCEPT {return fetch_or(__op) | __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator|=(_Tp __op) _NOEXCEPT {return fetch_or(__op) | __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator^=(_Tp __op) volatile _NOEXCEPT {return fetch_xor(__op) ^ __op;} + _LIBCPP_HIDE_FROM_ABI + _Tp operator^=(_Tp __op) _NOEXCEPT {return fetch_xor(__op) ^ __op;} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_ATOMIC_BASE_H diff --git a/libcxx/include/__atomic/atomic_flag.h b/libcxx/include/__atomic/atomic_flag.h new file mode 100644 index 000000000000..edfa978f9935 --- /dev/null +++ b/libcxx/include/__atomic/atomic_flag.h @@ -0,0 +1,230 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_ATOMIC_FLAG_H +#define _LIBCPP___ATOMIC_ATOMIC_FLAG_H + +#include <__atomic/atomic_sync.h> +#include <__atomic/contention_t.h> +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/memory_order.h> +#include <__chrono/duration.h> +#include <__config> +#include <__threading_support> +#include <cstdint> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct atomic_flag +{ + __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE> __a_; + + _LIBCPP_HIDE_FROM_ABI + bool test(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT + {return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m);} + _LIBCPP_HIDE_FROM_ABI + bool test(memory_order __m = memory_order_seq_cst) const _NOEXCEPT + {return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m);} + + _LIBCPP_HIDE_FROM_ABI + bool test_and_set(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT + {return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m);} + _LIBCPP_HIDE_FROM_ABI + bool test_and_set(memory_order __m = memory_order_seq_cst) _NOEXCEPT + {return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m);} + _LIBCPP_HIDE_FROM_ABI + void clear(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT + {__cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m);} + _LIBCPP_HIDE_FROM_ABI + void clear(memory_order __m = memory_order_seq_cst) _NOEXCEPT + {__cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m);} + + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void wait(bool __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT + {__cxx_atomic_wait(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);} + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT + {__cxx_atomic_wait(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);} + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void notify_one() volatile _NOEXCEPT + {__cxx_atomic_notify_one(&__a_);} + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void notify_one() _NOEXCEPT + {__cxx_atomic_notify_one(&__a_);} + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void notify_all() volatile _NOEXCEPT + {__cxx_atomic_notify_all(&__a_);} + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI + void notify_all() _NOEXCEPT + {__cxx_atomic_notify_all(&__a_);} + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI constexpr + atomic_flag() _NOEXCEPT : __a_(false) {} +#else + atomic_flag() _NOEXCEPT = default; +#endif + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR + atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION + + atomic_flag(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) volatile = delete; + +}; + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT +{ + return __o->test(); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test(const atomic_flag* __o) _NOEXCEPT +{ + return __o->test(); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + return __o->test(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + return __o->test(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT +{ + return __o->test_and_set(); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT +{ + return __o->test_and_set(); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + return __o->test_and_set(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +bool +atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + return __o->test_and_set(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT +{ + __o->clear(); +} + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_flag_clear(atomic_flag* __o) _NOEXCEPT +{ + __o->clear(); +} + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + __o->clear(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT +{ + __o->clear(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT +{ + __o->wait(__v); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT +{ + __o->wait(__v); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_wait_explicit(const volatile atomic_flag* __o, + bool __v, memory_order __m) _NOEXCEPT +{ + __o->wait(__v, __m); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_wait_explicit(const atomic_flag* __o, + bool __v, memory_order __m) _NOEXCEPT +{ + __o->wait(__v, __m); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT +{ + __o->notify_one(); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT +{ + __o->notify_one(); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT +{ + __o->notify_all(); +} + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_SYNC +void +atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT +{ + __o->notify_all(); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_ATOMIC_FLAG_H diff --git a/libcxx/include/__atomic/atomic_init.h b/libcxx/include/__atomic/atomic_init.h new file mode 100644 index 000000000000..14310aee10c1 --- /dev/null +++ b/libcxx/include/__atomic/atomic_init.h @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_ATOMIC_INIT_H +#define _LIBCPP___ATOMIC_ATOMIC_INIT_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#define ATOMIC_FLAG_INIT {false} +#define ATOMIC_VAR_INIT(__v) {__v} + +#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) +# if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1400 +# pragma clang deprecated(ATOMIC_VAR_INIT) +# endif +#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) + +#endif // _LIBCPP___ATOMIC_ATOMIC_INIT_H diff --git a/libcxx/include/__atomic/atomic_lock_free.h b/libcxx/include/__atomic/atomic_lock_free.h new file mode 100644 index 000000000000..d607569ed07d --- /dev/null +++ b/libcxx/include/__atomic/atomic_lock_free.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_ATOMIC_LOCK_FREE_H +#define _LIBCPP___ATOMIC_ATOMIC_LOCK_FREE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if defined(__CLANG_ATOMIC_BOOL_LOCK_FREE) +# define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE +# define ATOMIC_CHAR_LOCK_FREE __CLANG_ATOMIC_CHAR_LOCK_FREE +#ifndef _LIBCPP_HAS_NO_CHAR8_T +# define ATOMIC_CHAR8_T_LOCK_FREE __CLANG_ATOMIC_CHAR8_T_LOCK_FREE +#endif +# define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE +# define ATOMIC_CHAR32_T_LOCK_FREE __CLANG_ATOMIC_CHAR32_T_LOCK_FREE +# define ATOMIC_WCHAR_T_LOCK_FREE __CLANG_ATOMIC_WCHAR_T_LOCK_FREE +# define ATOMIC_SHORT_LOCK_FREE __CLANG_ATOMIC_SHORT_LOCK_FREE +# define ATOMIC_INT_LOCK_FREE __CLANG_ATOMIC_INT_LOCK_FREE +# define ATOMIC_LONG_LOCK_FREE __CLANG_ATOMIC_LONG_LOCK_FREE +# define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE +# define ATOMIC_POINTER_LOCK_FREE __CLANG_ATOMIC_POINTER_LOCK_FREE +#elif defined(__GCC_ATOMIC_BOOL_LOCK_FREE) +# define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE +# define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE +#ifndef _LIBCPP_HAS_NO_CHAR8_T +# define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE +#endif +# define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE +# define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE +# define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE +# define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +# define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +# define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +# define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +# define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE +#endif + +#endif // _LIBCPP___ATOMIC_ATOMIC_LOCK_FREE_H diff --git a/libcxx/include/__atomic/atomic_sync.h b/libcxx/include/__atomic/atomic_sync.h new file mode 100644 index 000000000000..d55450bb5f9c --- /dev/null +++ b/libcxx/include/__atomic/atomic_sync.h @@ -0,0 +1,112 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_ATOMIC_SYNC_H +#define _LIBCPP___ATOMIC_ATOMIC_SYNC_H + +#include <__atomic/contention_t.h> +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/memory_order.h> +#include <__availability> +#include <__chrono/duration.h> +#include <__config> +#include <__memory/addressof.h> +#include <__thread/poll_with_backoff.h> +#include <__threading_support> +#include <__type_traits/decay.h> +#include <cstring> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_THREADS + +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(void const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(void const volatile*, __cxx_contention_t); + +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*); +_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t); + +template <class _Atp, class _Fn> +struct __libcpp_atomic_wait_backoff_impl { + _Atp* __a; + _Fn __test_fn; + _LIBCPP_AVAILABILITY_SYNC + _LIBCPP_HIDE_FROM_ABI bool operator()(chrono::nanoseconds __elapsed) const + { + if(__elapsed > chrono::microseconds(64)) + { + auto const __monitor = std::__libcpp_atomic_monitor(__a); + if(__test_fn()) + return true; + std::__libcpp_atomic_wait(__a, __monitor); + } + else if(__elapsed > chrono::microseconds(4)) + __libcpp_thread_yield(); + else + {} // poll + return false; + } +}; + +template <class _Atp, class _Fn> +_LIBCPP_AVAILABILITY_SYNC +_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_wait(_Atp* __a, _Fn && __test_fn) +{ + __libcpp_atomic_wait_backoff_impl<_Atp, __decay_t<_Fn> > __backoff_fn = {__a, __test_fn}; + return std::__libcpp_thread_poll_with_backoff(__test_fn, __backoff_fn); +} + +#else // _LIBCPP_HAS_NO_THREADS + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_notify_all(__cxx_atomic_impl<_Tp> const volatile*) { } +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI void __cxx_atomic_notify_one(__cxx_atomic_impl<_Tp> const volatile*) { } +template <class _Atp, class _Fn> +_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_wait(_Atp*, _Fn && __test_fn) +{ + return std::__libcpp_thread_poll_with_backoff(__test_fn, __spinning_backoff_policy()); +} + +#endif // _LIBCPP_HAS_NO_THREADS + +template <typename _Tp> _LIBCPP_HIDE_FROM_ABI +bool __cxx_nonatomic_compare_equal(_Tp const& __lhs, _Tp const& __rhs) { + return std::memcmp(std::addressof(__lhs), std::addressof(__rhs), sizeof(_Tp)) == 0; +} + +template <class _Atp, class _Tp> +struct __cxx_atomic_wait_test_fn_impl { + _Atp* __a; + _Tp __val; + memory_order __order; + _LIBCPP_HIDE_FROM_ABI bool operator()() const + { + return !std::__cxx_nonatomic_compare_equal(std::__cxx_atomic_load(__a, __order), __val); + } +}; + +template <class _Atp, class _Tp> +_LIBCPP_AVAILABILITY_SYNC +_LIBCPP_HIDE_FROM_ABI bool __cxx_atomic_wait(_Atp* __a, _Tp const __val, memory_order __order) +{ + __cxx_atomic_wait_test_fn_impl<_Atp, _Tp> __test_fn = {__a, __val, __order}; + return std::__cxx_atomic_wait(__a, __test_fn); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_ATOMIC_SYNC_H diff --git a/libcxx/include/__atomic/check_memory_order.h b/libcxx/include/__atomic/check_memory_order.h new file mode 100644 index 000000000000..d744312122bd --- /dev/null +++ b/libcxx/include/__atomic/check_memory_order.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_CHECK_MEMORY_ORDER_H +#define _LIBCPP___ATOMIC_CHECK_MEMORY_ORDER_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#define _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) \ + _LIBCPP_DIAGNOSE_WARNING(__m == memory_order_consume || \ + __m == memory_order_acquire || \ + __m == memory_order_acq_rel, \ + "memory order argument to atomic operation is invalid") + +#define _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) \ + _LIBCPP_DIAGNOSE_WARNING(__m == memory_order_release || \ + __m == memory_order_acq_rel, \ + "memory order argument to atomic operation is invalid") + +#define _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__m, __f) \ + _LIBCPP_DIAGNOSE_WARNING(__f == memory_order_release || \ + __f == memory_order_acq_rel, \ + "memory order argument to atomic operation is invalid") + +#endif // _LIBCPP___ATOMIC_CHECK_MEMORY_ORDER_H diff --git a/libcxx/include/__atomic/contention_t.h b/libcxx/include/__atomic/contention_t.h new file mode 100644 index 000000000000..1d8d02430b4f --- /dev/null +++ b/libcxx/include/__atomic/contention_t.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_CONTENTION_T_H +#define _LIBCPP___ATOMIC_CONTENTION_T_H + +#include <__atomic/cxx_atomic_impl.h> +#include <__config> +#include <cstdint> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if defined(__linux__) || (defined(_AIX) && !defined(__64BIT__)) + using __cxx_contention_t = int32_t; +#else + using __cxx_contention_t = int64_t; +#endif // __linux__ || (_AIX && !__64BIT__) + +using __cxx_atomic_contention_t = __cxx_atomic_impl<__cxx_contention_t>; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_CONTENTION_T_H diff --git a/libcxx/include/__atomic/cxx_atomic_impl.h b/libcxx/include/__atomic/cxx_atomic_impl.h new file mode 100644 index 000000000000..167cee7f0bde --- /dev/null +++ b/libcxx/include/__atomic/cxx_atomic_impl.h @@ -0,0 +1,831 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H +#define _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H + +#include <__atomic/is_always_lock_free.h> +#include <__atomic/memory_order.h> +#include <__config> +#include <__memory/addressof.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_trivially_copyable.h> +#include <__type_traits/remove_const.h> +#include <cstddef> +#include <cstring> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) || \ + defined(_LIBCPP_ATOMIC_ONLY_USE_BUILTINS) + +// [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because +// the default operator= in an object is not volatile, a byte-by-byte copy +// is required. +template <typename _Tp, typename _Tv> _LIBCPP_HIDE_FROM_ABI +typename enable_if<is_assignable<_Tp&, _Tv>::value>::type +__cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) { + __a_value = __val; +} +template <typename _Tp, typename _Tv> _LIBCPP_HIDE_FROM_ABI +typename enable_if<is_assignable<_Tp&, _Tv>::value>::type +__cxx_atomic_assign_volatile(_Tp volatile& __a_value, _Tv volatile const& __val) { + volatile char* __to = reinterpret_cast<volatile char*>(std::addressof(__a_value)); + volatile char* __end = __to + sizeof(_Tp); + volatile const char* __from = reinterpret_cast<volatile const char*>(std::addressof(__val)); + while (__to != __end) + *__to++ = *__from++; +} + +#endif + +#if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) + +template <typename _Tp> +struct __cxx_atomic_base_impl { + + _LIBCPP_HIDE_FROM_ABI +#ifndef _LIBCPP_CXX03_LANG + __cxx_atomic_base_impl() _NOEXCEPT = default; +#else + __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {} +#endif // _LIBCPP_CXX03_LANG + _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp value) _NOEXCEPT + : __a_value(value) {} + _Tp __a_value; +}; + +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_order(memory_order __order) { + // Avoid switch statement to make this a constexpr. + return __order == memory_order_relaxed ? __ATOMIC_RELAXED: + (__order == memory_order_acquire ? __ATOMIC_ACQUIRE: + (__order == memory_order_release ? __ATOMIC_RELEASE: + (__order == memory_order_seq_cst ? __ATOMIC_SEQ_CST: + (__order == memory_order_acq_rel ? __ATOMIC_ACQ_REL: + __ATOMIC_CONSUME)))); +} + +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int __to_gcc_failure_order(memory_order __order) { + // Avoid switch statement to make this a constexpr. + return __order == memory_order_relaxed ? __ATOMIC_RELAXED: + (__order == memory_order_acquire ? __ATOMIC_ACQUIRE: + (__order == memory_order_release ? __ATOMIC_RELAXED: + (__order == memory_order_seq_cst ? __ATOMIC_SEQ_CST: + (__order == memory_order_acq_rel ? __ATOMIC_ACQUIRE: + __ATOMIC_CONSUME)))); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { + __cxx_atomic_assign_volatile(__a->__a_value, __val); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { + __a->__a_value = __val; +} + +_LIBCPP_HIDE_FROM_ABI inline +void __cxx_atomic_thread_fence(memory_order __order) { + __atomic_thread_fence(__to_gcc_order(__order)); +} + +_LIBCPP_HIDE_FROM_ABI inline +void __cxx_atomic_signal_fence(memory_order __order) { + __atomic_signal_fence(__to_gcc_order(__order)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, + memory_order __order) { + __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, + memory_order __order) { + __atomic_store(std::addressof(__a->__a_value), std::addressof(__val), __to_gcc_order(__order)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(const volatile __cxx_atomic_base_impl<_Tp>* __a, + memory_order __order) { + _Tp __ret; + __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); + return __ret; +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { + _Tp __ret; + __atomic_load(std::addressof(__a->__a_value), std::addressof(__ret), __to_gcc_order(__order)); + return __ret; +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Tp __value, memory_order __order) { + _Tp __ret; + __atomic_exchange( + std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); + return __ret; +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, + memory_order __order) { + _Tp __ret; + __atomic_exchange( + std::addressof(__a->__a_value), std::addressof(__value), std::addressof(__ret), __to_gcc_order(__order)); + return __ret; +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong( + volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, + memory_order __success, memory_order __failure) { + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + false, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong( + __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, + memory_order __failure) { + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + false, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak( + volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, + memory_order __success, memory_order __failure) { + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + true, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak( + __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, + memory_order __failure) { + return __atomic_compare_exchange( + std::addressof(__a->__a_value), + __expected, + std::addressof(__value), + true, + __to_gcc_order(__success), + __to_gcc_failure_order(__failure)); +} + +template <typename _Tp> +struct __skip_amt { enum {value = 1}; }; + +template <typename _Tp> +struct __skip_amt<_Tp*> { enum {value = sizeof(_Tp)}; }; + +// FIXME: Haven't figured out what the spec says about using arrays with +// atomic_fetch_add. Force a failure rather than creating bad behavior. +template <typename _Tp> +struct __skip_amt<_Tp[]> { }; +template <typename _Tp, int n> +struct __skip_amt<_Tp[n]> { }; + +template <typename _Tp, typename _Td> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Td __delta, memory_order __order) { + return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); +} + +template <typename _Tp, typename _Td> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, + memory_order __order) { + return __atomic_fetch_add(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); +} + +template <typename _Tp, typename _Td> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Td __delta, memory_order __order) { + return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); +} + +template <typename _Tp, typename _Td> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, + memory_order __order) { + return __atomic_fetch_sub(std::addressof(__a->__a_value), __delta * __skip_amt<_Tp>::value, __to_gcc_order(__order)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Tp __pattern, memory_order __order) { + return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, + _Tp __pattern, memory_order __order) { + return __atomic_fetch_and(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Tp __pattern, memory_order __order) { + return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, + memory_order __order) { + return __atomic_fetch_or(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, + _Tp __pattern, memory_order __order) { + return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, + memory_order __order) { + return __atomic_fetch_xor(std::addressof(__a->__a_value), __pattern, __to_gcc_order(__order)); +} + +#define __cxx_atomic_is_lock_free(__s) __atomic_is_lock_free(__s, 0) + +#elif defined(_LIBCPP_HAS_C_ATOMIC_IMP) + +template <typename _Tp> +struct __cxx_atomic_base_impl { + + _LIBCPP_HIDE_FROM_ABI +#ifndef _LIBCPP_CXX03_LANG + __cxx_atomic_base_impl() _NOEXCEPT = default; +#else + __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {} +#endif // _LIBCPP_CXX03_LANG + _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp __value) _NOEXCEPT + : __a_value(__value) {} + _LIBCPP_DISABLE_EXTENSION_WARNING _Atomic(_Tp) __a_value; +}; + +#define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s) + +_LIBCPP_HIDE_FROM_ABI inline +void __cxx_atomic_thread_fence(memory_order __order) _NOEXCEPT { + __c11_atomic_thread_fence(static_cast<__memory_order_underlying_t>(__order)); +} + +_LIBCPP_HIDE_FROM_ABI inline +void __cxx_atomic_signal_fence(memory_order __order) _NOEXCEPT { + __c11_atomic_signal_fence(static_cast<__memory_order_underlying_t>(__order)); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val) _NOEXCEPT { + __c11_atomic_init(std::addressof(__a->__a_value), __val); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> * __a, _Tp __val) _NOEXCEPT { + __c11_atomic_init(std::addressof(__a->__a_value), __val); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val, memory_order __order) _NOEXCEPT { + __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> * __a, _Tp __val, memory_order __order) _NOEXCEPT { + __c11_atomic_store(std::addressof(__a->__a_value), __val, static_cast<__memory_order_underlying_t>(__order)); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const volatile* __a, memory_order __order) _NOEXCEPT { + using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; + return __c11_atomic_load( + const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const* __a, memory_order __order) _NOEXCEPT { + using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; + return __c11_atomic_load( + const_cast<__ptr_type>(std::addressof(__a->__a_value)), static_cast<__memory_order_underlying_t>(__order)); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __value, memory_order __order) _NOEXCEPT { + return __c11_atomic_exchange( + std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> * __a, _Tp __value, memory_order __order) _NOEXCEPT { + return __c11_atomic_exchange( + std::addressof(__a->__a_value), __value, static_cast<__memory_order_underlying_t>(__order)); +} + +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR memory_order __to_failure_order(memory_order __order) { + // Avoid switch statement to make this a constexpr. + return __order == memory_order_release ? memory_order_relaxed: + (__order == memory_order_acq_rel ? memory_order_acquire: + __order); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { + return __c11_atomic_compare_exchange_strong( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> * __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { + return __c11_atomic_compare_exchange_strong( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { + return __c11_atomic_compare_exchange_weak( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> * __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { + return __c11_atomic_compare_exchange_weak( + std::addressof(__a->__a_value), + __expected, + __value, + static_cast<__memory_order_underlying_t>(__success), + static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> * __a, _Tp __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> * __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_add( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> * __a, _Tp __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> * __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_sub( + std::addressof(__a->__a_value), __delta, static_cast<__memory_order_underlying_t>(__order)); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_and( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_and( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_or( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_or( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} + +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_xor( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} +template<class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { + return __c11_atomic_fetch_xor( + std::addressof(__a->__a_value), __pattern, static_cast<__memory_order_underlying_t>(__order)); +} + +#endif // _LIBCPP_HAS_GCC_ATOMIC_IMP, _LIBCPP_HAS_C_ATOMIC_IMP + +#ifdef _LIBCPP_ATOMIC_ONLY_USE_BUILTINS + +template<typename _Tp> +struct __cxx_atomic_lock_impl { + + _LIBCPP_HIDE_FROM_ABI + __cxx_atomic_lock_impl() _NOEXCEPT + : __a_value(), __a_lock(0) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit + __cxx_atomic_lock_impl(_Tp value) _NOEXCEPT + : __a_value(value), __a_lock(0) {} + + _Tp __a_value; + mutable __cxx_atomic_base_impl<_LIBCPP_ATOMIC_FLAG_TYPE> __a_lock; + + _LIBCPP_HIDE_FROM_ABI void __lock() const volatile { + while(1 == __cxx_atomic_exchange(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(true), memory_order_acquire)) + /*spin*/; + } + _LIBCPP_HIDE_FROM_ABI void __lock() const { + while(1 == __cxx_atomic_exchange(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(true), memory_order_acquire)) + /*spin*/; + } + _LIBCPP_HIDE_FROM_ABI void __unlock() const volatile { + __cxx_atomic_store(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(false), memory_order_release); + } + _LIBCPP_HIDE_FROM_ABI void __unlock() const { + __cxx_atomic_store(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(false), memory_order_release); + } + _LIBCPP_HIDE_FROM_ABI _Tp __read() const volatile { + __lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a_value); + __unlock(); + return __old; + } + _LIBCPP_HIDE_FROM_ABI _Tp __read() const { + __lock(); + _Tp __old = __a_value; + __unlock(); + return __old; + } +}; + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __val) { + __cxx_atomic_assign_volatile(__a->__a_value, __val); +} +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_init(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __val) { + __a->__a_value = __val; +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __val, memory_order) { + __a->__lock(); + __cxx_atomic_assign_volatile(__a->__a_value, __val); + __a->__unlock(); +} +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +void __cxx_atomic_store(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __val, memory_order) { + __a->__lock(); + __a->__a_value = __val; + __a->__unlock(); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(const volatile __cxx_atomic_lock_impl<_Tp>* __a, memory_order) { + return __a->__read(); +} +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_load(const __cxx_atomic_lock_impl<_Tp>* __a, memory_order) { + return __a->__read(); +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __value, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, __value); + __a->__unlock(); + return __old; +} +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_exchange(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __value, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value = __value; + __a->__unlock(); + return __old; +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Tp* __expected, _Tp __value, memory_order, memory_order) { + _Tp __temp; + __a->__lock(); + __cxx_atomic_assign_volatile(__temp, __a->__a_value); + bool __ret = (std::memcmp(&__temp, __expected, sizeof(_Tp)) == 0); + if(__ret) + __cxx_atomic_assign_volatile(__a->__a_value, __value); + else + __cxx_atomic_assign_volatile(*__expected, __a->__a_value); + __a->__unlock(); + return __ret; +} +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_lock_impl<_Tp>* __a, + _Tp* __expected, _Tp __value, memory_order, memory_order) { + __a->__lock(); + bool __ret = (std::memcmp(&__a->__a_value, __expected, sizeof(_Tp)) == 0); + if(__ret) + std::memcpy(&__a->__a_value, &__value, sizeof(_Tp)); + else + std::memcpy(__expected, &__a->__a_value, sizeof(_Tp)); + __a->__unlock(); + return __ret; +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Tp* __expected, _Tp __value, memory_order, memory_order) { + _Tp __temp; + __a->__lock(); + __cxx_atomic_assign_volatile(__temp, __a->__a_value); + bool __ret = (std::memcmp(&__temp, __expected, sizeof(_Tp)) == 0); + if(__ret) + __cxx_atomic_assign_volatile(__a->__a_value, __value); + else + __cxx_atomic_assign_volatile(*__expected, __a->__a_value); + __a->__unlock(); + return __ret; +} +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_lock_impl<_Tp>* __a, + _Tp* __expected, _Tp __value, memory_order, memory_order) { + __a->__lock(); + bool __ret = (std::memcmp(&__a->__a_value, __expected, sizeof(_Tp)) == 0); + if(__ret) + std::memcpy(&__a->__a_value, &__value, sizeof(_Tp)); + else + std::memcpy(__expected, &__a->__a_value, sizeof(_Tp)); + __a->__unlock(); + return __ret; +} + +template <typename _Tp, typename _Td> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Td __delta, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old + __delta)); + __a->__unlock(); + return __old; +} +template <typename _Tp, typename _Td> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_add(__cxx_atomic_lock_impl<_Tp>* __a, + _Td __delta, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value += __delta; + __a->__unlock(); + return __old; +} + +template <typename _Tp, typename _Td> +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_add(volatile __cxx_atomic_lock_impl<_Tp*>* __a, + ptrdiff_t __delta, memory_order) { + __a->__lock(); + _Tp* __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, __old + __delta); + __a->__unlock(); + return __old; +} +template <typename _Tp, typename _Td> +_LIBCPP_HIDE_FROM_ABI +_Tp* __cxx_atomic_fetch_add(__cxx_atomic_lock_impl<_Tp*>* __a, + ptrdiff_t __delta, memory_order) { + __a->__lock(); + _Tp* __old = __a->__a_value; + __a->__a_value += __delta; + __a->__unlock(); + return __old; +} + +template <typename _Tp, typename _Td> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Td __delta, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old - __delta)); + __a->__unlock(); + return __old; +} +template <typename _Tp, typename _Td> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_sub(__cxx_atomic_lock_impl<_Tp>* __a, + _Td __delta, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value -= __delta; + __a->__unlock(); + return __old; +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old & __pattern)); + __a->__unlock(); + return __old; +} +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_and(__cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value &= __pattern; + __a->__unlock(); + return __old; +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old | __pattern)); + __a->__unlock(); + return __old; +} +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_or(__cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value |= __pattern; + __a->__unlock(); + return __old; +} + +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(volatile __cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old; + __cxx_atomic_assign_volatile(__old, __a->__a_value); + __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old ^ __pattern)); + __a->__unlock(); + return __old; +} +template <typename _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp __cxx_atomic_fetch_xor(__cxx_atomic_lock_impl<_Tp>* __a, + _Tp __pattern, memory_order) { + __a->__lock(); + _Tp __old = __a->__a_value; + __a->__a_value ^= __pattern; + __a->__unlock(); + return __old; +} + +template <typename _Tp, + typename _Base = typename conditional<__libcpp_is_always_lock_free<_Tp>::__value, + __cxx_atomic_base_impl<_Tp>, + __cxx_atomic_lock_impl<_Tp> >::type> +#else +template <typename _Tp, + typename _Base = __cxx_atomic_base_impl<_Tp> > +#endif //_LIBCPP_ATOMIC_ONLY_USE_BUILTINS +struct __cxx_atomic_impl : public _Base { + static_assert(is_trivially_copyable<_Tp>::value, + "std::atomic<T> requires that 'T' be a trivially copyable type"); + + _LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT + : _Base(__value) {} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_CXX_ATOMIC_IMPL_H diff --git a/libcxx/include/__atomic/fence.h b/libcxx/include/__atomic/fence.h new file mode 100644 index 000000000000..c62f38f21157 --- /dev/null +++ b/libcxx/include/__atomic/fence.h @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_FENCE_H +#define _LIBCPP___ATOMIC_FENCE_H + +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/memory_order.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_thread_fence(memory_order __m) _NOEXCEPT +{ + __cxx_atomic_thread_fence(__m); +} + +inline _LIBCPP_HIDE_FROM_ABI +void +atomic_signal_fence(memory_order __m) _NOEXCEPT +{ + __cxx_atomic_signal_fence(__m); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_FENCE_H diff --git a/libcxx/include/__atomic/is_always_lock_free.h b/libcxx/include/__atomic/is_always_lock_free.h new file mode 100644 index 000000000000..fbbd43707499 --- /dev/null +++ b/libcxx/include/__atomic/is_always_lock_free.h @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_IS_ALWAYS_LOCK_FREE_H +#define _LIBCPP___ATOMIC_IS_ALWAYS_LOCK_FREE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp> +struct __libcpp_is_always_lock_free { + // __atomic_always_lock_free is available in all Standard modes + static const bool __value = __atomic_always_lock_free(sizeof(_Tp), 0); +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_IS_ALWAYS_LOCK_FREE_H diff --git a/libcxx/include/__atomic/kill_dependency.h b/libcxx/include/__atomic/kill_dependency.h new file mode 100644 index 000000000000..1bd5c8ca765a --- /dev/null +++ b/libcxx/include/__atomic/kill_dependency.h @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_KILL_DEPENDENCY_H +#define _LIBCPP___ATOMIC_KILL_DEPENDENCY_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI +_Tp kill_dependency(_Tp __y) _NOEXCEPT +{ + return __y; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_KILL_DEPENDENCY_H diff --git a/libcxx/include/__atomic/memory_order.h b/libcxx/include/__atomic/memory_order.h new file mode 100644 index 000000000000..3671dc3cf9be --- /dev/null +++ b/libcxx/include/__atomic/memory_order.h @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ATOMIC_MEMORY_ORDER_H +#define _LIBCPP___ATOMIC_MEMORY_ORDER_H + +#include <__config> +#include <__type_traits/is_same.h> +#include <__type_traits/underlying_type.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Figure out what the underlying type for `memory_order` would be if it were +// declared as an unscoped enum (accounting for -fshort-enums). Use this result +// to pin the underlying type in C++20. +enum __legacy_memory_order { + __mo_relaxed, + __mo_consume, + __mo_acquire, + __mo_release, + __mo_acq_rel, + __mo_seq_cst +}; + +using __memory_order_underlying_t = underlying_type<__legacy_memory_order>::type; + +#if _LIBCPP_STD_VER >= 20 + +enum class memory_order : __memory_order_underlying_t { + relaxed = __mo_relaxed, + consume = __mo_consume, + acquire = __mo_acquire, + release = __mo_release, + acq_rel = __mo_acq_rel, + seq_cst = __mo_seq_cst +}; + +static_assert((is_same<underlying_type<memory_order>::type, __memory_order_underlying_t>::value), + "unexpected underlying type for std::memory_order"); + +inline constexpr auto memory_order_relaxed = memory_order::relaxed; +inline constexpr auto memory_order_consume = memory_order::consume; +inline constexpr auto memory_order_acquire = memory_order::acquire; +inline constexpr auto memory_order_release = memory_order::release; +inline constexpr auto memory_order_acq_rel = memory_order::acq_rel; +inline constexpr auto memory_order_seq_cst = memory_order::seq_cst; + +#else + +enum memory_order { + memory_order_relaxed = __mo_relaxed, + memory_order_consume = __mo_consume, + memory_order_acquire = __mo_acquire, + memory_order_release = __mo_release, + memory_order_acq_rel = __mo_acq_rel, + memory_order_seq_cst = __mo_seq_cst, +}; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ATOMIC_MEMORY_ORDER_H diff --git a/libcxx/include/__availability b/libcxx/include/__availability index 6dfca3fa8b1a..7807f22b716f 100644 --- a/libcxx/include/__availability +++ b/libcxx/include/__availability @@ -39,17 +39,23 @@ // // This mechanism is general in nature, and any vendor can add their markup to // the library (see below). Whenever a new feature is added that requires support -// in the shared library, a macro should be added below to mark this feature -// as unavailable. When vendors decide to ship the feature as part of their -// shared library, they can update the markup appropriately. +// in the shared library, two macros are added below to allow marking the feature +// as unavailable: +// 1. A macro named `_LIBCPP_AVAILABILITY_HAS_NO_<feature>` which must be defined +// exactly when compiling for a target that doesn't support the feature. +// 2. A macro named `_LIBCPP_AVAILABILITY_<feature>`, which must always be defined +// and must expand to the proper availability attribute for the platform. +// +// When vendors decide to ship the feature as part of their shared library, they +// can update these macros appropriately for their platform, and the library will +// use those to provide an optimal user experience. // // Furthermore, many features in the standard library have corresponding -// feature-test macros. When a feature is made unavailable on some deployment -// target, a macro should be defined to signal that it is unavailable. That -// macro can then be picked up when feature-test macros are generated (see -// generate_feature_test_macro_components.py) to make sure that feature-test -// macros don't announce a feature as being implemented if it has been marked -// as unavailable. +// feature-test macros. The `_LIBCPP_AVAILABILITY_HAS_NO_<feature>` macros +// are checked by the corresponding feature-test macros generated by +// generate_feature_test_macro_components.py to ensure that the library +// doesn't announce a feature as being implemented if it is unavailable on +// the deployment target. // // Note that this mechanism is disabled by default in the "upstream" libc++. // Availability annotations are only meaningful when shipping libc++ inside @@ -83,9 +89,8 @@ // This controls the availability of std::shared_mutex and std::shared_timed_mutex, // which were added to the dylib later. +// # define _LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX # define _LIBCPP_AVAILABILITY_SHARED_MUTEX -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex // These macros control the availability of std::bad_optional_access and // other exception types. These were put in the shared library to prevent @@ -95,16 +100,23 @@ // Note that when exceptions are disabled, the methods that normally throw // these exceptions can be used even on older deployment targets, but those // methods will abort instead of throwing. +// # define _LIBCPP_AVAILABILITY_HAS_NO_BAD_OPTIONAL_ACCESS # define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS + +// # define _LIBCPP_AVAILABILITY_HAS_NO_BAD_VARIANT_ACCESS # define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS + +// # define _LIBCPP_AVAILABILITY_HAS_NO_BAD_ANY_CAST # define _LIBCPP_AVAILABILITY_BAD_ANY_CAST // This controls the availability of std::uncaught_exceptions(). +// # define _LIBCPP_AVAILABILITY_HAS_NO_UNCAUGHT_EXCEPTIONS # define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS // This controls the availability of the sized version of ::operator delete, // ::operator delete[], and their align_val_t variants, which were all added // in C++17, and hence not present in early dylibs. +// # define _LIBCPP_AVAILABILITY_HAS_NO_SIZED_NEW_DELETE # define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE // This controls the availability of the std::future_error exception. @@ -112,73 +124,83 @@ // Note that when exceptions are disabled, the methods that normally throw // std::future_error can be used even on older deployment targets, but those // methods will abort instead of throwing. +// # define _LIBCPP_AVAILABILITY_HAS_NO_FUTURE_ERROR # define _LIBCPP_AVAILABILITY_FUTURE_ERROR // This controls the availability of std::type_info's vtable. // I can't imagine how using std::type_info can work at all if // this isn't supported. +// # define _LIBCPP_AVAILABILITY_HAS_NO_TYPEINFO_VTABLE # define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE // This controls the availability of std::locale::category members // (e.g. std::locale::collate), which are defined in the dylib. +// # define _LIBCPP_AVAILABILITY_HAS_NO_LOCALE_CATEGORY # define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY // This controls the availability of atomic operations on std::shared_ptr // (e.g. `std::atomic_store(std::shared_ptr)`), which require a shared // lock table located in the dylib. +// # define _LIBCPP_AVAILABILITY_HAS_NO_ATOMIC_SHARED_PTR # define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR // These macros control the availability of all parts of <filesystem> that // depend on something in the dylib. -# define _LIBCPP_AVAILABILITY_FILESYSTEM -# define _LIBCPP_AVAILABILITY_FILESYSTEM_PUSH -# define _LIBCPP_AVAILABILITY_FILESYSTEM_POP -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem +// # define _LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM_LIBRARY +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP // This controls the availability of floating-point std::to_chars functions. // These overloads were added later than the integer overloads. +// # define _LIBCPP_AVAILABILITY_HAS_NO_TO_CHARS_FLOATING_POINT # define _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT // This controls the availability of the C++20 synchronization library, // which requires shared library support for various operations // (see libcxx/src/atomic.cpp). This includes <barier>, <latch>, // <semaphore>, and notification functions on std::atomic. +// # define _LIBCPP_AVAILABILITY_HAS_NO_SYNC # define _LIBCPP_AVAILABILITY_SYNC -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore - - // This controls the availability of the C++20 format library. - // The library is in development and not ABI stable yet. P2216 is - // retroactively accepted in C++20. This paper contains ABI breaking - // changes. -# define _LIBCPP_AVAILABILITY_FORMAT -// # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format // This controls whether the library claims to provide a default verbose // termination function, and consequently whether the headers will try // to use it when the mechanism isn't overriden at compile-time. -// # define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY +// # define _LIBCPP_AVAILABILITY_HAS_NO_VERBOSE_ABORT +# define _LIBCPP_AVAILABILITY_VERBOSE_ABORT + + // This controls the availability of the C++17 std::pmr library, + // which is implemented in large part in the built library. +// # define _LIBCPP_AVAILABILITY_HAS_NO_PMR +# define _LIBCPP_AVAILABILITY_PMR #elif defined(__APPLE__) -# define _LIBCPP_AVAILABILITY_SHARED_MUTEX \ - __attribute__((availability(macos,strict,introduced=10.12))) \ - __attribute__((availability(ios,strict,introduced=10.0))) \ - __attribute__((availability(tvos,strict,introduced=10.0))) \ - __attribute__((availability(watchos,strict,introduced=3.0))) + // shared_mutex and shared_timed_mutex # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex +# define _LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX # endif +# define _LIBCPP_AVAILABILITY_SHARED_MUTEX \ + __attribute__((availability(macos,strict,introduced=10.12))) \ + __attribute__((availability(ios,strict,introduced=10.0))) \ + __attribute__((availability(tvos,strict,introduced=10.0))) \ + __attribute__((availability(watchos,strict,introduced=3.0))) + // bad_optional_access, bad_variant_access and bad_any_cast // Note: bad_optional_access & friends were not introduced in the matching // macOS and iOS versions, so the version mismatch between macOS and others // is intended. +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) +# define _LIBCPP_AVAILABILITY_HAS_NO_BAD_OPTIONAL_ACCESS +# define _LIBCPP_AVAILABILITY_HAS_NO_BAD_VARIANT_ACCESS +# define _LIBCPP_AVAILABILITY_HAS_NO_BAD_ANY_CAST +# endif # define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS \ __attribute__((availability(macos,strict,introduced=10.13))) \ __attribute__((availability(ios,strict,introduced=12.0))) \ @@ -189,78 +211,142 @@ # define _LIBCPP_AVAILABILITY_BAD_ANY_CAST \ _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS + // uncaught_exceptions +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) +# define _LIBCPP_AVAILABILITY_HAS_NO_UNCAUGHT_EXCEPTIONS +# endif # define _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS \ __attribute__((availability(macos,strict,introduced=10.12))) \ __attribute__((availability(ios,strict,introduced=10.0))) \ __attribute__((availability(tvos,strict,introduced=10.0))) \ __attribute__((availability(watchos,strict,introduced=3.0))) + // sized operator new and sized operator delete +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) +# define _LIBCPP_AVAILABILITY_HAS_NO_SIZED_NEW_DELETE +# endif # define _LIBCPP_AVAILABILITY_SIZED_NEW_DELETE \ __attribute__((availability(macos,strict,introduced=10.12))) \ __attribute__((availability(ios,strict,introduced=10.0))) \ __attribute__((availability(tvos,strict,introduced=10.0))) \ __attribute__((availability(watchos,strict,introduced=3.0))) + // future_error +# if (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 60000) +# define _LIBCPP_AVAILABILITY_HAS_NO_FUTURE_ERROR +# endif # define _LIBCPP_AVAILABILITY_FUTURE_ERROR \ __attribute__((availability(ios,strict,introduced=6.0))) + // type_info's vtable +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 100900) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 70000) +# define _LIBCPP_AVAILABILITY_HAS_NO_TYPEINFO_VTABLE +# endif # define _LIBCPP_AVAILABILITY_TYPEINFO_VTABLE \ __attribute__((availability(macos,strict,introduced=10.9))) \ __attribute__((availability(ios,strict,introduced=7.0))) + // locale::category +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 100900) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 70000) +# define _LIBCPP_AVAILABILITY_HAS_NO_LOCALE_CATEGORY +# endif # define _LIBCPP_AVAILABILITY_LOCALE_CATEGORY \ __attribute__((availability(macos,strict,introduced=10.9))) \ __attribute__((availability(ios,strict,introduced=7.0))) + // atomic operations on shared_ptr +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 100900) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 70000) +# define _LIBCPP_AVAILABILITY_HAS_NO_ATOMIC_SHARED_PTR +# endif # define _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR \ __attribute__((availability(macos,strict,introduced=10.9))) \ __attribute__((availability(ios,strict,introduced=7.0))) -# define _LIBCPP_AVAILABILITY_FILESYSTEM \ + // <filesystem> +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) +# define _LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM_LIBRARY +# endif +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY \ __attribute__((availability(macos,strict,introduced=10.15))) \ __attribute__((availability(ios,strict,introduced=13.0))) \ __attribute__((availability(tvos,strict,introduced=13.0))) \ __attribute__((availability(watchos,strict,introduced=6.0))) -# define _LIBCPP_AVAILABILITY_FILESYSTEM_PUSH \ +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH \ _Pragma("clang attribute push(__attribute__((availability(macos,strict,introduced=10.15))), apply_to=any(function,record))") \ _Pragma("clang attribute push(__attribute__((availability(ios,strict,introduced=13.0))), apply_to=any(function,record))") \ _Pragma("clang attribute push(__attribute__((availability(tvos,strict,introduced=13.0))), apply_to=any(function,record))") \ _Pragma("clang attribute push(__attribute__((availability(watchos,strict,introduced=6.0))), apply_to=any(function,record))") -# define _LIBCPP_AVAILABILITY_FILESYSTEM_POP \ +# define _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP \ _Pragma("clang attribute pop") \ _Pragma("clang attribute pop") \ _Pragma("clang attribute pop") \ _Pragma("clang attribute pop") -# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem -# endif + // std::to_chars(floating-point) +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 130300) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 160300) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 160300) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 90300) +# define _LIBCPP_AVAILABILITY_HAS_NO_TO_CHARS_FLOATING_POINT +# endif # define _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT \ - __attribute__((unavailable)) + __attribute__((availability(macos,strict,introduced=13.3))) \ + __attribute__((availability(ios,strict,introduced=16.3))) \ + __attribute__((availability(tvos,strict,introduced=16.3))) \ + __attribute__((availability(watchos,strict,introduced=9.3))) -# define _LIBCPP_AVAILABILITY_SYNC \ - __attribute__((availability(macos,strict,introduced=11.0))) \ - __attribute__((availability(ios,strict,introduced=14.0))) \ - __attribute__((availability(tvos,strict,introduced=14.0))) \ - __attribute__((availability(watchos,strict,introduced=7.0))) + // c++20 synchronization library # if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000) || \ (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 140000) || \ (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 140000) || \ (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 70000) -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore +# define _LIBCPP_AVAILABILITY_HAS_NO_SYNC # endif +# define _LIBCPP_AVAILABILITY_SYNC \ + __attribute__((availability(macos,strict,introduced=11.0))) \ + __attribute__((availability(ios,strict,introduced=14.0))) \ + __attribute__((availability(tvos,strict,introduced=14.0))) \ + __attribute__((availability(watchos,strict,introduced=7.0))) -# define _LIBCPP_AVAILABILITY_FORMAT \ + // __libcpp_verbose_abort +# if 1 // TODO: Update once this is released +# define _LIBCPP_AVAILABILITY_HAS_NO_VERBOSE_ABORT +# endif +# define _LIBCPP_AVAILABILITY_VERBOSE_ABORT \ __attribute__((unavailable)) -# define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format -# define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY + // std::pmr +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 140000) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 170000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 170000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 100000) +# define _LIBCPP_AVAILABILITY_HAS_NO_PMR +# endif +// TODO: Enable std::pmr markup once https://github.com/llvm/llvm-project/issues/40340 has been fixed +// Until then, it is possible for folks to try to use `std::pmr` when back-deploying to targets that don't support +// it and it'll be a load-time error, but we don't have a good alternative because the library won't compile if we +// use availability annotations until that bug has been fixed. +# if 0 +# define _LIBCPP_AVAILABILITY_PMR \ + __attribute__((availability(macos, strict, introduced = 14.0))) \ + __attribute__((availability(ios, strict, introduced = 17.0))) \ + __attribute__((availability(tvos, strict, introduced = 17.0))) \ + __attribute__((availability(watchos, strict, introduced = 10.0))) +# else +# define _LIBCPP_AVAILABILITY_PMR +# endif #else @@ -270,10 +356,10 @@ #endif -// Define availability attributes that depend on _LIBCPP_NO_EXCEPTIONS. +// Define availability attributes that depend on _LIBCPP_HAS_NO_EXCEPTIONS. // Those are defined in terms of the availability attributes above, and // should not be vendor-specific. -#if defined(_LIBCPP_NO_EXCEPTIONS) +#if defined(_LIBCPP_HAS_NO_EXCEPTIONS) # define _LIBCPP_AVAILABILITY_FUTURE # define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST # define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS diff --git a/libcxx/include/__bit/bit_cast.h b/libcxx/include/__bit/bit_cast.h index 2ca4120c7630..39842465e12a 100644 --- a/libcxx/include/__bit/bit_cast.h +++ b/libcxx/include/__bit/bit_cast.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _ToType, class _FromType> requires(sizeof(_ToType) == sizeof(_FromType) && @@ -29,7 +29,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _ToType bit_cast(const _Fr return __builtin_bit_cast(_ToType, __from); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__bit/bit_ceil.h b/libcxx/include/__bit/bit_ceil.h index a558d6194270..706d446359dd 100644 --- a/libcxx/include/__bit/bit_ceil.h +++ b/libcxx/include/__bit/bit_ceil.h @@ -24,18 +24,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept { if (__t < 2) return 1; const unsigned __n = numeric_limits<_Tp>::digits - std::countl_zero((_Tp)(__t - 1u)); - _LIBCPP_ASSERT(__n != numeric_limits<_Tp>::digits, "Bad input to bit_ceil"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n != numeric_limits<_Tp>::digits, "Bad input to bit_ceil"); if constexpr (sizeof(_Tp) >= sizeof(unsigned)) return _Tp{1} << __n; else { const unsigned __extra = numeric_limits<unsigned>::digits - numeric_limits<_Tp>::digits; - const unsigned __retVal = 1u << (__n + __extra); - return (_Tp)(__retVal >> __extra); + const unsigned __ret_val = 1u << (__n + __extra); + return (_Tp)(__ret_val >> __extra); } } diff --git a/libcxx/include/__bit/bit_floor.h b/libcxx/include/__bit/bit_floor.h index b2e38092f2d7..cf5cf5803ad6 100644 --- a/libcxx/include/__bit/bit_floor.h +++ b/libcxx/include/__bit/bit_floor.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept { return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t); } diff --git a/libcxx/include/__bit/bit_width.h b/libcxx/include/__bit/bit_width.h index 4381f227f5e5..a2020a01421e 100644 --- a/libcxx/include/__bit/bit_width.h +++ b/libcxx/include/__bit/bit_width.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept { return __t == 0 ? 0 : std::__bit_log2(__t) + 1; } diff --git a/libcxx/include/__bit/byteswap.h b/libcxx/include/__bit/byteswap.h index 6fa8d48bafa4..a1e1b530975e 100644 --- a/libcxx/include/__bit/byteswap.h +++ b/libcxx/include/__bit/byteswap.h @@ -13,7 +13,6 @@ #include <__concepts/arithmetic.h> #include <__config> #include <cstdint> -#include <cstdlib> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -21,10 +20,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <integral _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { if constexpr (sizeof(_Tp) == 1) { return __val; @@ -48,7 +47,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp byteswap(_Tp __val) noexcept { } } -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__bit/countl.h b/libcxx/include/__bit/countl.h index 86eaee0c1b3b..5d5744ac9a65 100644 --- a/libcxx/include/__bit/countl.h +++ b/libcxx/include/__bit/countl.h @@ -24,13 +24,13 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); } # ifndef _LIBCPP_HAS_NO_INT128 @@ -86,12 +86,12 @@ int __countl_zero(_Tp __t) _NOEXCEPT #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept { return std::__countl_zero(__t); } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/libcxx/include/__bit/countr.h b/libcxx/include/__bit/countr.h index d3ca5b6c94f1..66ca5e7e66f2 100644 --- a/libcxx/include/__bit/countr.h +++ b/libcxx/include/__bit/countr.h @@ -23,19 +23,19 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned __x) _NOEXCEPT { return __builtin_ctz(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned long __x) _NOEXCEPT { return __builtin_ctzl(__x); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned long long __x) _NOEXCEPT { return __builtin_ctzll(__x); } #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { if (__t == 0) return numeric_limits<_Tp>::digits; @@ -57,7 +57,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; } diff --git a/libcxx/include/__bit/has_single_bit.h b/libcxx/include/__bit/has_single_bit.h index b89f5995b32d..a4e178060a73 100644 --- a/libcxx/include/__bit/has_single_bit.h +++ b/libcxx/include/__bit/has_single_bit.h @@ -24,7 +24,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept { return __t != 0 && (((__t & (__t - 1)) == 0)); } diff --git a/libcxx/include/__bit/popcount.h b/libcxx/include/__bit/popcount.h index 33b94cff7122..62f4786bceaf 100644 --- a/libcxx/include/__bit/popcount.h +++ b/libcxx/include/__bit/popcount.h @@ -35,7 +35,7 @@ int __libcpp_popcount(unsigned long long __x) _NOEXCEPT { return __builtin_popco #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept { if (sizeof(_Tp) <= sizeof(unsigned int)) return std::__libcpp_popcount(static_cast<unsigned int>(__t)); else if (sizeof(_Tp) <= sizeof(unsigned long)) diff --git a/libcxx/include/__bit/rotate.h b/libcxx/include/__bit/rotate.h index 5aa7518b3c57..e9f4c8d474b0 100644 --- a/libcxx/include/__bit/rotate.h +++ b/libcxx/include/__bit/rotate.h @@ -34,7 +34,7 @@ _Tp __rotr(_Tp __t, unsigned int __cnt) _NOEXCEPT #if _LIBCPP_STD_VER >= 20 template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { const unsigned int __dig = numeric_limits<_Tp>::digits; if ((__cnt % __dig) == 0) return __t; @@ -42,7 +42,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, unsigned int __cnt) noexcept { } template <__libcpp_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, unsigned int __cnt) noexcept { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, unsigned int __cnt) noexcept { return std::__rotr(__t, __cnt); } diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference index 26657491393d..a6bb6d42505a 100644 --- a/libcxx/include/__bit_reference +++ b/libcxx/include/__bit_reference @@ -19,8 +19,9 @@ #include <__iterator/iterator_traits.h> #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> +#include <__type_traits/conditional.h> +#include <__utility/swap.h> #include <cstring> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -75,7 +76,7 @@ public: return *this; } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr const __bit_reference& operator=(bool __x) const noexcept { if (__x) *__seg_ |= __mask_; @@ -155,6 +156,8 @@ class __bit_const_reference friend typename _Cp::__self; friend class __bit_iterator<_Cp, true>; public: + using __container = typename _Cp::__self; + _LIBCPP_INLINE_VISIBILITY __bit_const_reference(const __bit_const_reference&) = default; @@ -728,12 +731,12 @@ move_backward(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsCons // swap_ranges -template <class __C1, class __C2> -_LIBCPP_HIDE_FROM_ABI __bit_iterator<__C2, false> -__swap_ranges_aligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, false> __last, - __bit_iterator<__C2, false> __result) +template <class _Cl, class _Cr> +_LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> +__swap_ranges_aligned(__bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, + __bit_iterator<_Cr, false> __result) { - typedef __bit_iterator<__C1, false> _I1; + typedef __bit_iterator<_Cl, false> _I1; typedef typename _I1::difference_type difference_type; typedef typename _I1::__storage_type __storage_type; const int __bits_per_word = _I1::__bits_per_word; @@ -778,12 +781,12 @@ __swap_ranges_aligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, return __result; } -template <class __C1, class __C2> -_LIBCPP_HIDE_FROM_ABI __bit_iterator<__C2, false> -__swap_ranges_unaligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, false> __last, - __bit_iterator<__C2, false> __result) +template <class _Cl, class _Cr> +_LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> +__swap_ranges_unaligned(__bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, + __bit_iterator<_Cr, false> __result) { - typedef __bit_iterator<__C1, false> _I1; + typedef __bit_iterator<_Cl, false> _I1; typedef typename _I1::difference_type difference_type; typedef typename _I1::__storage_type __storage_type; const int __bits_per_word = _I1::__bits_per_word; @@ -878,11 +881,11 @@ __swap_ranges_unaligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1 return __result; } -template <class __C1, class __C2> +template <class _Cl, class _Cr> inline _LIBCPP_INLINE_VISIBILITY -__bit_iterator<__C2, false> -swap_ranges(__bit_iterator<__C1, false> __first1, __bit_iterator<__C1, false> __last1, - __bit_iterator<__C2, false> __first2) +__bit_iterator<_Cr, false> +swap_ranges(__bit_iterator<_Cl, false> __first1, __bit_iterator<_Cl, false> __last1, + __bit_iterator<_Cr, false> __first2) { if (__first1.__ctz_ == __first2.__ctz_) return _VSTD::__swap_ranges_aligned(__first1, __last1, __first2); @@ -1135,7 +1138,7 @@ private: public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator() _NOEXCEPT -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 : __seg_(nullptr), __ctz_(0) #endif {} @@ -1311,15 +1314,15 @@ private: friend __bit_iterator<_Dp, false> copy_backward(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result); - template <class __C1, class __C2>friend __bit_iterator<__C2, false> __swap_ranges_aligned(__bit_iterator<__C1, false>, - __bit_iterator<__C1, false>, - __bit_iterator<__C2, false>); - template <class __C1, class __C2>friend __bit_iterator<__C2, false> __swap_ranges_unaligned(__bit_iterator<__C1, false>, - __bit_iterator<__C1, false>, - __bit_iterator<__C2, false>); - template <class __C1, class __C2>friend __bit_iterator<__C2, false> swap_ranges(__bit_iterator<__C1, false>, - __bit_iterator<__C1, false>, - __bit_iterator<__C2, false>); + template <class _Cl, class _Cr>friend __bit_iterator<_Cr, false> __swap_ranges_aligned(__bit_iterator<_Cl, false>, + __bit_iterator<_Cl, false>, + __bit_iterator<_Cr, false>); + template <class _Cl, class _Cr>friend __bit_iterator<_Cr, false> __swap_ranges_unaligned(__bit_iterator<_Cl, false>, + __bit_iterator<_Cl, false>, + __bit_iterator<_Cr, false>); + template <class _Cl, class _Cr>friend __bit_iterator<_Cr, false> swap_ranges(__bit_iterator<_Cl, false>, + __bit_iterator<_Cl, false>, + __bit_iterator<_Cr, false>); template <class _Dp> _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> rotate(__bit_iterator<_Dp, false>, diff --git a/libcxx/include/__charconv/chars_format.h b/libcxx/include/__charconv/chars_format.h index 695bd873189c..0e781c047e39 100644 --- a/libcxx/include/__charconv/chars_format.h +++ b/libcxx/include/__charconv/chars_format.h @@ -19,58 +19,45 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 - -enum class _LIBCPP_ENUM_VIS chars_format -{ - scientific = 0x1, - fixed = 0x2, - hex = 0x4, - general = fixed | scientific -}; - -inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format -operator~(chars_format __x) { - return chars_format(~_VSTD::__to_underlying(__x)); +#if _LIBCPP_STD_VER >= 17 + +enum class _LIBCPP_ENUM_VIS chars_format { scientific = 0x1, fixed = 0x2, hex = 0x4, general = fixed | scientific }; + +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator~(chars_format __x) { + return chars_format(~std::__to_underlying(__x)); } -inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format -operator&(chars_format __x, chars_format __y) { - return chars_format(_VSTD::__to_underlying(__x) & - _VSTD::__to_underlying(__y)); +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator&(chars_format __x, chars_format __y) { + return chars_format(std::__to_underlying(__x) & std::__to_underlying(__y)); } -inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format -operator|(chars_format __x, chars_format __y) { - return chars_format(_VSTD::__to_underlying(__x) | - _VSTD::__to_underlying(__y)); +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator|(chars_format __x, chars_format __y) { + return chars_format(std::__to_underlying(__x) | std::__to_underlying(__y)); } -inline _LIBCPP_INLINE_VISIBILITY constexpr chars_format -operator^(chars_format __x, chars_format __y) { - return chars_format(_VSTD::__to_underlying(__x) ^ - _VSTD::__to_underlying(__y)); +inline _LIBCPP_HIDE_FROM_ABI constexpr chars_format operator^(chars_format __x, chars_format __y) { + return chars_format(std::__to_underlying(__x) ^ std::__to_underlying(__y)); } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& operator&=(chars_format& __x, chars_format __y) { __x = __x & __y; return __x; } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& operator|=(chars_format& __x, chars_format __y) { __x = __x | __y; return __x; } -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 chars_format& operator^=(chars_format& __x, chars_format __y) { __x = __x ^ __y; return __x; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__charconv/from_chars_integral.h b/libcxx/include/__charconv/from_chars_integral.h new file mode 100644 index 000000000000..acfdf4b30da7 --- /dev/null +++ b/libcxx/include/__charconv/from_chars_integral.h @@ -0,0 +1,239 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHARCONV_FROM_CHARS_INTEGRAL_H +#define _LIBCPP___CHARCONV_FROM_CHARS_INTEGRAL_H + +#include <__algorithm/copy_n.h> +#include <__charconv/from_chars_result.h> +#include <__charconv/traits.h> +#include <__config> +#include <__memory/addressof.h> +#include <__system_error/errc.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_unsigned.h> +#include <__type_traits/make_unsigned.h> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 17 + +from_chars_result from_chars(const char*, const char*, bool, int = 10) = delete; + +template <typename _It, typename _Tp, typename _Fn, typename... _Ts> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) { + using __tl = numeric_limits<_Tp>; + decltype(std::__to_unsigned_like(__value)) __x; + + bool __neg = (__first != __last && *__first == '-'); + auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...); + switch (__r.ec) { + case errc::invalid_argument: + return {__first, __r.ec}; + case errc::result_out_of_range: + return __r; + default: + break; + } + + if (__neg) { + if (__x <= std::__complement(std::__to_unsigned_like(__tl::min()))) { + __x = std::__complement(__x); + std::copy_n(std::addressof(__x), 1, std::addressof(__value)); + return __r; + } + } else { + if (__x <= std::__to_unsigned_like(__tl::max())) { + __value = __x; + return __r; + } + } + + return {__r.ptr, errc::result_out_of_range}; +} + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __in_pattern(_Tp __c) { + return '0' <= __c && __c <= '9'; +} + +struct _LIBCPP_HIDDEN __in_pattern_result { + bool __ok; + int __val; + + explicit _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI operator bool() const { return __ok; } +}; + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __in_pattern_result __in_pattern(_Tp __c, int __base) { + if (__base <= 10) + return {'0' <= __c && __c < '0' + __base, __c - '0'}; + else if (std::__in_pattern(__c)) + return {true, __c - '0'}; + else if ('a' <= __c && __c < 'a' + __base - 10) + return {true, __c - 'a' + 10}; + else + return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10}; +} + +template <typename _It, typename _Tp, typename _Fn, typename... _Ts> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) { + auto __find_non_zero = [](_It __firstit, _It __lastit) { + for (; __firstit != __lastit; ++__firstit) + if (*__firstit != '0') + break; + return __firstit; + }; + + auto __p = __find_non_zero(__first, __last); + if (__p == __last || !std::__in_pattern(*__p, __args...)) { + if (__p == __first) + return {__first, errc::invalid_argument}; + else { + __value = 0; + return {__p, {}}; + } + } + + auto __r = __f(__p, __last, __value, __args...); + if (__r.ec == errc::result_out_of_range) { + for (; __r.ptr != __last; ++__r.ptr) { + if (!std::__in_pattern(*__r.ptr, __args...)) + break; + } + } + + return __r; +} + +template <typename _Tp, typename enable_if<is_unsigned<_Tp>::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) { + using __tx = __itoa::__traits<_Tp>; + using __output_type = typename __tx::type; + + return std::__subject_seq_combinator( + __first, __last, __value, [](const char* __f, const char* __l, _Tp& __val) -> from_chars_result { + __output_type __a, __b; + auto __p = __tx::__read(__f, __l, __a, __b); + if (__p == __l || !std::__in_pattern(*__p)) { + __output_type __m = numeric_limits<_Tp>::max(); + if (__m >= __a && __m - __a >= __b) { + __val = __a + __b; + return {__p, {}}; + } + } + return {__p, errc::result_out_of_range}; + }); +} + +template <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) { + using __t = decltype(std::__to_unsigned_like(__value)); + return std::__sign_combinator(__first, __last, __value, __from_chars_atoi<__t>); +} + +/* +// Code used to generate __from_chars_log2f_lut. +#include <cmath> +#include <format> +#include <iostream> + +int main() { + for (int i = 2; i <= 36; ++i) + std::cout << std::format("{},\n", log2f(i)); +} +*/ +/// log2f table for bases [2, 36]. +inline constexpr float __from_chars_log2f_lut[35] = { + 1, 1.5849625, 2, 2.321928, 2.5849626, 2.807355, 3, 3.169925, 3.321928, + 3.4594316, 3.5849626, 3.7004397, 3.807355, 3.9068906, 4, 4.087463, 4.169925, 4.2479277, + 4.321928, 4.3923173, 4.4594316, 4.523562, 4.5849624, 4.643856, 4.70044, 4.7548876, 4.807355, + 4.857981, 4.9068904, 4.9541965, 5, 5.044394, 5.087463, 5.129283, 5.169925}; + +template <typename _Tp, typename enable_if<is_unsigned<_Tp>::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) { + if (__base == 10) + return std::__from_chars_atoi(__first, __last, __value); + + return std::__subject_seq_combinator( + __first, + __last, + __value, + [](const char* __p, const char* __lastp, _Tp& __val, int __b) -> from_chars_result { + using __tl = numeric_limits<_Tp>; + // __base is always between 2 and 36 inclusive. + auto __digits = __tl::digits / __from_chars_log2f_lut[__b - 2]; + _Tp __x = __in_pattern(*__p++, __b).__val, __y = 0; + + for (int __i = 1; __p != __lastp; ++__i, ++__p) { + if (auto __c = __in_pattern(*__p, __b)) { + if (__i < __digits - 1) + __x = __x * __b + __c.__val; + else { + if (!__itoa::__mul_overflowed(__x, __b, __x)) + ++__p; + __y = __c.__val; + break; + } + } else + break; + } + + if (__p == __lastp || !__in_pattern(*__p, __b)) { + if (__tl::max() - __x >= __y) { + __val = __x + __y; + return {__p, {}}; + } + } + return {__p, errc::result_out_of_range}; + }, + __base); +} + +template <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +__from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) { + using __t = decltype(std::__to_unsigned_like(__value)); + return std::__sign_combinator(__first, __last, __value, __from_chars_integral<__t>, __base); +} + +template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +from_chars(const char* __first, const char* __last, _Tp& __value) { + return std::__from_chars_atoi(__first, __last, __value); +} + +template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result +from_chars(const char* __first, const char* __last, _Tp& __value, int __base) { + _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]"); + return std::__from_chars_integral(__first, __last, __value, __base); +} +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHARCONV_FROM_CHARS_INTEGRAL_H diff --git a/libcxx/include/__charconv/from_chars_result.h b/libcxx/include/__charconv/from_chars_result.h index 05ffe1485cae..fa98616a0cb7 100644 --- a/libcxx/include/__charconv/from_chars_result.h +++ b/libcxx/include/__charconv/from_chars_result.h @@ -11,7 +11,7 @@ #define _LIBCPP___CHARCONV_FROM_CHARS_RESULT_H #include <__config> -#include <__errc> +#include <__system_error/errc.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,18 +19,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 -struct _LIBCPP_TYPE_VIS from_chars_result -{ - const char* ptr; - errc ec; -# if _LIBCPP_STD_VER > 17 - _LIBCPP_HIDE_FROM_ABI friend bool operator==(const from_chars_result&, const from_chars_result&) = default; +struct _LIBCPP_EXPORTED_FROM_ABI from_chars_result { + const char* ptr; + errc ec; +# if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const from_chars_result&, const from_chars_result&) = default; # endif }; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__charconv/tables.h b/libcxx/include/__charconv/tables.h index 9b82440348be..6b93536b8c1b 100644 --- a/libcxx/include/__charconv/tables.h +++ b/libcxx/include/__charconv/tables.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 namespace __itoa { @@ -62,32 +62,41 @@ inline constexpr char __base_16_lut[512] = { 'f', 'd', 'f', 'e', 'f', 'f'}; inline constexpr uint32_t __pow10_32[10] = { - UINT32_C(0), UINT32_C(10), UINT32_C(100), UINT32_C(1000), UINT32_C(10000), - UINT32_C(100000), UINT32_C(1000000), UINT32_C(10000000), UINT32_C(100000000), UINT32_C(1000000000)}; - -inline constexpr uint64_t __pow10_64[20] = {UINT64_C(0), - UINT64_C(10), - UINT64_C(100), - UINT64_C(1000), - UINT64_C(10000), - UINT64_C(100000), - UINT64_C(1000000), - UINT64_C(10000000), - UINT64_C(100000000), - UINT64_C(1000000000), - UINT64_C(10000000000), - UINT64_C(100000000000), - UINT64_C(1000000000000), - UINT64_C(10000000000000), - UINT64_C(100000000000000), - UINT64_C(1000000000000000), - UINT64_C(10000000000000000), - UINT64_C(100000000000000000), - UINT64_C(1000000000000000000), - UINT64_C(10000000000000000000)}; + UINT32_C(0), + UINT32_C(10), + UINT32_C(100), + UINT32_C(1000), + UINT32_C(10000), + UINT32_C(100000), + UINT32_C(1000000), + UINT32_C(10000000), + UINT32_C(100000000), + UINT32_C(1000000000)}; + +inline constexpr uint64_t __pow10_64[20] = { + UINT64_C(0), + UINT64_C(10), + UINT64_C(100), + UINT64_C(1000), + UINT64_C(10000), + UINT64_C(100000), + UINT64_C(1000000), + UINT64_C(10000000), + UINT64_C(100000000), + UINT64_C(1000000000), + UINT64_C(10000000000), + UINT64_C(100000000000), + UINT64_C(1000000000000), + UINT64_C(10000000000000), + UINT64_C(100000000000000), + UINT64_C(1000000000000000), + UINT64_C(10000000000000000), + UINT64_C(100000000000000000), + UINT64_C(1000000000000000000), + UINT64_C(10000000000000000000)}; # ifndef _LIBCPP_HAS_NO_INT128 -inline constexpr int __pow10_128_offset = 0; +inline constexpr int __pow10_128_offset = 0; inline constexpr __uint128_t __pow10_128[40] = { UINT64_C(0), UINT64_C(10), @@ -147,7 +156,7 @@ inline constexpr char __digits_base_10[200] = { } // namespace __itoa -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__charconv/to_chars.h b/libcxx/include/__charconv/to_chars.h new file mode 100644 index 000000000000..8ef09af73755 --- /dev/null +++ b/libcxx/include/__charconv/to_chars.h @@ -0,0 +1,25 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHARCONV_TO_CHARS +#define _LIBCPP___CHARCONV_TO_CHARS + +#include <__charconv/to_chars_floating_point.h> +#include <__charconv/to_chars_integral.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_TO_CHARS diff --git a/libcxx/include/__charconv/to_chars_base_10.h b/libcxx/include/__charconv/to_chars_base_10.h index fc7fb76e3e98..33c512e20f04 100644 --- a/libcxx/include/__charconv/to_chars_base_10.h +++ b/libcxx/include/__charconv/to_chars_base_10.h @@ -25,7 +25,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 namespace __itoa { @@ -72,7 +72,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __append10(char* __fir static_cast<uint32_t>(__value % 100000000)); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u32(char* __first, uint32_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* +__base_10_u32(char* __first, uint32_t __value) noexcept { if (__value < 1000000) { if (__value < 10000) { if (__value < 100) { @@ -107,7 +108,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u32(c return __itoa::__append10(__first, __value); } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u64(char* __buffer, uint64_t __value) noexcept { +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* +__base_10_u64(char* __buffer, uint64_t __value) noexcept { if (__value <= UINT32_MAX) return __itoa::__base_10_u32(__buffer, static_cast<uint32_t>(__value)); @@ -130,12 +132,13 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u64(c /// range that can be used. However the range is sufficient for /// \ref __base_10_u128. _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline __uint128_t __pow_10(int __exp) noexcept { - _LIBCPP_ASSERT(__exp >= __pow10_128_offset, "Index out of bounds"); + _LIBCPP_ASSERT_UNCATEGORIZED(__exp >= __pow10_128_offset, "Index out of bounds"); return __pow10_128[__exp - __pow10_128_offset]; } -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u128(char* __buffer, __uint128_t __value) noexcept { - _LIBCPP_ASSERT( +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* +__base_10_u128(char* __buffer, __uint128_t __value) noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED( __value > numeric_limits<uint64_t>::max(), "The optimizations for this algorithm fail when this isn't true."); // Unlike the 64 to 32 bit case the 128 bit case the "upper half" can't be @@ -159,8 +162,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u128( __value %= __itoa::__pow_10(29); __buffer = __itoa::__append10(__buffer, static_cast<uint64_t>(__value / __itoa::__pow_10(19))); __value %= __itoa::__pow_10(19); - } - else { + } else { // step 2 // This version needs to determine the position of the leading non-zero digit. __buffer = __base_10_u64(__buffer, static_cast<uint64_t>(__value / __itoa::__pow_10(19))); @@ -176,7 +178,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __base_10_u128( # endif } // namespace __itoa -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__charconv/to_chars_floating_point.h b/libcxx/include/__charconv/to_chars_floating_point.h new file mode 100644 index 000000000000..08720e107885 --- /dev/null +++ b/libcxx/include/__charconv/to_chars_floating_point.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHARCONV_TO_CHARS_FLOATING_POINT_H +#define _LIBCPP___CHARCONV_TO_CHARS_FLOATING_POINT_H + +#include <__availability> +#include <__charconv/chars_format.h> +#include <__charconv/to_chars_result.h> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 17 + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, float __value); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, double __value); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, long double __value); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, float __value, chars_format __fmt); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, double __value, chars_format __fmt); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, long double __value, chars_format __fmt); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, float __value, chars_format __fmt, int __precision); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, double __value, chars_format __fmt, int __precision); + +_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision); +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHARCONV_TO_CHARS_FLOATING_POINT_H diff --git a/libcxx/include/__charconv/to_chars_integral.h b/libcxx/include/__charconv/to_chars_integral.h new file mode 100644 index 000000000000..28fac7524cf3 --- /dev/null +++ b/libcxx/include/__charconv/to_chars_integral.h @@ -0,0 +1,326 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H +#define _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H + +#include <__algorithm/copy_n.h> +#include <__bit/countl.h> +#include <__charconv/tables.h> +#include <__charconv/to_chars_base_10.h> +#include <__charconv/to_chars_result.h> +#include <__charconv/traits.h> +#include <__config> +#include <__system_error/errc.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_same.h> +#include <__type_traits/make_32_64_or_128_bit.h> +#include <__type_traits/make_unsigned.h> +#include <__utility/unreachable.h> +#include <cstddef> +#include <cstdint> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 17 + +to_chars_result to_chars(char*, char*, bool, int = 10) = delete; + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type); + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) { + auto __x = std::__to_unsigned_like(__value); + if (__value < 0 && __first != __last) { + *__first++ = '-'; + __x = std::__complement(__x); + } + + return std::__to_chars_itoa(__first, __last, __x, false_type()); +} + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) { + using __tx = __itoa::__traits<_Tp>; + auto __diff = __last - __first; + + if (__tx::digits <= __diff || __tx::__width(__value) <= __diff) + return {__tx::__convert(__first, __value), errc(0)}; + else + return {__last, errc::value_too_large}; +} + +# ifndef _LIBCPP_HAS_NO_INT128 +template <> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) { + // When the value fits in 64-bits use the 64-bit code path. This reduces + // the number of expensive calculations on 128-bit values. + // + // NOTE the 128-bit code path requires this optimization. + if (__value <= numeric_limits<uint64_t>::max()) + return __to_chars_itoa(__first, __last, static_cast<uint64_t>(__value), false_type()); + + using __tx = __itoa::__traits<__uint128_t>; + auto __diff = __last - __first; + + if (__tx::digits <= __diff || __tx::__width(__value) <= __diff) + return {__tx::__convert(__first, __value), errc(0)}; + else + return {__last, errc::value_too_large}; +} +# endif + +template <class _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type); + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, true_type) { + auto __x = std::__to_unsigned_like(__value); + if (__value < 0 && __first != __last) { + *__first++ = '-'; + __x = std::__complement(__x); + } + + return std::__to_chars_integral(__first, __last, __x, __base, false_type()); +} + +namespace __itoa { + +template <unsigned _Base> +struct _LIBCPP_HIDDEN __integral; + +template <> +struct _LIBCPP_HIDDEN __integral<2> { + template <typename _Tp> + _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept { + // If value == 0 still need one digit. If the value != this has no + // effect since the code scans for the most significant bit set. (Note + // that __libcpp_clz doesn't work for 0.) + return numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1); + } + + template <typename _Tp> + _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result + __to_chars(char* __first, char* __last, _Tp __value) { + ptrdiff_t __cap = __last - __first; + int __n = __width(__value); + if (__n > __cap) + return {__last, errc::value_too_large}; + + __last = __first + __n; + char* __p = __last; + const unsigned __divisor = 16; + while (__value > __divisor) { + unsigned __c = __value % __divisor; + __value /= __divisor; + __p -= 4; + std::copy_n(&__base_2_lut[4 * __c], 4, __p); + } + do { + unsigned __c = __value % 2; + __value /= 2; + *--__p = "01"[__c]; + } while (__value != 0); + return {__last, errc(0)}; + } +}; + +template <> +struct _LIBCPP_HIDDEN __integral<8> { + template <typename _Tp> + _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept { + // If value == 0 still need one digit. If the value != this has no + // effect since the code scans for the most significat bit set. (Note + // that __libcpp_clz doesn't work for 0.) + return ((numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1)) + 2) / 3; + } + + template <typename _Tp> + _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result + __to_chars(char* __first, char* __last, _Tp __value) { + ptrdiff_t __cap = __last - __first; + int __n = __width(__value); + if (__n > __cap) + return {__last, errc::value_too_large}; + + __last = __first + __n; + char* __p = __last; + unsigned __divisor = 64; + while (__value > __divisor) { + unsigned __c = __value % __divisor; + __value /= __divisor; + __p -= 2; + std::copy_n(&__base_8_lut[2 * __c], 2, __p); + } + do { + unsigned __c = __value % 8; + __value /= 8; + *--__p = "01234567"[__c]; + } while (__value != 0); + return {__last, errc(0)}; + } +}; + +template <> +struct _LIBCPP_HIDDEN __integral<16> { + template <typename _Tp> + _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept { + // If value == 0 still need one digit. If the value != this has no + // effect since the code scans for the most significat bit set. (Note + // that __libcpp_clz doesn't work for 0.) + return (numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1) + 3) / 4; + } + + template <typename _Tp> + _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result + __to_chars(char* __first, char* __last, _Tp __value) { + ptrdiff_t __cap = __last - __first; + int __n = __width(__value); + if (__n > __cap) + return {__last, errc::value_too_large}; + + __last = __first + __n; + char* __p = __last; + unsigned __divisor = 256; + while (__value > __divisor) { + unsigned __c = __value % __divisor; + __value /= __divisor; + __p -= 2; + std::copy_n(&__base_16_lut[2 * __c], 2, __p); + } + if (__first != __last) + do { + unsigned __c = __value % 16; + __value /= 16; + *--__p = "0123456789abcdef"[__c]; + } while (__value != 0); + return {__last, errc(0)}; + } +}; + +} // namespace __itoa + +template <unsigned _Base, typename _Tp, typename enable_if<(sizeof(_Tp) >= sizeof(unsigned)), int>::type = 0> +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value) { + return __itoa::__integral<_Base>::__width(__value); +} + +template <unsigned _Base, typename _Tp, typename enable_if<(sizeof(_Tp) < sizeof(unsigned)), int>::type = 0> +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value) { + return std::__to_chars_integral_width<_Base>(static_cast<unsigned>(__value)); +} + +template <unsigned _Base, typename _Tp, typename enable_if<(sizeof(_Tp) >= sizeof(unsigned)), int>::type = 0> +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value) { + return __itoa::__integral<_Base>::__to_chars(__first, __last, __value); +} + +template <unsigned _Base, typename _Tp, typename enable_if<(sizeof(_Tp) < sizeof(unsigned)), int>::type = 0> +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value) { + return std::__to_chars_integral<_Base>(__first, __last, static_cast<unsigned>(__value)); +} + +template <typename _Tp> +_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value, unsigned __base) { + _LIBCPP_ASSERT_UNCATEGORIZED(__value >= 0, "The function requires a non-negative value."); + + unsigned __base_2 = __base * __base; + unsigned __base_3 = __base_2 * __base; + unsigned __base_4 = __base_2 * __base_2; + + int __r = 0; + while (true) { + if (__value < __base) + return __r + 1; + if (__value < __base_2) + return __r + 2; + if (__value < __base_3) + return __r + 3; + if (__value < __base_4) + return __r + 4; + + __value /= __base_4; + __r += 4; + } + + __libcpp_unreachable(); +} + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type) { + if (__base == 10) [[likely]] + return std::__to_chars_itoa(__first, __last, __value, false_type()); + + switch (__base) { + case 2: + return std::__to_chars_integral<2>(__first, __last, __value); + case 8: + return std::__to_chars_integral<8>(__first, __last, __value); + case 16: + return std::__to_chars_integral<16>(__first, __last, __value); + } + + ptrdiff_t __cap = __last - __first; + int __n = std::__to_chars_integral_width(__value, __base); + if (__n > __cap) + return {__last, errc::value_too_large}; + + __last = __first + __n; + char* __p = __last; + do { + unsigned __c = __value % __base; + __value /= __base; + *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c]; + } while (__value != 0); + return {__last, errc(0)}; +} + +template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, _Tp __value) { + using _Type = __make_32_64_or_128_bit_t<_Tp>; + static_assert(!is_same<_Type, void>::value, "unsupported integral type used in to_chars"); + return std::__to_chars_itoa(__first, __last, static_cast<_Type>(__value), is_signed<_Tp>()); +} + +template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result +to_chars(char* __first, char* __last, _Tp __value, int __base) { + _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]"); + + using _Type = __make_32_64_or_128_bit_t<_Tp>; + return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base, is_signed<_Tp>()); +} + +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H diff --git a/libcxx/include/__charconv/to_chars_result.h b/libcxx/include/__charconv/to_chars_result.h index 2eb4098dfc42..aba5e5f06b5b 100644 --- a/libcxx/include/__charconv/to_chars_result.h +++ b/libcxx/include/__charconv/to_chars_result.h @@ -11,7 +11,7 @@ #define _LIBCPP___CHARCONV_TO_CHARS_RESULT_H #include <__config> -#include <__errc> +#include <__system_error/errc.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,18 +19,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 -struct _LIBCPP_TYPE_VIS to_chars_result -{ - char* ptr; - errc ec; -# if _LIBCPP_STD_VER > 17 - _LIBCPP_HIDE_FROM_ABI friend bool operator==(const to_chars_result&, const to_chars_result&) = default; +struct _LIBCPP_EXPORTED_FROM_ABI to_chars_result { + char* ptr; + errc ec; +# if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const to_chars_result&, const to_chars_result&) = default; # endif }; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__charconv/traits.h b/libcxx/include/__charconv/traits.h new file mode 100644 index 000000000000..d3884b560dfd --- /dev/null +++ b/libcxx/include/__charconv/traits.h @@ -0,0 +1,199 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHARCONV_TRAITS +#define _LIBCPP___CHARCONV_TRAITS + +#include <__bit/countl.h> +#include <__charconv/tables.h> +#include <__charconv/to_chars_base_10.h> +#include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_unsigned.h> +#include <cstdint> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 17 + +namespace __itoa { + +template <typename _Tp, typename = void> +struct _LIBCPP_HIDDEN __traits_base; + +template <typename _Tp> +struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) <= sizeof(uint32_t)>> { + using type = uint32_t; + + /// The width estimation using a log10 algorithm. + /// + /// The algorithm is based on + /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 + /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that + /// function requires its input to have at least one bit set the value of + /// zero is set to one. This means the first element of the lookup table is + /// zero. + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { + auto __t = (32 - std::__libcpp_clz(static_cast<type>(__v | 1))) * 1233 >> 12; + return __t - (__v < __itoa::__pow10_32[__t]) + 1; + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { + return __itoa::__base_10_u32(__p, __v); + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_32)& __pow() { + return __itoa::__pow10_32; + } +}; + +template <typename _Tp> +struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(uint64_t)>> { + using type = uint64_t; + + /// The width estimation using a log10 algorithm. + /// + /// The algorithm is based on + /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 + /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that + /// function requires its input to have at least one bit set the value of + /// zero is set to one. This means the first element of the lookup table is + /// zero. + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { + auto __t = (64 - std::__libcpp_clz(static_cast<type>(__v | 1))) * 1233 >> 12; + return __t - (__v < __itoa::__pow10_64[__t]) + 1; + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { + return __itoa::__base_10_u64(__p, __v); + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_64)& __pow() { + return __itoa::__pow10_64; + } +}; + +# ifndef _LIBCPP_HAS_NO_INT128 +template <typename _Tp> +struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(__uint128_t)> > { + using type = __uint128_t; + + /// The width estimation using a log10 algorithm. + /// + /// The algorithm is based on + /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 + /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that + /// function requires its input to have at least one bit set the value of + /// zero is set to one. This means the first element of the lookup table is + /// zero. + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { + _LIBCPP_ASSERT_UNCATEGORIZED( + __v > numeric_limits<uint64_t>::max(), "The optimizations for this algorithm fail when this isn't true."); + // There's always a bit set in the upper 64-bits. + auto __t = (128 - std::__libcpp_clz(static_cast<uint64_t>(__v >> 64))) * 1233 >> 12; + _LIBCPP_ASSERT_UNCATEGORIZED(__t >= __itoa::__pow10_128_offset, "Index out of bounds"); + // __t is adjusted since the lookup table misses the lower entries. + return __t - (__v < __itoa::__pow10_128[__t - __itoa::__pow10_128_offset]) + 1; + } + + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { + return __itoa::__base_10_u128(__p, __v); + } + + // TODO FMT This pow function should get an index. + // By moving this to its own header it can be reused by the pow function in to_chars_base_10. + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_128)& __pow() { + return __itoa::__pow10_128; + } +}; +# endif + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool +__mul_overflowed(unsigned char __a, _Tp __b, unsigned char& __r) { + auto __c = __a * __b; + __r = __c; + return __c > numeric_limits<unsigned char>::max(); +} + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool +__mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) { + auto __c = __a * __b; + __r = __c; + return __c > numeric_limits<unsigned short>::max(); +} + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) { + static_assert(is_unsigned<_Tp>::value, ""); + return __builtin_mul_overflow(__a, __b, &__r); +} + +template <typename _Tp, typename _Up> +inline _LIBCPP_HIDE_FROM_ABI bool _LIBCPP_CONSTEXPR_SINCE_CXX23 __mul_overflowed(_Tp __a, _Up __b, _Tp& __r) { + return __itoa::__mul_overflowed(__a, static_cast<_Tp>(__b), __r); +} + +template <typename _Tp> +struct _LIBCPP_HIDDEN __traits : __traits_base<_Tp> { + static constexpr int digits = numeric_limits<_Tp>::digits10 + 1; + using __traits_base<_Tp>::__pow; + using typename __traits_base<_Tp>::type; + + // precondition: at least one non-zero character available + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char const* + __read(char const* __p, char const* __ep, type& __a, type& __b) { + type __cprod[digits]; + int __j = digits - 1; + int __i = digits; + do { + if (*__p < '0' || *__p > '9') + break; + __cprod[--__i] = *__p++ - '0'; + } while (__p != __ep && __i != 0); + + __a = __inner_product(__cprod + __i + 1, __cprod + __j, __pow() + 1, __cprod[__i]); + if (__itoa::__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b)) + --__p; + return __p; + } + + template <typename _It1, typename _It2, class _Up> + static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Up + __inner_product(_It1 __first1, _It1 __last1, _It2 __first2, _Up __init) { + for (; __first1 < __last1; ++__first1, ++__first2) + __init = __init + *__first1 * *__first2; + return __init; + } +}; + +} // namespace __itoa + +template <typename _Tp> +inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Tp __complement(_Tp __x) { + static_assert(is_unsigned<_Tp>::value, "cast to unsigned first"); + return _Tp(~__x + 1); +} + +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CHARCONV_TRAITS diff --git a/libcxx/include/__chrono/calendar.h b/libcxx/include/__chrono/calendar.h index d3762a631c91..91aaf6325389 100644 --- a/libcxx/include/__chrono/calendar.h +++ b/libcxx/include/__chrono/calendar.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -26,12 +26,12 @@ namespace chrono { struct local_t {}; -template<class Duration> -using local_time = time_point<local_t, Duration>; +template<class _Duration> +using local_time = time_point<local_t, _Duration>; using local_seconds = local_time<seconds>; using local_days = local_time<days>; -struct last_spec { _LIBCPP_HIDE_FROM_ABI explicit last_spec() = default; }; +struct last_spec { explicit last_spec() = default; }; inline constexpr last_spec last{}; @@ -39,6 +39,6 @@ inline constexpr last_spec last{}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_CALENDAR_H diff --git a/libcxx/include/__chrono/concepts.h b/libcxx/include/__chrono/concepts.h new file mode 100644 index 000000000000..61ec256b23ab --- /dev/null +++ b/libcxx/include/__chrono/concepts.h @@ -0,0 +1,36 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CHRONO_CONCEPTS_H +#define _LIBCPP___CHRONO_CONCEPTS_H + +#include <__chrono/hh_mm_ss.h> +#include <__chrono/time_point.h> +#include <__config> +#include <__type_traits/is_specialization.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <class _Tp> +concept __is_hh_mm_ss = __is_specialization_v<_Tp, chrono::hh_mm_ss>; + +template <class _Tp> +concept __is_time_point = __is_specialization_v<_Tp, chrono::time_point>; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___CHRONO_CONCEPTS_H diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h index 36846b3f7140..1301cd6f1f1a 100644 --- a/libcxx/include/__chrono/convert_to_tm.h +++ b/libcxx/include/__chrono/convert_to_tm.h @@ -10,8 +10,11 @@ #ifndef _LIBCPP___CHRONO_CONVERT_TO_TM_H #define _LIBCPP___CHRONO_CONVERT_TO_TM_H +#include <__chrono/calendar.h> +#include <__chrono/concepts.h> #include <__chrono/day.h> #include <__chrono/duration.h> +#include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> @@ -26,17 +29,23 @@ #include <__chrono/year_month_weekday.h> #include <__concepts/same_as.h> #include <__config> +#include <__format/format_error.h> #include <__memory/addressof.h> +#include <__type_traits/is_convertible.h> #include <cstdint> #include <ctime> +#include <limits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // Conerts a chrono date and weekday to a given _Tm type. // @@ -67,6 +76,24 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _Date& __date, chrono::weekday _ return __result; } +template <class _Tm, class _Duration> +_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const chrono::sys_time<_Duration> __tp) { + chrono::sys_days __days = chrono::floor<chrono::days>(__tp); + chrono::year_month_day __ymd{__days}; + + _Tm __result = std::__convert_to_tm<_Tm>(chrono::year_month_day{__ymd}, chrono::weekday{__days}); + + uint64_t __sec = + chrono::duration_cast<chrono::seconds>(__tp - chrono::time_point_cast<chrono::seconds>(__days)).count(); + __sec %= 24 * 3600; + __result.tm_hour = __sec / 3600; + __sec %= 3600; + __result.tm_min = __sec / 60; + __result.tm_sec = __sec % 60; + + return __result; +} + // Convert a chrono (calendar) time point, or dururation to the given _Tm type, // which must have the same properties as std::tm. template <class _Tm, class _ChronoT> @@ -76,17 +103,37 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { __result.tm_zone = "UTC"; # endif - if constexpr (chrono::__is_duration<_ChronoT>::value) { + if constexpr (__is_time_point<_ChronoT>) { + if constexpr (same_as<typename _ChronoT::clock, chrono::system_clock>) + return std::__convert_to_tm<_Tm>(__value); + else if constexpr (same_as<typename _ChronoT::clock, chrono::file_clock>) + return std::__convert_to_tm<_Tm>(_ChronoT::clock::to_sys(__value)); + else if constexpr (same_as<typename _ChronoT::clock, chrono::local_t>) + return std::__convert_to_tm<_Tm>(chrono::sys_time<typename _ChronoT::duration>{__value.time_since_epoch()}); + else + static_assert(sizeof(_ChronoT) == 0, "TODO: Add the missing clock specialization"); + } else if constexpr (chrono::__is_duration<_ChronoT>::value) { // [time.format]/6 // ... However, if a flag refers to a "time of day" (e.g. %H, %I, %p, // etc.), then a specialization of duration is interpreted as the time of // day elapsed since midnight. - uint64_t __sec = chrono::duration_cast<chrono::seconds>(__value).count(); - __sec %= 24 * 3600; - __result.tm_hour = __sec / 3600; - __sec %= 3600; - __result.tm_min = __sec / 60; - __result.tm_sec = __sec % 60; + + // Not all values can be converted to hours, it may run into ratio + // conversion errors. In that case the conversion to seconds works. + if constexpr (is_convertible_v<_ChronoT, chrono::hours>) { + auto __hour = chrono::floor<chrono::hours>(__value); + auto __sec = chrono::duration_cast<chrono::seconds>(__value - __hour); + __result.tm_hour = __hour.count() % 24; + __result.tm_min = __sec.count() / 60; + __result.tm_sec = __sec.count() % 60; + } else { + uint64_t __sec = chrono::duration_cast<chrono::seconds>(__value).count(); + __sec %= 24 * 3600; + __result.tm_hour = __sec / 3600; + __sec %= 3600; + __result.tm_min = __sec / 60; + __result.tm_sec = __sec % 60; + } } else if constexpr (same_as<_ChronoT, chrono::day>) __result.tm_mday = static_cast<unsigned>(__value); else if constexpr (same_as<_ChronoT, chrono::month>) @@ -114,14 +161,26 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { } else if constexpr (same_as<_ChronoT, chrono::year_month_weekday> || same_as<_ChronoT, chrono::year_month_weekday_last>) { return std::__convert_to_tm<_Tm>(chrono::year_month_day{static_cast<chrono::sys_days>(__value)}, __value.weekday()); + } else if constexpr (__is_hh_mm_ss<_ChronoT>) { + __result.tm_sec = __value.seconds().count(); + __result.tm_min = __value.minutes().count(); + // In libc++ hours is stored as a long. The type in std::tm is an int. So + // the overflow can only occur when hour uses more bits than an int + // provides. + if constexpr (sizeof(std::chrono::hours::rep) > sizeof(__result.tm_hour)) + if (__value.hours().count() > std::numeric_limits<decltype(__result.tm_hour)>::max()) + std::__throw_format_error("Formatting hh_mm_ss, encountered an hour overflow"); + __result.tm_hour = __value.hours().count(); } else static_assert(sizeof(_ChronoT) == 0, "Add the missing type specialization"); return __result; } -#endif //if _LIBCPP_STD_VER > 17 +#endif // if _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___CHRONO_CONVERT_TO_TM_H diff --git a/libcxx/include/__chrono/day.h b/libcxx/include/__chrono/day.h index 35ecfcf9e5bd..c907c036c146 100644 --- a/libcxx/include/__chrono/day.h +++ b/libcxx/include/__chrono/day.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -29,7 +29,7 @@ class day { private: unsigned char __d_; public: - _LIBCPP_HIDE_FROM_ABI day() = default; + day() = default; _LIBCPP_HIDE_FROM_ABI explicit inline constexpr day(unsigned __val) noexcept : __d_(static_cast<unsigned char>(__val)) {} _LIBCPP_HIDE_FROM_ABI inline constexpr day& operator++() noexcept { ++__d_; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr day operator++(int) noexcept { day __tmp = *this; ++(*this); return __tmp; } @@ -79,6 +79,6 @@ day& day::operator-=(const days& __dd) noexcept _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_DAY_H diff --git a/libcxx/include/__chrono/duration.h b/libcxx/include/__chrono/duration.h index afcc38b5cfc0..96e9671eb5a9 100644 --- a/libcxx/include/__chrono/duration.h +++ b/libcxx/include/__chrono/duration.h @@ -10,6 +10,8 @@ #ifndef _LIBCPP___CHRONO_DURATION_H #define _LIBCPP___CHRONO_DURATION_H +#include <__compare/ordering.h> +#include <__compare/three_way_comparable.h> #include <__config> #include <__type_traits/common_type.h> #include <__type_traits/enable_if.h> @@ -130,7 +132,7 @@ duration_cast(const duration<_Rep, _Period>& __fd) template <class _Rep> struct _LIBCPP_TEMPLATE_VIS treat_as_floating_point : is_floating_point<_Rep> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Rep> inline constexpr bool treat_as_floating_point_v = treat_as_floating_point<_Rep>::value; #endif @@ -144,7 +146,7 @@ public: _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR _Rep min() _NOEXCEPT {return numeric_limits<_Rep>::lowest();} }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _ToDuration, class _Rep, class _Period> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if @@ -186,11 +188,11 @@ round(const duration<_Rep, _Period>& __d) { _ToDuration __lower = chrono::floor<_ToDuration>(__d); _ToDuration __upper = __lower + _ToDuration{1}; - auto __lowerDiff = __d - __lower; - auto __upperDiff = __upper - __d; - if (__lowerDiff < __upperDiff) + auto __lower_diff = __d - __lower; + auto __upper_diff = __upper - __d; + if (__lower_diff < __upper_diff) return __lower; - if (__lowerDiff > __upperDiff) + if (__lower_diff > __upper_diff) return __upper; return __lower.count() & 1 ? __upper : __lower; } @@ -242,11 +244,10 @@ private: rep __rep_; public: - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR #ifndef _LIBCPP_CXX03_LANG - duration() = default; + constexpr duration() = default; #else - duration() {} + _LIBCPP_HIDE_FROM_ABI duration() {} #endif template <class _Rep2> @@ -307,7 +308,7 @@ typedef duration<long long, milli> milliseconds; typedef duration<long long > seconds; typedef duration< long, ratio< 60> > minutes; typedef duration< long, ratio<3600> > hours; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef duration< int, ratio_multiply<ratio<24>, hours::period>> days; typedef duration< int, ratio_multiply<ratio<7>, days::period>> weeks; typedef duration< int, ratio_multiply<ratio<146097, 400>, days::period>> years; @@ -343,6 +344,8 @@ operator==(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period return __duration_eq<duration<_Rep1, _Period1>, duration<_Rep2, _Period2> >()(__lhs, __rhs); } +#if _LIBCPP_STD_VER <= 17 + // Duration != template <class _Rep1, class _Period1, class _Rep2, class _Period2> @@ -354,6 +357,8 @@ operator!=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period return !(__lhs == __rhs); } +#endif // _LIBCPP_STD_VER <= 17 + // Duration < template <class _LhsDuration, class _RhsDuration> @@ -417,6 +422,20 @@ operator>=(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period return !(__lhs < __rhs); } +#if _LIBCPP_STD_VER >= 20 + +template<class _Rep1, class _Period1, class _Rep2, class _Period2> + requires three_way_comparable<common_type_t<_Rep1, _Rep2>> +_LIBCPP_HIDE_FROM_ABI +constexpr auto operator<=>(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) +{ + using _Ct = common_type_t<duration<_Rep1, _Period1>, duration<_Rep2, _Period2>>; + return _Ct(__lhs).count() <=> _Ct(__rhs).count(); +} + +#endif // _LIBCPP_STD_VER >= 20 + // Duration + template <class _Rep1, class _Period1, class _Rep2, class _Period2> @@ -530,7 +549,7 @@ operator%(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2 } // namespace chrono -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 // Suffixes for duration literals [time.duration.literals] inline namespace literals { @@ -609,7 +628,7 @@ namespace chrono { // hoist the literals into namespace std::chrono using namespace literals::chrono_literals; } // namespace chrono -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__chrono/file_clock.h b/libcxx/include/__chrono/file_clock.h index ef62b8329599..557a880ed452 100644 --- a/libcxx/include/__chrono/file_clock.h +++ b/libcxx/include/__chrono/file_clock.h @@ -27,7 +27,7 @@ struct _FilesystemClock; _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // !_LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -44,7 +44,7 @@ using file_time = time_point<file_clock, _Duration>; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #ifndef _LIBCPP_CXX03_LANG _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM @@ -63,9 +63,9 @@ struct _FilesystemClock { _LIBCPP_EXPORTED_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14 const bool is_steady = false; - _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_FUNC_VIS static time_point now() noexcept; + _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_EXPORTED_FROM_ABI static time_point now() noexcept; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Duration> _LIBCPP_HIDE_FROM_ABI static chrono::sys_time<_Duration> to_sys(const chrono::file_time<_Duration>& __t) { @@ -77,7 +77,7 @@ struct _FilesystemClock { static chrono::file_time<_Duration> from_sys(const chrono::sys_time<_Duration>& __t) { return chrono::file_time<_Duration>(__t.time_since_epoch()); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 }; _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // !_LIBCPP_CXX03_LANG diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h index 2015783acbbb..30ed360d4ef5 100644 --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -11,9 +11,11 @@ #define _LIBCPP___CHRONO_FORMATTER_H #include <__chrono/calendar.h> +#include <__chrono/concepts.h> #include <__chrono/convert_to_tm.h> #include <__chrono/day.h> #include <__chrono/duration.h> +#include <__chrono/file_clock.h> #include <__chrono/hh_mm_ss.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> @@ -21,6 +23,7 @@ #include <__chrono/ostream.h> #include <__chrono/parser_std_format_spec.h> #include <__chrono/statically_widen.h> +#include <__chrono/system_clock.h> #include <__chrono/time_point.h> #include <__chrono/weekday.h> #include <__chrono/year.h> @@ -35,13 +38,12 @@ #include <__format/format_functions.h> #include <__format/format_parse_context.h> #include <__format/formatter.h> -#include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> +#include <__format/write_escaped.h> #include <__memory/addressof.h> #include <cmath> #include <ctime> #include <sstream> -#include <string> #include <string_view> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -50,7 +52,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +#if _LIBCPP_STD_VER >= 20 namespace __formatter { @@ -75,13 +77,15 @@ namespace __formatter { // For tiny ratios it's not possible to convert a duration to a hh_mm_ss. This // fails compile-time due to the limited precision of the ratio (64-bit is too // small). Therefore a duration uses its own conversion. -template <class _CharT, class _Tp> - requires(chrono::__is_duration<_Tp>::value) -_LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_stringstream<_CharT>& __sstr) { +template <class _CharT, class _Rep, class _Period> +_LIBCPP_HIDE_FROM_ABI void +__format_sub_seconds(const chrono::duration<_Rep, _Period>& __value, basic_stringstream<_CharT>& __sstr) { __sstr << std::use_facet<numpunct<_CharT>>(__sstr.getloc()).decimal_point(); + using __duration = chrono::duration<_Rep, _Period>; + auto __fraction = __value - chrono::duration_cast<chrono::seconds>(__value); - if constexpr (chrono::treat_as_floating_point_v<typename _Tp::rep>) + if constexpr (chrono::treat_as_floating_point_v<_Rep>) // When the floating-point value has digits itself they are ignored based // on the wording in [tab:time.format.spec] // If the precision of the input cannot be exactly represented with @@ -96,19 +100,44 @@ _LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_string // https://godbolt.org/z/6dsbnW8ba std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}.0f}"), - __fraction.count(), - chrono::hh_mm_ss<_Tp>::fractional_width); + chrono::duration_cast<typename chrono::hh_mm_ss<__duration>::precision>(__fraction).count(), + chrono::hh_mm_ss<__duration>::fractional_width); + else + std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}}"), + chrono::duration_cast<typename chrono::hh_mm_ss<__duration>::precision>(__fraction).count(), + chrono::hh_mm_ss<__duration>::fractional_width); +} + +template <class _CharT, __is_time_point _Tp> +_LIBCPP_HIDE_FROM_ABI void __format_sub_seconds(const _Tp& __value, basic_stringstream<_CharT>& __sstr) { + __formatter::__format_sub_seconds(__value.time_since_epoch(), __sstr); +} + +template <class _CharT, class _Duration> +_LIBCPP_HIDE_FROM_ABI void +__format_sub_seconds(const chrono::hh_mm_ss<_Duration>& __value, basic_stringstream<_CharT>& __sstr) { + __sstr << std::use_facet<numpunct<_CharT>>(__sstr.getloc()).decimal_point(); + if constexpr (chrono::treat_as_floating_point_v<typename _Duration::rep>) + std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, + _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}.0f}"), + __value.subseconds().count(), + __value.fractional_width); else std::format_to(std::ostreambuf_iterator<_CharT>{__sstr}, _LIBCPP_STATICALLY_WIDEN(_CharT, "{:0{}}"), - __fraction.count(), - chrono::hh_mm_ss<_Tp>::fractional_width); + __value.subseconds().count(), + __value.fractional_width); } template <class _Tp> consteval bool __use_fraction() { - if constexpr (chrono::__is_duration<_Tp>::value) + if constexpr (__is_time_point<_Tp>) + return chrono::hh_mm_ss<typename _Tp::duration>::fractional_width; + else if constexpr (chrono::__is_duration<_Tp>::value) return chrono::hh_mm_ss<_Tp>::fractional_width; + else if constexpr (__is_hh_mm_ss<_Tp>) + return _Tp::fractional_width; else return false; } @@ -169,7 +198,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( if (__year < 1000 || __year > 9999) __formatter::__format_century(__year, __sstr); else - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); } break; case _CharT('j'): @@ -180,7 +209,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( // an intemediate step. __sstr << chrono::duration_cast<chrono::days>(chrono::duration_cast<chrono::seconds>(__value)).count(); else - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); break; case _CharT('q'): @@ -208,7 +237,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( case _CharT('S'): case _CharT('T'): - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); if constexpr (__use_fraction<_Tp>()) __formatter::__format_sub_seconds(__value, __sstr); break; @@ -240,20 +269,19 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( // // TODO FMT evaluate the comment above. -# if defined(__GLIBC__) || defined(_AIX) +# if defined(__GLIBC__) || defined(_AIX) || defined(_WIN32) case _CharT('y'): // Glibc fails for negative values, AIX for positive values too. __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02}"), (std::abs(__t.tm_year + 1900)) % 100); break; -# endif // defined(__GLIBC__) || defined(_AIX) +# endif // defined(__GLIBC__) || defined(_AIX) || defined(_WIN32) - case _CharT('Y'): { - int __year = __t.tm_year + 1900; - if (__year < 1000) - __formatter::__format_year(__year, __sstr); - else - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); - } break; + case _CharT('Y'): + // Depending on the platform's libc the range of supported years is + // limited. Intead of of testing all conditions use the internal + // implementation unconditionally. + __formatter::__format_year(__t.tm_year + 1900, __sstr); + break; case _CharT('F'): { int __year = __t.tm_year + 1900; @@ -261,9 +289,14 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( __formatter::__format_year(__year, __sstr); __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday); } else - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); } break; + case _CharT('Z'): + // TODO FMT Add proper timezone support. + __sstr << _LIBCPP_STATICALLY_WIDEN(_CharT, "UTC"); + break; + case _CharT('O'): if constexpr (__use_fraction<_Tp>()) { // Handle OS using the normal representation for the non-fractional @@ -271,7 +304,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( // fractional part should be formatted. if (*(__it + 1) == 'S') { ++__it; - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); __formatter::__format_sub_seconds(__value, __sstr); break; } @@ -281,7 +314,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( ++__it; [[fallthrough]]; default: - __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1); + __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1)); break; } } else { @@ -292,7 +325,9 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( template <class _Tp> _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { - if constexpr (same_as<_Tp, chrono::day>) + if constexpr (__is_time_point<_Tp>) + return true; + else if constexpr (same_as<_Tp, chrono::day>) return true; else if constexpr (same_as<_Tp, chrono::month>) return __value.ok(); @@ -322,13 +357,17 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_ok(const _Tp& __value) { return __value.weekday().ok(); else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) return __value.weekday().ok(); + else if constexpr (__is_hh_mm_ss<_Tp>) + return true; else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } template <class _Tp> _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { - if constexpr (same_as<_Tp, chrono::day>) + if constexpr (__is_time_point<_Tp>) + return true; + else if constexpr (same_as<_Tp, chrono::day>) return true; else if constexpr (same_as<_Tp, chrono::month>) return __value.ok(); @@ -358,13 +397,17 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __weekday_name_ok(const _Tp& __value) { return __value.weekday().ok(); else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) return __value.weekday().ok(); + else if constexpr (__is_hh_mm_ss<_Tp>) + return true; else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } template <class _Tp> _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { - if constexpr (same_as<_Tp, chrono::day>) + if constexpr (__is_time_point<_Tp>) + return true; + else if constexpr (same_as<_Tp, chrono::day>) return true; else if constexpr (same_as<_Tp, chrono::month>) return __value.ok(); @@ -394,13 +437,17 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __date_ok(const _Tp& __value) { return __value.ok(); else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) return __value.ok(); + else if constexpr (__is_hh_mm_ss<_Tp>) + return true; else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } template <class _Tp> _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { - if constexpr (same_as<_Tp, chrono::day>) + if constexpr (__is_time_point<_Tp>) + return true; + else if constexpr (same_as<_Tp, chrono::day>) return true; else if constexpr (same_as<_Tp, chrono::month>) return __value.ok(); @@ -430,16 +477,18 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __month_name_ok(const _Tp& __value) { return __value.month().ok(); else if constexpr (same_as<_Tp, chrono::year_month_weekday_last>) return __value.month().ok(); + else if constexpr (__is_hh_mm_ss<_Tp>) + return true; else static_assert(sizeof(_Tp) == 0, "Add the missing type specialization"); } -template <class _CharT, class _Tp> +template <class _CharT, class _Tp, class _FormatContext> _LIBCPP_HIDE_FROM_ABI auto __format_chrono(const _Tp& __value, - auto& __ctx, + _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs, - basic_string_view<_CharT> __chrono_specs) -> decltype(__ctx.out()) { + basic_string_view<_CharT> __chrono_specs) { basic_stringstream<_CharT> __sstr; // [time.format]/2 // 2.1 - the "C" locale if the L option is not present in chrono-format-spec, otherwise @@ -464,42 +513,63 @@ __format_chrono(const _Tp& __value, } else { // Test __weekday_name_ before __weekday_ to give a better error. if (__specs.__chrono_.__weekday_name_ && !__formatter::__weekday_name_ok(__value)) - std::__throw_format_error("formatting a weekday name needs a valid weekday"); + std::__throw_format_error("Formatting a weekday name needs a valid weekday"); if (__specs.__chrono_.__weekday_ && !__formatter::__weekday_ok(__value)) - std::__throw_format_error("formatting a weekday needs a valid weekday"); + std::__throw_format_error("Formatting a weekday needs a valid weekday"); if (__specs.__chrono_.__day_of_year_ && !__formatter::__date_ok(__value)) - std::__throw_format_error("formatting a day of year needs a valid date"); + std::__throw_format_error("Formatting a day of year needs a valid date"); if (__specs.__chrono_.__week_of_year_ && !__formatter::__date_ok(__value)) - std::__throw_format_error("formatting a week of year needs a valid date"); + std::__throw_format_error("Formatting a week of year needs a valid date"); if (__specs.__chrono_.__month_name_ && !__formatter::__month_name_ok(__value)) - std::__throw_format_error("formatting a month name from an invalid month number"); + std::__throw_format_error("Formatting a month name from an invalid month number"); + + if constexpr (__is_hh_mm_ss<_Tp>) { + // Note this is a pedantic intepretation of the Standard. A hh_mm_ss + // is no longer a time_of_day and can store an arbitrary number of + // hours. A number of hours in a 12 or 24 hour clock can't represent + // 24 hours or more. The functions std::chrono::make12 and + // std::chrono::make24 reaffirm this view point. + // + // Interestingly this will be the only output stream function that + // throws. + // + // TODO FMT The wording probably needs to be adapted to + // - The displayed hours is hh_mm_ss.hours() % 24 + // - It should probably allow %j in the same fashion as duration. + // - The stream formatter should change its output when hours >= 24 + // - Write it as not valid, + // - or write the number of days. + if (__specs.__chrono_.__hour_ && __value.hours().count() > 23) + std::__throw_format_error("Formatting a hour needs a valid value"); + + if (__value.is_negative()) + __sstr << _CharT('-'); + } __formatter::__format_chrono_using_chrono_specs(__value, __sstr, __chrono_specs); } } - // TODO FMT Use the stringstream's view after P0408R7 has been implemented. - basic_string<_CharT> __str = __sstr.str(); - return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); + return __formatter::__write_string(__sstr.view(), __ctx.out(), __specs); } } // namespace __formatter template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_chrono { +struct _LIBCPP_TEMPLATE_VIS __formatter_chrono { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto __parse( - basic_format_parse_context<_CharT>& __parse_ctx, __format_spec::__fields __fields, __format_spec::__flags __flags) - -> decltype(__parse_ctx.begin()) { - return __parser_.__parse(__parse_ctx, __fields, __flags); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator + __parse(_ParseContext& __ctx, __format_spec::__fields __fields, __format_spec::__flags __flags) { + return __parser_.__parse(__ctx, __fields, __flags); } - template <class _Tp> - _LIBCPP_HIDE_FROM_ABI auto format(const _Tp& __value, auto& __ctx) const -> decltype(__ctx.out()) const { + template <class _Tp, class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _Tp& __value, _FormatContext& __ctx) const { return __formatter::__format_chrono( __value, __ctx, __parser_.__parser_.__get_parsed_chrono_specifications(__ctx), __parser_.__chrono_specs_); } @@ -507,13 +577,47 @@ public: __format_spec::__parser_chrono<_CharT> __parser_; }; +template <class _Duration, __fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::sys_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__clock); + } +}; + +template <class _Duration, __fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::file_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__clock); + } +}; + +template <class _Duration, __fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::local_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + // The flags are not __clock since there is no associated time-zone. + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date_time); + } +}; + template <class _Rep, class _Period, __fmt_char_type _CharT> struct formatter<chrono::duration<_Rep, _Period>, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { // [time.format]/1 // Giving a precision specification in the chrono-format-spec is valid only // for std::chrono::duration types where the representation type Rep is a @@ -523,193 +627,203 @@ public: // // Note this doesn't refer to chrono::treat_as_floating_point_v<_Rep>. if constexpr (std::floating_point<_Rep>) - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono_fractional, __format_spec::__flags::__duration); + return _Base::__parse(__ctx, __format_spec::__fields_chrono_fractional, __format_spec::__flags::__duration); else - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__duration); + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__duration); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::day, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::day, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__day); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__day); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::month, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::weekday, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday_indexed, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::weekday_indexed, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::weekday_last, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::weekday_last, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__weekday); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_day, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::month_day, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_day); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_day); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_day_last, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::month_day_last, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_weekday, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::month_weekday, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::month_weekday_last, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::month_weekday_last, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__month_weekday); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year_month, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year_month); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__year_month); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_day, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year_month_day, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_day_last, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year_month_day_last, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_weekday, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year_month_weekday, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); } }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<chrono::year_month_weekday_last, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year_month_weekday_last, _CharT> : public __formatter_chrono<_CharT> { public: using _Base = __formatter_chrono<_CharT>; - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - return _Base::__parse(__parse_ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__date); } }; -#endif // if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +template <class _Duration, __fmt_char_type _CharT> +struct formatter<chrono::hh_mm_ss<_Duration>, _CharT> : public __formatter_chrono<_CharT> { +public: + using _Base = __formatter_chrono<_CharT>; + + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__time); + } +}; +#endif // if _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__chrono/hh_mm_ss.h b/libcxx/include/__chrono/hh_mm_ss.h index fd61cbe8f845..5bd452e57fa3 100644 --- a/libcxx/include/__chrono/hh_mm_ss.h +++ b/libcxx/include/__chrono/hh_mm_ss.h @@ -13,14 +13,14 @@ #include <__chrono/duration.h> #include <__chrono/time_point.h> #include <__config> +#include <__type_traits/common_type.h> #include <ratio> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -85,6 +85,7 @@ private: chrono::seconds __s_; precision __f_; }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(hh_mm_ss); _LIBCPP_HIDE_FROM_ABI constexpr bool is_am(const hours& __h) noexcept { return __h >= hours( 0) && __h < hours(12); } _LIBCPP_HIDE_FROM_ABI constexpr bool is_pm(const hours& __h) noexcept { return __h >= hours(12) && __h < hours(24); } @@ -107,6 +108,6 @@ _LIBCPP_HIDE_FROM_ABI constexpr hours make24(const hours& __h, bool __is_pm) noe _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_HH_MM_SS_H diff --git a/libcxx/include/__chrono/literals.h b/libcxx/include/__chrono/literals.h index 50529bd44ad1..28ddc43a2c0c 100644 --- a/libcxx/include/__chrono/literals.h +++ b/libcxx/include/__chrono/literals.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -44,6 +44,6 @@ namespace chrono { // hoist the literals into namespace std::chrono _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_LITERALS_H diff --git a/libcxx/include/__chrono/month.h b/libcxx/include/__chrono/month.h index e929f248842e..7566e4ed2998 100644 --- a/libcxx/include/__chrono/month.h +++ b/libcxx/include/__chrono/month.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -29,11 +29,11 @@ class month { private: unsigned char __m_; public: - _LIBCPP_HIDE_FROM_ABI month() = default; + month() = default; _LIBCPP_HIDE_FROM_ABI explicit inline constexpr month(unsigned __val) noexcept : __m_(static_cast<unsigned char>(__val)) {} - _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator++() noexcept { ++__m_; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator++() noexcept { *this += months{1}; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr month operator++(int) noexcept { month __tmp = *this; ++(*this); return __tmp; } - _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator--() noexcept { --__m_; return *this; } + _LIBCPP_HIDE_FROM_ABI inline constexpr month& operator--() noexcept { *this -= months{1}; return *this; } _LIBCPP_HIDE_FROM_ABI inline constexpr month operator--(int) noexcept { month __tmp = *this; --(*this); return __tmp; } _LIBCPP_HIDE_FROM_ABI constexpr month& operator+=(const months& __m1) noexcept; _LIBCPP_HIDE_FROM_ABI constexpr month& operator-=(const months& __m1) noexcept; @@ -98,6 +98,6 @@ inline constexpr month December{12}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_MONTH_H diff --git a/libcxx/include/__chrono/month_weekday.h b/libcxx/include/__chrono/month_weekday.h index 01cdf76d84bb..eb9e42d01f85 100644 --- a/libcxx/include/__chrono/month_weekday.h +++ b/libcxx/include/__chrono/month_weekday.h @@ -18,7 +18,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,10 +42,6 @@ bool operator==(const month_weekday& __lhs, const month_weekday& __rhs) noexcept { return __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); } _LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const month_weekday& __lhs, const month_weekday& __rhs) noexcept -{ return !(__lhs == __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr month_weekday operator/(const month& __lhs, const weekday_indexed& __rhs) noexcept { return month_weekday{__lhs, __rhs}; } @@ -78,11 +74,6 @@ bool operator==(const month_weekday_last& __lhs, const month_weekday_last& __rhs { return __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); } _LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const month_weekday_last& __lhs, const month_weekday_last& __rhs) noexcept -{ return !(__lhs == __rhs); } - - -_LIBCPP_HIDE_FROM_ABI inline constexpr month_weekday_last operator/(const month& __lhs, const weekday_last& __rhs) noexcept { return month_weekday_last{__lhs, __rhs}; } @@ -101,6 +92,6 @@ month_weekday_last operator/(const weekday_last& __lhs, int __rhs) noexcept _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_MONTH_WEEKDAY_H diff --git a/libcxx/include/__chrono/monthday.h b/libcxx/include/__chrono/monthday.h index c0ee3e4a94fd..03fd7503a6b4 100644 --- a/libcxx/include/__chrono/monthday.h +++ b/libcxx/include/__chrono/monthday.h @@ -20,7 +20,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -32,7 +32,7 @@ private: chrono::month __m_; chrono::day __d_; public: - _LIBCPP_HIDE_FROM_ABI month_day() = default; + month_day() = default; _LIBCPP_HIDE_FROM_ABI constexpr month_day(const chrono::month& __mval, const chrono::day& __dval) noexcept : __m_{__mval}, __d_{__dval} {} _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::month month() const noexcept { return __m_; } @@ -124,6 +124,6 @@ month_day_last operator/(last_spec, int __rhs) noexcept _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_MONTHDAY_H diff --git a/libcxx/include/__chrono/ostream.h b/libcxx/include/__chrono/ostream.h index 30a04bd2658b..f171944b5cab 100644 --- a/libcxx/include/__chrono/ostream.h +++ b/libcxx/include/__chrono/ostream.h @@ -10,12 +10,16 @@ #ifndef _LIBCPP___CHRONO_OSTREAM_H #define _LIBCPP___CHRONO_OSTREAM_H +#include <__chrono/calendar.h> #include <__chrono/day.h> #include <__chrono/duration.h> +#include <__chrono/file_clock.h> +#include <__chrono/hh_mm_ss.h> #include <__chrono/month.h> #include <__chrono/month_weekday.h> #include <__chrono/monthday.h> #include <__chrono/statically_widen.h> +#include <__chrono/system_clock.h> #include <__chrono/weekday.h> #include <__chrono/year.h> #include <__chrono/year_month.h> @@ -33,10 +37,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +#if _LIBCPP_STD_VER >= 20 namespace chrono { +template <class _CharT, class _Traits, class _Duration> +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_time<_Duration> __tp) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp); +} + +template <class _CharT, class _Traits, class _Duration> +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const file_time<_Duration> __tp) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp); +} + +template <class _CharT, class _Traits, class _Duration> +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const local_time<_Duration> __tp) { + return __os << sys_time<_Duration>{__tp.time_since_epoch()}; +} + // Depending on the type the return is a const _CharT* or a basic_string<_CharT> template <class _CharT, class _Period> _LIBCPP_HIDE_FROM_ABI auto __units_suffix() { @@ -92,7 +114,7 @@ _LIBCPP_HIDE_FROM_ABI auto __units_suffix() { } template <class _CharT, class _Traits, class _Rep, class _Period> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& __d) { basic_ostringstream<_CharT, _Traits> __s; __s.flags(__os.flags()); @@ -103,21 +125,19 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& -operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) { - return __os - << (__d.ok() - ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%d}"), __d) - // Note this error differs from the wording of the Standard. The - // Standard wording doesn't work well on AIX or Windows. There - // the formatted day seems to be either modulo 100 or completely - // omitted. Judging by the wording this is valid. - // TODO FMT Write a paper of file an LWG issue. - : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02} is not a valid day"), static_cast<unsigned>(__d))); +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) { + return __os << (__d.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%d}"), __d) + // Note this error differs from the wording of the Standard. The + // Standard wording doesn't work well on AIX or Windows. There + // the formatted day seems to be either modulo 100 or completely + // omitted. Judging by the wording this is valid. + // TODO FMT Write a paper of file an LWG issue. + : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:02} is not a valid day"), + static_cast<unsigned>(__d))); } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m) { return __os << (__m.ok() ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%b}"), __m) : std::format(__os.getloc(), @@ -126,14 +146,14 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m) { } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y) { return __os << (__y.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y}"), __y) : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%Y} is not a valid year"), __y)); } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd) { return __os << (__wd.ok() ? std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%a}"), __wd) : std::format(__os.getloc(), // TODO FMT Standard mandated locale isn't used. @@ -142,7 +162,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd) { } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_indexed& __wdi) { auto __i = __wdi.index(); return __os << (__i >= 1 && __i <= 5 @@ -154,13 +174,13 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_indexed& __wdi) { } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday_last& __wdl) { return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}[last]"), __wdl.weekday()); } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md) { // TODO FMT The Standard allows 30th of February to be printed. // It would be nice to show an error message instead. @@ -168,47 +188,47 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md) { } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day_last& __mdl) { return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/last"), __mdl.month()); } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const month_weekday& __mwd) { return __os << std::format( __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwd.month(), __mwd.weekday_indexed()); } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const month_weekday_last& __mwdl) { return __os << std::format( __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L}/{:L}"), __mwdl.month(), __mwdl.weekday_last()); } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month& __ym) { return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ym.year(), __ym.month()); } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_day& __ymd) { return __os << (__ymd.ok() ? std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F}"), __ymd) : std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{:%F} is not a valid date"), __ymd)); } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_day_last& __ymdl) { return __os << std::format( __os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{}/{:L}"), __ymdl.year(), __ymdl.month_day_last()); } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday& __ymwd) { return __os << std::format( __os.getloc(), @@ -219,7 +239,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday& __ymw } template <class _CharT, class _Traits> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT basic_ostream<_CharT, _Traits>& +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday_last& __ymwdl) { return __os << std::format( __os.getloc(), @@ -229,9 +249,15 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month_weekday_last& __ymwdl.weekday_last()); } +template <class _CharT, class _Traits, class _Duration> +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const hh_mm_ss<_Duration> __hms) { + return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%T}"), __hms); +} + } // namespace chrono -#endif //if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +#endif // if _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__chrono/parser_std_format_spec.h b/libcxx/include/__chrono/parser_std_format_spec.h index dbcfe6da608a..296be8794ec5 100644 --- a/libcxx/include/__chrono/parser_std_format_spec.h +++ b/libcxx/include/__chrono/parser_std_format_spec.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +#if _LIBCPP_STD_VER >= 20 namespace __format_spec { @@ -137,17 +137,19 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) { template <class _CharT> class _LIBCPP_TEMPLATE_VIS __parser_chrono { + using _ConstIterator = typename basic_format_parse_context<_CharT>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr auto - __parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields, __flags __flags) - -> decltype(__parse_ctx.begin()) { - const _CharT* __begin = __parser_.__parse(__parse_ctx, __fields); - const _CharT* __end = __parse_ctx.end(); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator + __parse(_ParseContext& __ctx, __fields __fields, __flags __flags) { + _ConstIterator __begin = __parser_.__parse(__ctx, __fields); + _ConstIterator __end = __ctx.end(); if (__begin == __end) return __begin; - const _CharT* __last = __parse_chrono_specs(__begin, __end, __flags); - __chrono_specs_ = basic_string_view<_CharT>{__begin, __last}; + _ConstIterator __last = __parse_chrono_specs(__begin, __end, __flags); + __chrono_specs_ = basic_string_view<_CharT>{__begin, __last}; return __last; } @@ -156,19 +158,20 @@ public: basic_string_view<_CharT> __chrono_specs_; private: - _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* - __parse_chrono_specs(const _CharT* __begin, const _CharT* __end, __flags __flags) { - _LIBCPP_ASSERT(__begin != __end, - "When called with an empty input the function will cause " - "undefined behavior by evaluating data not in the input"); + _LIBCPP_HIDE_FROM_ABI constexpr _ConstIterator + __parse_chrono_specs(_ConstIterator __begin, _ConstIterator __end, __flags __flags) { + _LIBCPP_ASSERT_UNCATEGORIZED( + __begin != __end, + "When called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); if (*__begin != _CharT('%') && *__begin != _CharT('}')) - std::__throw_format_error("Expected '%' or '}' in the chrono format-string"); + std::__throw_format_error("The format specifier expects a '%' or a '}'"); do { switch (*__begin) { case _CharT('{'): - std::__throw_format_error("The chrono-specs contains a '{'"); + std::__throw_format_error("The chrono specifiers contain a '{'"); case _CharT('}'): return __begin; @@ -190,10 +193,10 @@ private: /// \pre *__begin == '%' /// \post __begin points at the end parsed conversion-spec _LIBCPP_HIDE_FROM_ABI constexpr void - __parse_conversion_spec(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + __parse_conversion_spec(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) { ++__begin; if (__begin == __end) - std::__throw_format_error("End of input while parsing the modifier chrono conversion-spec"); + std::__throw_format_error("End of input while parsing a conversion specifier"); switch (*__begin) { case _CharT('n'): @@ -212,6 +215,7 @@ private: case _CharT('p'): // TODO FMT does the formater require an hour or a time? case _CharT('H'): case _CharT('I'): + __parser_.__hour_ = true; __validate_hour(__flags); break; @@ -219,6 +223,7 @@ private: case _CharT('R'): case _CharT('T'): case _CharT('X'): + __parser_.__hour_ = true; __format_spec::__validate_time(__flags); break; @@ -304,13 +309,14 @@ private: /// \pre *__begin == 'E' /// \post __begin is incremented by one. _LIBCPP_HIDE_FROM_ABI constexpr void - __parse_modifier_E(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + __parse_modifier_E(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) { ++__begin; if (__begin == __end) std::__throw_format_error("End of input while parsing the modifier E"); switch (*__begin) { case _CharT('X'): + __parser_.__hour_ = true; __format_spec::__validate_time(__flags); break; @@ -343,7 +349,7 @@ private: /// \pre *__begin == 'O' /// \post __begin is incremented by one. _LIBCPP_HIDE_FROM_ABI constexpr void - __parse_modifier_O(const _CharT*& __begin, const _CharT* __end, __flags __flags) { + __parse_modifier_O(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) { ++__begin; if (__begin == __end) std::__throw_format_error("End of input while parsing the modifier O"); @@ -359,6 +365,7 @@ private: case _CharT('I'): case _CharT('H'): + __parser_.__hour_ = true; __format_spec::__validate_hour(__flags); break; @@ -403,7 +410,7 @@ private: } // namespace __format_spec -#endif //_LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__chrono/statically_widen.h b/libcxx/include/__chrono/statically_widen.h index 360b6c2c7d57..a18c46f057a8 100644 --- a/libcxx/include/__chrono/statically_widen.h +++ b/libcxx/include/__chrono/statically_widen.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <__fmt_char_type _CharT> @@ -33,7 +33,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __statically_widen(const char* __s return __wstr; } # define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str, L##__str) -# else // _LIBCPP_HAS_NO_WIDE_CHARACTERS +# else // _LIBCPP_HAS_NO_WIDE_CHARACTERS // Without this indirection the unit test test/libcxx/modules_include.sh.cpp // fails for the CI build "No wide characters". This seems like a bug. @@ -45,7 +45,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __statically_widen(const char* __s # define _LIBCPP_STATICALLY_WIDEN(_CharT, __str) ::std::__statically_widen<_CharT>(__str) # endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__chrono/steady_clock.h b/libcxx/include/__chrono/steady_clock.h index ba83351738dd..cdcd2fa0d970 100644 --- a/libcxx/include/__chrono/steady_clock.h +++ b/libcxx/include/__chrono/steady_clock.h @@ -24,7 +24,7 @@ namespace chrono { #ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK -class _LIBCPP_TYPE_VIS steady_clock +class _LIBCPP_EXPORTED_FROM_ABI steady_clock { public: typedef nanoseconds duration; diff --git a/libcxx/include/__chrono/system_clock.h b/libcxx/include/__chrono/system_clock.h index 331db468013c..06fe071df2b6 100644 --- a/libcxx/include/__chrono/system_clock.h +++ b/libcxx/include/__chrono/system_clock.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace chrono { -class _LIBCPP_TYPE_VIS system_clock +class _LIBCPP_EXPORTED_FROM_ABI system_clock { public: typedef microseconds duration; @@ -38,7 +38,7 @@ public: static time_point from_time_t(time_t __t) _NOEXCEPT; }; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Duration> using sys_time = time_point<system_clock, _Duration>; diff --git a/libcxx/include/__chrono/time_point.h b/libcxx/include/__chrono/time_point.h index 8a8fa2176d6c..c14835401fa4 100644 --- a/libcxx/include/__chrono/time_point.h +++ b/libcxx/include/__chrono/time_point.h @@ -11,6 +11,8 @@ #define _LIBCPP___CHRONO_TIME_POINT_H #include <__chrono/duration.h> +#include <__compare/ordering.h> +#include <__compare/three_way_comparable.h> #include <__config> #include <__type_traits/common_type.h> #include <__type_traits/enable_if.h> @@ -90,7 +92,7 @@ time_point_cast(const time_point<_Clock, _Duration>& __t) return time_point<_Clock, _ToDuration>(chrono::duration_cast<_ToDuration>(__t.time_since_epoch())); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _ToDuration, class _Clock, class _Duration> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if @@ -138,7 +140,7 @@ abs(duration<_Rep, _Period> __d) { return __d >= __d.zero() ? +__d : -__d; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 // time_point == @@ -150,6 +152,8 @@ operator==(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, return __lhs.time_since_epoch() == __rhs.time_since_epoch(); } +#if _LIBCPP_STD_VER <= 17 + // time_point != template <class _Clock, class _Duration1, class _Duration2> @@ -160,6 +164,8 @@ operator!=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, return !(__lhs == __rhs); } +#endif // _LIBCPP_STD_VER <= 17 + // time_point < template <class _Clock, class _Duration1, class _Duration2> @@ -200,6 +206,16 @@ operator>=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, return !(__lhs < __rhs); } +#if _LIBCPP_STD_VER >= 20 + +template <class _Clock, class _Duration1, three_way_comparable_with<_Duration1> _Duration2> +_LIBCPP_HIDE_FROM_ABI constexpr auto +operator<=>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) { + return __lhs.time_since_epoch() <=> __rhs.time_since_epoch(); +} + +#endif // _LIBCPP_STD_VER >= 20 + // time_point operator+(time_point x, duration y); template <class _Clock, class _Duration1, class _Rep2, class _Period2> diff --git a/libcxx/include/__chrono/weekday.h b/libcxx/include/__chrono/weekday.h index e0bc8a4cae2b..776d8ed3124c 100644 --- a/libcxx/include/__chrono/weekday.h +++ b/libcxx/include/__chrono/weekday.h @@ -20,7 +20,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -35,7 +35,7 @@ private: unsigned char __wd_; _LIBCPP_HIDE_FROM_ABI static constexpr unsigned char __weekday_from_days(int __days) noexcept; public: - _LIBCPP_HIDE_FROM_ABI weekday() = default; + weekday() = default; _LIBCPP_HIDE_FROM_ABI inline explicit constexpr weekday(unsigned __val) noexcept : __wd_(static_cast<unsigned char>(__val == 7 ? 0 : __val)) {} _LIBCPP_HIDE_FROM_ABI inline constexpr weekday(const sys_days& __sysd) noexcept : __wd_(__weekday_from_days(__sysd.time_since_epoch().count())) {} @@ -70,10 +70,6 @@ bool operator==(const weekday& __lhs, const weekday& __rhs) noexcept { return __lhs.c_encoding() == __rhs.c_encoding(); } _LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const weekday& __lhs, const weekday& __rhs) noexcept -{ return !(__lhs == __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator< (const weekday& __lhs, const weekday& __rhs) noexcept { return __lhs.c_encoding() < __rhs.c_encoding(); } @@ -126,7 +122,7 @@ private: chrono::weekday __wd_; unsigned char __idx_; public: - _LIBCPP_HIDE_FROM_ABI weekday_indexed() = default; + weekday_indexed() = default; _LIBCPP_HIDE_FROM_ABI inline constexpr weekday_indexed(const chrono::weekday& __wdval, unsigned __idxval) noexcept : __wd_{__wdval}, __idx_(__idxval) {} _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::weekday weekday() const noexcept { return __wd_; } @@ -138,11 +134,6 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept { return __lhs.weekday() == __rhs.weekday() && __lhs.index() == __rhs.index(); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept -{ return !(__lhs == __rhs); } - - class weekday_last { private: chrono::weekday __wd_; @@ -158,10 +149,6 @@ bool operator==(const weekday_last& __lhs, const weekday_last& __rhs) noexcept { return __lhs.weekday() == __rhs.weekday(); } _LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const weekday_last& __lhs, const weekday_last& __rhs) noexcept -{ return !(__lhs == __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr weekday_indexed weekday::operator[](unsigned __index) const noexcept { return weekday_indexed{*this, __index}; } _LIBCPP_HIDE_FROM_ABI inline constexpr @@ -180,6 +167,6 @@ inline constexpr weekday Saturday{6}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_WEEKDAY_H diff --git a/libcxx/include/__chrono/year.h b/libcxx/include/__chrono/year.h index 79ee8a02b8fb..14bcbdafdd8a 100644 --- a/libcxx/include/__chrono/year.h +++ b/libcxx/include/__chrono/year.h @@ -22,7 +22,7 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -33,7 +33,7 @@ class year { private: short __y_; public: - _LIBCPP_HIDE_FROM_ABI year() = default; + year() = default; _LIBCPP_HIDE_FROM_ABI explicit inline constexpr year(int __val) noexcept : __y_(static_cast<short>(__val)) {} _LIBCPP_HIDE_FROM_ABI inline constexpr year& operator++() noexcept { ++__y_; return *this; } @@ -95,7 +95,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool year::ok() const noexcept { _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_POP_MACROS diff --git a/libcxx/include/__chrono/year_month.h b/libcxx/include/__chrono/year_month.h index 9f1e65c8c83d..f4eea8427fc5 100644 --- a/libcxx/include/__chrono/year_month.h +++ b/libcxx/include/__chrono/year_month.h @@ -20,7 +20,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -31,7 +31,7 @@ class year_month { chrono::year __y_; chrono::month __m_; public: - _LIBCPP_HIDE_FROM_ABI year_month() = default; + year_month() = default; _LIBCPP_HIDE_FROM_ABI constexpr year_month(const chrono::year& __yval, const chrono::month& __mval) noexcept : __y_{__yval}, __m_{__mval} {} _LIBCPP_HIDE_FROM_ABI inline constexpr chrono::year year() const noexcept { return __y_; } @@ -96,6 +96,6 @@ year_month operator-(const year_month& __lhs, const years& __rhs) noexcept _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_YEAR_MONTH_H diff --git a/libcxx/include/__chrono/year_month_day.h b/libcxx/include/__chrono/year_month_day.h index b74901470c66..ed5903f7d3f6 100644 --- a/libcxx/include/__chrono/year_month_day.h +++ b/libcxx/include/__chrono/year_month_day.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -42,7 +42,7 @@ private: chrono::month __m_; chrono::day __d_; public: - _LIBCPP_HIDE_FROM_ABI year_month_day() = default; + year_month_day() = default; _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_day( const chrono::year& __yval, const chrono::month& __mval, const chrono::day& __dval) noexcept : __y_{__yval}, __m_{__mval}, __d_{__dval} {} @@ -302,6 +302,6 @@ bool year_month_day::ok() const noexcept _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_YEAR_MONTH_DAY_H diff --git a/libcxx/include/__chrono/year_month_weekday.h b/libcxx/include/__chrono/year_month_weekday.h index 6604deaf12cd..4b5cb492a191 100644 --- a/libcxx/include/__chrono/year_month_weekday.h +++ b/libcxx/include/__chrono/year_month_weekday.h @@ -27,7 +27,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -39,7 +39,7 @@ class year_month_weekday { chrono::month __m_; chrono::weekday_indexed __wdi_; public: - _LIBCPP_HIDE_FROM_ABI year_month_weekday() = default; + year_month_weekday() = default; _LIBCPP_HIDE_FROM_ABI constexpr year_month_weekday(const chrono::year& __yval, const chrono::month& __mval, const chrono::weekday_indexed& __wdival) noexcept : __y_{__yval}, __m_{__mval}, __wdi_{__wdival} {} @@ -99,10 +99,6 @@ bool operator==(const year_month_weekday& __lhs, const year_month_weekday& __rhs { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); } _LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept -{ return !(__lhs == __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday operator/(const year_month& __lhs, const weekday_indexed& __rhs) noexcept { return year_month_weekday{__lhs.year(), __lhs.month(), __rhs}; } @@ -192,11 +188,6 @@ bool operator==(const year_month_weekday_last& __lhs, const year_month_weekday_l { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); } _LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept -{ return !(__lhs == __rhs); } - - -_LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday_last operator/(const year_month& __lhs, const weekday_last& __rhs) noexcept { return year_month_weekday_last{__lhs.year(), __lhs.month(), __rhs}; } @@ -250,6 +241,6 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr year_month_weekday_last& year_month_weekd _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #endif // _LIBCPP___CHRONO_YEAR_MONTH_WEEKDAY_H diff --git a/libcxx/include/__compare/common_comparison_category.h b/libcxx/include/__compare/common_comparison_category.h index 06c4b28491e3..5fad99bf5ce0 100644 --- a/libcxx/include/__compare/common_comparison_category.h +++ b/libcxx/include/__compare/common_comparison_category.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __comp_detail { @@ -65,14 +65,14 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __get_comp_type() { using _CCC = _ClassifyCompCategory; constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; - constexpr _CCC _Cat = __comp_detail::__compute_comp_type(__type_kinds); - if constexpr (_Cat == _None) + constexpr _CCC __cat = __comp_detail::__compute_comp_type(__type_kinds); + if constexpr (__cat == _None) return void(); - else if constexpr (_Cat == _PartialOrd) + else if constexpr (__cat == _PartialOrd) return partial_ordering::equivalent; - else if constexpr (_Cat == _WeakOrd) + else if constexpr (__cat == _WeakOrd) return weak_ordering::equivalent; - else if constexpr (_Cat == _StrongOrd) + else if constexpr (__cat == _StrongOrd) return strong_ordering::equivalent; else static_assert(_False, "unhandled case"); @@ -88,7 +88,7 @@ struct _LIBCPP_TEMPLATE_VIS common_comparison_category { template<class... _Ts> using common_comparison_category_t = typename common_comparison_category<_Ts...>::type; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/compare_partial_order_fallback.h b/libcxx/include/__compare/compare_partial_order_fallback.h index 06f03fe7adee..fb2921ed52d2 100644 --- a/libcxx/include/__compare/compare_partial_order_fallback.h +++ b/libcxx/include/__compare/compare_partial_order_fallback.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __compare_partial_order_fallback { @@ -67,7 +67,7 @@ inline namespace __cpo { inline constexpr auto compare_partial_order_fallback = __compare_partial_order_fallback::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/compare_strong_order_fallback.h b/libcxx/include/__compare/compare_strong_order_fallback.h index 869386817a12..d84d065e4064 100644 --- a/libcxx/include/__compare/compare_strong_order_fallback.h +++ b/libcxx/include/__compare/compare_strong_order_fallback.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __compare_strong_order_fallback { @@ -64,7 +64,7 @@ inline namespace __cpo { inline constexpr auto compare_strong_order_fallback = __compare_strong_order_fallback::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/compare_three_way.h b/libcxx/include/__compare/compare_three_way.h index fdbba04a78e6..2bc63a00e55d 100644 --- a/libcxx/include/__compare/compare_three_way.h +++ b/libcxx/include/__compare/compare_three_way.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct _LIBCPP_TEMPLATE_VIS compare_three_way { @@ -34,7 +34,7 @@ struct _LIBCPP_TEMPLATE_VIS compare_three_way using is_transparent = void; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/compare_three_way_result.h b/libcxx/include/__compare/compare_three_way_result.h index 8885d7effad1..632ebdce1bce 100644 --- a/libcxx/include/__compare/compare_three_way_result.h +++ b/libcxx/include/__compare/compare_three_way_result.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class, class, class> struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result { }; @@ -37,7 +37,7 @@ struct _LIBCPP_TEMPLATE_VIS compare_three_way_result : __compare_three_way_resul template<class _Tp, class _Up = _Tp> using compare_three_way_result_t = typename compare_three_way_result<_Tp, _Up>::type; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/compare_weak_order_fallback.h b/libcxx/include/__compare/compare_weak_order_fallback.h index f434dcb4a31a..d3ba04a86bcf 100644 --- a/libcxx/include/__compare/compare_weak_order_fallback.h +++ b/libcxx/include/__compare/compare_weak_order_fallback.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __compare_weak_order_fallback { @@ -64,7 +64,7 @@ inline namespace __cpo { inline constexpr auto compare_weak_order_fallback = __compare_weak_order_fallback::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/is_eq.h b/libcxx/include/__compare/is_eq.h index 49648924e81f..9a82df1ebe88 100644 --- a/libcxx/include/__compare/is_eq.h +++ b/libcxx/include/__compare/is_eq.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_eq(partial_ordering __c) noexcept { return __c == 0; } _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_neq(partial_ordering __c) noexcept { return __c != 0; } @@ -27,7 +27,7 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_lteq(partial_ordering __c) noexce _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gt(partial_ordering __c) noexcept { return __c > 0; } _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gteq(partial_ordering __c) noexcept { return __c >= 0; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/ordering.h b/libcxx/include/__compare/ordering.h index ff148abf234f..c348f0433a32 100644 --- a/libcxx/include/__compare/ordering.h +++ b/libcxx/include/__compare/ordering.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // exposition only enum class _LIBCPP_ENUM_VIS _OrdResult : signed char { @@ -40,7 +40,7 @@ template<class _Tp, class... _Args> inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); struct _CmpUnspecifiedParam { - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEVAL + _LIBCPP_HIDE_FROM_ABI constexpr _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} template<class _Tp, class = enable_if_t<!__one_of_v<_Tp, int, partial_ordering, weak_ordering, strong_ordering>>> @@ -319,7 +319,7 @@ inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater) template <class _Tp> concept __comparison_category = __one_of_v<_Tp, partial_ordering, weak_ordering, strong_ordering>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/partial_order.h b/libcxx/include/__compare/partial_order.h index aee07ebb4280..9cb76cc5bdbd 100644 --- a/libcxx/include/__compare/partial_order.h +++ b/libcxx/include/__compare/partial_order.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __partial_order { @@ -67,7 +67,7 @@ inline namespace __cpo { inline constexpr auto partial_order = __partial_order::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/strong_order.h b/libcxx/include/__compare/strong_order.h index 05856c209390..b6e0cfaaa57d 100644 --- a/libcxx/include/__compare/strong_order.h +++ b/libcxx/include/__compare/strong_order.h @@ -30,7 +30,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __strong_order { @@ -130,7 +130,7 @@ inline namespace __cpo { inline constexpr auto strong_order = __strong_order::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/synth_three_way.h b/libcxx/include/__compare/synth_three_way.h index 7d338987e0d4..6420d1362db0 100644 --- a/libcxx/include/__compare/synth_three_way.h +++ b/libcxx/include/__compare/synth_three_way.h @@ -21,30 +21,36 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [expos.only.func] -_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = - []<class _Tp, class _Up>(const _Tp& __t, const _Up& __u) - requires requires { - { __t < __u } -> __boolean_testable; - { __u < __t } -> __boolean_testable; - } - { - if constexpr (three_way_comparable_with<_Tp, _Up>) { - return __t <=> __u; - } else { - if (__t < __u) return weak_ordering::less; - if (__u < __t) return weak_ordering::greater; - return weak_ordering::equivalent; - } - }; +// TODO MODULES restore the lamba to match the Standard. +// See https://github.com/llvm/llvm-project/issues/57222 +//_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = +// []<class _Tp, class _Up>(const _Tp& __t, const _Up& __u) +template <class _Tp, class _Up> +_LIBCPP_HIDE_FROM_ABI constexpr auto __synth_three_way(const _Tp& __t, const _Up& __u) + requires requires { + { __t < __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + } +{ + if constexpr (three_way_comparable_with<_Tp, _Up>) { + return __t <=> __u; + } else { + if (__t < __u) + return weak_ordering::less; + if (__u < __t) + return weak_ordering::greater; + return weak_ordering::equivalent; + } +} template <class _Tp, class _Up = _Tp> using __synth_three_way_result = decltype(std::__synth_three_way(std::declval<_Tp&>(), std::declval<_Up&>())); -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/three_way_comparable.h b/libcxx/include/__compare/three_way_comparable.h index 6c98916d858e..2b77bc3f54e6 100644 --- a/libcxx/include/__compare/three_way_comparable.h +++ b/libcxx/include/__compare/three_way_comparable.h @@ -25,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class _Tp, class _Cat> concept __compares_as = @@ -52,7 +52,7 @@ concept three_way_comparable_with = { __u <=> __t } -> __compares_as<_Cat>; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__compare/weak_order.h b/libcxx/include/__compare/weak_order.h index abb24e3665b5..9cbc1d24aa04 100644 --- a/libcxx/include/__compare/weak_order.h +++ b/libcxx/include/__compare/weak_order.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [cmp.alg] namespace __weak_order { @@ -95,7 +95,7 @@ inline namespace __cpo { inline constexpr auto weak_order = __weak_order::__fn{}; } // namespace __cpo -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/arithmetic.h b/libcxx/include/__concepts/arithmetic.h index 215b52aa0218..f41e4c9f2747 100644 --- a/libcxx/include/__concepts/arithmetic.h +++ b/libcxx/include/__concepts/arithmetic.h @@ -22,20 +22,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concepts.arithmetic], arithmetic concepts -template<class _Tp> +template <class _Tp> concept integral = is_integral_v<_Tp>; -template<class _Tp> +template <class _Tp> concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; -template<class _Tp> +template <class _Tp> concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; -template<class _Tp> +template <class _Tp> concept floating_point = is_floating_point_v<_Tp>; // Concept helpers for the internal type traits for the fundamental types. @@ -45,7 +45,7 @@ concept __libcpp_unsigned_integer = __libcpp_is_unsigned_integer<_Tp>::value; template <class _Tp> concept __libcpp_signed_integer = __libcpp_is_signed_integer<_Tp>::value; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/assignable.h b/libcxx/include/__concepts/assignable.h index 91edd400adf6..3f7544c93406 100644 --- a/libcxx/include/__concepts/assignable.h +++ b/libcxx/include/__concepts/assignable.h @@ -22,19 +22,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.assignable] -template<class _Lhs, class _Rhs> +template <class _Lhs, class _Rhs> concept assignable_from = - is_lvalue_reference_v<_Lhs> && - common_reference_with<__make_const_lvalue_ref<_Lhs>, __make_const_lvalue_ref<_Rhs>> && - requires (_Lhs __lhs, _Rhs&& __rhs) { - { __lhs = _VSTD::forward<_Rhs>(__rhs) } -> same_as<_Lhs>; - }; + is_lvalue_reference_v<_Lhs> && + common_reference_with<__make_const_lvalue_ref<_Lhs>, __make_const_lvalue_ref<_Rhs>> && + requires(_Lhs __lhs, _Rhs&& __rhs) { + { __lhs = _VSTD::forward<_Rhs>(__rhs) } -> same_as<_Lhs>; + }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/boolean_testable.h b/libcxx/include/__concepts/boolean_testable.h index a96bde711749..d290e1cf3d83 100644 --- a/libcxx/include/__concepts/boolean_testable.h +++ b/libcxx/include/__concepts/boolean_testable.h @@ -19,19 +19,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concepts.booleantestable] -template<class _Tp> +template <class _Tp> concept __boolean_testable_impl = convertible_to<_Tp, bool>; -template<class _Tp> +template <class _Tp> concept __boolean_testable = __boolean_testable_impl<_Tp> && requires(_Tp&& __t) { { !_VSTD::forward<_Tp>(__t) } -> __boolean_testable_impl; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/class_or_enum.h b/libcxx/include/__concepts/class_or_enum.h index c4d2f98952c0..c1b4a8c258f3 100644 --- a/libcxx/include/__concepts/class_or_enum.h +++ b/libcxx/include/__concepts/class_or_enum.h @@ -21,19 +21,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // Whether a type is a class type or enumeration type according to the Core wording. -template<class _Tp> +template <class _Tp> concept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>; // Work around Clang bug https://llvm.org/PR52970 // TODO: remove this workaround once libc++ no longer has to support Clang 13 (it was fixed in Clang 14). -template<class _Tp> +template <class _Tp> concept __workaround_52970 = is_class_v<__remove_cvref_t<_Tp>> || is_union_v<__remove_cvref_t<_Tp>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/common_reference_with.h b/libcxx/include/__concepts/common_reference_with.h index cc92762d3109..4eb687e071bc 100644 --- a/libcxx/include/__concepts/common_reference_with.h +++ b/libcxx/include/__concepts/common_reference_with.h @@ -20,17 +20,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.commonref] -template<class _Tp, class _Up> +template <class _Tp, class _Up> concept common_reference_with = - same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>> && - convertible_to<_Tp, common_reference_t<_Tp, _Up>> && - convertible_to<_Up, common_reference_t<_Tp, _Up>>; + same_as<common_reference_t<_Tp, _Up>, common_reference_t<_Up, _Tp>> && + convertible_to<_Tp, common_reference_t<_Tp, _Up>> && convertible_to<_Up, common_reference_t<_Tp, _Up>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/common_with.h b/libcxx/include/__concepts/common_with.h index 569a0ee3b769..85abb05efbc2 100644 --- a/libcxx/include/__concepts/common_with.h +++ b/libcxx/include/__concepts/common_with.h @@ -23,27 +23,29 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.common] -template<class _Tp, class _Up> +// clang-format off +template <class _Tp, class _Up> concept common_with = - same_as<common_type_t<_Tp, _Up>, common_type_t<_Up, _Tp>> && - requires { - static_cast<common_type_t<_Tp, _Up>>(std::declval<_Tp>()); - static_cast<common_type_t<_Tp, _Up>>(std::declval<_Up>()); - } && - common_reference_with< - add_lvalue_reference_t<const _Tp>, - add_lvalue_reference_t<const _Up>> && - common_reference_with< - add_lvalue_reference_t<common_type_t<_Tp, _Up>>, - common_reference_t< - add_lvalue_reference_t<const _Tp>, - add_lvalue_reference_t<const _Up>>>; - -#endif // _LIBCPP_STD_VER > 17 + same_as<common_type_t<_Tp, _Up>, common_type_t<_Up, _Tp>> && + requires { + static_cast<common_type_t<_Tp, _Up>>(std::declval<_Tp>()); + static_cast<common_type_t<_Tp, _Up>>(std::declval<_Up>()); + } && + common_reference_with< + add_lvalue_reference_t<const _Tp>, + add_lvalue_reference_t<const _Up>> && + common_reference_with< + add_lvalue_reference_t<common_type_t<_Tp, _Up>>, + common_reference_t< + add_lvalue_reference_t<const _Tp>, + add_lvalue_reference_t<const _Up>>>; +// clang-format on + +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/constructible.h b/libcxx/include/__concepts/constructible.h index 1d78eb5fd157..835a44429c09 100644 --- a/libcxx/include/__concepts/constructible.h +++ b/libcxx/include/__concepts/constructible.h @@ -20,36 +20,35 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.constructible] -template<class _Tp, class... _Args> -concept constructible_from = - destructible<_Tp> && is_constructible_v<_Tp, _Args...>; +template <class _Tp, class... _Args> +concept constructible_from = destructible<_Tp> && is_constructible_v<_Tp, _Args...>; // [concept.default.init] -template<class _Tp> +template <class _Tp> concept __default_initializable = requires { ::new _Tp; }; -template<class _Tp> -concept default_initializable = constructible_from<_Tp> && - requires { _Tp{}; } && __default_initializable<_Tp>; +template <class _Tp> +concept default_initializable = constructible_from<_Tp> && requires { _Tp{}; } && __default_initializable<_Tp>; // [concept.moveconstructible] -template<class _Tp> -concept move_constructible = - constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; +template <class _Tp> +concept move_constructible = constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; // [concept.copyconstructible] -template<class _Tp> +// clang-format off +template <class _Tp> concept copy_constructible = - move_constructible<_Tp> && - constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> && - constructible_from<_Tp, const _Tp&> && convertible_to<const _Tp&, _Tp> && - constructible_from<_Tp, const _Tp> && convertible_to<const _Tp, _Tp>; + move_constructible<_Tp> && + constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> && + constructible_from<_Tp, const _Tp&> && convertible_to<const _Tp&, _Tp> && + constructible_from<_Tp, const _Tp> && convertible_to<const _Tp, _Tp>; +// clang-format on -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/convertible_to.h b/libcxx/include/__concepts/convertible_to.h index 2c1d2674100f..6d5b6c1268d5 100644 --- a/libcxx/include/__concepts/convertible_to.h +++ b/libcxx/include/__concepts/convertible_to.h @@ -19,18 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.convertible] -template<class _From, class _To> -concept convertible_to = - is_convertible_v<_From, _To> && - requires { - static_cast<_To>(std::declval<_From>()); - }; +template <class _From, class _To> +concept convertible_to = is_convertible_v<_From, _To> && requires { static_cast<_To>(std::declval<_From>()); }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/copyable.h b/libcxx/include/__concepts/copyable.h index c5d8a80b9dad..2bf0ad42fc1a 100644 --- a/libcxx/include/__concepts/copyable.h +++ b/libcxx/include/__concepts/copyable.h @@ -20,19 +20,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concepts.object] -template<class _Tp> +// clang-format off +template <class _Tp> concept copyable = - copy_constructible<_Tp> && - movable<_Tp> && - assignable_from<_Tp&, _Tp&> && - assignable_from<_Tp&, const _Tp&> && - assignable_from<_Tp&, const _Tp>; - -#endif // _LIBCPP_STD_VER > 17 + copy_constructible<_Tp> && + movable<_Tp> && + assignable_from<_Tp&, _Tp&> && + assignable_from<_Tp&, const _Tp&> && + assignable_from<_Tp&, const _Tp>; +// clang-format on + +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/derived_from.h b/libcxx/include/__concepts/derived_from.h index 0d3462df6a6d..9875faee81b9 100644 --- a/libcxx/include/__concepts/derived_from.h +++ b/libcxx/include/__concepts/derived_from.h @@ -19,16 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.derived] -template<class _Dp, class _Bp> -concept derived_from = - is_base_of_v<_Bp, _Dp> && - is_convertible_v<const volatile _Dp*, const volatile _Bp*>; +template <class _Dp, class _Bp> +concept derived_from = is_base_of_v<_Bp, _Dp> && is_convertible_v<const volatile _Dp*, const volatile _Bp*>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/destructible.h b/libcxx/include/__concepts/destructible.h index ad3819d5dcfe..28b4b1bc24ec 100644 --- a/libcxx/include/__concepts/destructible.h +++ b/libcxx/include/__concepts/destructible.h @@ -18,14 +18,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.destructible] -template<class _Tp> +template <class _Tp> concept destructible = is_nothrow_destructible_v<_Tp>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/different_from.h b/libcxx/include/__concepts/different_from.h index 15fd8f05510b..fd31f6e25805 100644 --- a/libcxx/include/__concepts/different_from.h +++ b/libcxx/include/__concepts/different_from.h @@ -19,12 +19,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 -template<class _Tp, class _Up> +template <class _Tp, class _Up> concept __different_from = !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/equality_comparable.h b/libcxx/include/__concepts/equality_comparable.h index b865141705f1..278fc7640928 100644 --- a/libcxx/include/__concepts/equality_comparable.h +++ b/libcxx/include/__concepts/equality_comparable.h @@ -21,33 +21,35 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.equalitycomparable] -template<class _Tp, class _Up> +template <class _Tp, class _Up> concept __weakly_equality_comparable_with = - requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { - { __t == __u } -> __boolean_testable; - { __t != __u } -> __boolean_testable; - { __u == __t } -> __boolean_testable; - { __u != __t } -> __boolean_testable; - }; - -template<class _Tp> + requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t == __u } -> __boolean_testable; + { __t != __u } -> __boolean_testable; + { __u == __t } -> __boolean_testable; + { __u != __t } -> __boolean_testable; + }; + +template <class _Tp> concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>; -template<class _Tp, class _Up> +// clang-format off +template <class _Tp, class _Up> concept equality_comparable_with = - equality_comparable<_Tp> && equality_comparable<_Up> && - common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && - equality_comparable< - common_reference_t< - __make_const_lvalue_ref<_Tp>, - __make_const_lvalue_ref<_Up>>> && - __weakly_equality_comparable_with<_Tp, _Up>; - -#endif // _LIBCPP_STD_VER > 17 + equality_comparable<_Tp> && equality_comparable<_Up> && + common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> && + equality_comparable< + common_reference_t< + __make_const_lvalue_ref<_Tp>, + __make_const_lvalue_ref<_Up>>> && + __weakly_equality_comparable_with<_Tp, _Up>; +// clang-format on + +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/invocable.h b/libcxx/include/__concepts/invocable.h index ec39b7b817cc..e5be514b5c38 100644 --- a/libcxx/include/__concepts/invocable.h +++ b/libcxx/include/__concepts/invocable.h @@ -19,21 +19,21 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.invocable] -template<class _Fn, class... _Args> +template <class _Fn, class... _Args> concept invocable = requires(_Fn&& __fn, _Args&&... __args) { _VSTD::invoke(_VSTD::forward<_Fn>(__fn), _VSTD::forward<_Args>(__args)...); // not required to be equality preserving }; // [concept.regular.invocable] -template<class _Fn, class... _Args> +template <class _Fn, class... _Args> concept regular_invocable = invocable<_Fn, _Args...>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/movable.h b/libcxx/include/__concepts/movable.h index 749b78ad10b8..bc5b9d767c6a 100644 --- a/libcxx/include/__concepts/movable.h +++ b/libcxx/include/__concepts/movable.h @@ -21,18 +21,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concepts.object] -template<class _Tp> -concept movable = - is_object_v<_Tp> && - move_constructible<_Tp> && - assignable_from<_Tp&, _Tp> && - swappable<_Tp>; +template <class _Tp> +concept movable = is_object_v<_Tp> && move_constructible<_Tp> && assignable_from<_Tp&, _Tp> && swappable<_Tp>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/predicate.h b/libcxx/include/__concepts/predicate.h index 7ae97832642d..00731efc8fcd 100644 --- a/libcxx/include/__concepts/predicate.h +++ b/libcxx/include/__concepts/predicate.h @@ -20,15 +20,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.predicate] -template<class _Fn, class... _Args> -concept predicate = - regular_invocable<_Fn, _Args...> && __boolean_testable<invoke_result_t<_Fn, _Args...>>; +template <class _Fn, class... _Args> +concept predicate = regular_invocable<_Fn, _Args...> && __boolean_testable<invoke_result_t<_Fn, _Args...>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/regular.h b/libcxx/include/__concepts/regular.h index d15728d298bd..9f3d8bf30be3 100644 --- a/libcxx/include/__concepts/regular.h +++ b/libcxx/include/__concepts/regular.h @@ -19,14 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.object] -template<class _Tp> +template <class _Tp> concept regular = semiregular<_Tp> && equality_comparable<_Tp>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/relation.h b/libcxx/include/__concepts/relation.h index 7d5141cac74c..7545a7db93da 100644 --- a/libcxx/include/__concepts/relation.h +++ b/libcxx/include/__concepts/relation.h @@ -18,26 +18,25 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.relation] -template<class _Rp, class _Tp, class _Up> +template <class _Rp, class _Tp, class _Up> concept relation = - predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> && - predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>; + predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> && predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>; // [concept.equiv] -template<class _Rp, class _Tp, class _Up> +template <class _Rp, class _Tp, class _Up> concept equivalence_relation = relation<_Rp, _Tp, _Up>; // [concept.strictweakorder] -template<class _Rp, class _Tp, class _Up> +template <class _Rp, class _Tp, class _Up> concept strict_weak_order = relation<_Rp, _Tp, _Up>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/same_as.h b/libcxx/include/__concepts/same_as.h index 554ebc3b074b..4241131c70c1 100644 --- a/libcxx/include/__concepts/same_as.h +++ b/libcxx/include/__concepts/same_as.h @@ -18,17 +18,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.same] -template<class _Tp, class _Up> +template <class _Tp, class _Up> concept __same_as_impl = _IsSame<_Tp, _Up>::value; -template<class _Tp, class _Up> +template <class _Tp, class _Up> concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/semiregular.h b/libcxx/include/__concepts/semiregular.h index d15bb3ba42ba..7a159d17dfc1 100644 --- a/libcxx/include/__concepts/semiregular.h +++ b/libcxx/include/__concepts/semiregular.h @@ -19,14 +19,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.object] -template<class _Tp> +template <class _Tp> concept semiregular = copyable<_Tp> && default_initializable<_Tp>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/swappable.h b/libcxx/include/__concepts/swappable.h index d91a7a1dc3c3..c1969de34510 100644 --- a/libcxx/include/__concepts/swappable.h +++ b/libcxx/include/__concepts/swappable.h @@ -28,94 +28,96 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.swappable] namespace ranges { namespace __swap { - template<class _Tp> - void swap(_Tp&, _Tp&) = delete; +template <class _Tp> +void swap(_Tp&, _Tp&) = delete; - template<class _Tp, class _Up> - concept __unqualified_swappable_with = +// clang-format off +template <class _Tp, class _Up> +concept __unqualified_swappable_with = (__class_or_enum<remove_cvref_t<_Tp>> || __class_or_enum<remove_cvref_t<_Up>>) && requires(_Tp&& __t, _Up&& __u) { - swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); + swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); }; +// clang-format on - struct __fn; +struct __fn; - template<class _Tp, class _Up, size_t _Size> - concept __swappable_arrays = - !__unqualified_swappable_with<_Tp(&)[_Size], _Up(&)[_Size]> && +// clang-format off +template <class _Tp, class _Up, size_t _Size> +concept __swappable_arrays = + !__unqualified_swappable_with<_Tp (&)[_Size], _Up (&)[_Size]> && extent_v<_Tp> == extent_v<_Up> && - requires(_Tp(& __t)[_Size], _Up(& __u)[_Size], const __fn& __swap) { - __swap(__t[0], __u[0]); + requires(_Tp (&__t)[_Size], _Up (&__u)[_Size], const __fn& __swap) { + __swap(__t[0], __u[0]); }; - - template<class _Tp> - concept __exchangeable = - !__unqualified_swappable_with<_Tp&, _Tp&> && - move_constructible<_Tp> && - assignable_from<_Tp&, _Tp>; - - struct __fn { - // 2.1 `S` is `(void)swap(E1, E2)`* if `E1` or `E2` has class or enumeration type and... - // *The name `swap` is used here unqualified. - template<class _Tp, class _Up> - requires __unqualified_swappable_with<_Tp, _Up> - constexpr void operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) - { - swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); - } - - // 2.2 Otherwise, if `E1` and `E2` are lvalues of array types with equal extent and... - template<class _Tp, class _Up, size_t _Size> - requires __swappable_arrays<_Tp, _Up, _Size> - constexpr void operator()(_Tp(& __t)[_Size], _Up(& __u)[_Size]) const - noexcept(noexcept((*this)(*__t, *__u))) - { - // TODO(cjdb): replace with `ranges::swap_ranges`. - for (size_t __i = 0; __i < _Size; ++__i) { - (*this)(__t[__i], __u[__i]); - } +// clang-format on + +template <class _Tp> +concept __exchangeable = + !__unqualified_swappable_with<_Tp&, _Tp&> && move_constructible<_Tp> && assignable_from<_Tp&, _Tp>; + +struct __fn { + // 2.1 `S` is `(void)swap(E1, E2)`* if `E1` or `E2` has class or enumeration type and... + // *The name `swap` is used here unqualified. + template <class _Tp, class _Up> + requires __unqualified_swappable_with<_Tp, _Up> + _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)))) { + swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); + } + + // 2.2 Otherwise, if `E1` and `E2` are lvalues of array types with equal extent and... + template <class _Tp, class _Up, size_t _Size> + requires __swappable_arrays<_Tp, _Up, _Size> + _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Tp (&__t)[_Size], _Up (&__u)[_Size]) const + noexcept(noexcept((*this)(*__t, *__u))) { + // TODO(cjdb): replace with `ranges::swap_ranges`. + for (size_t __i = 0; __i < _Size; ++__i) { + (*this)(__t[__i], __u[__i]); } - - // 2.3 Otherwise, if `E1` and `E2` are lvalues of the same type `T` that models... - template<__exchangeable _Tp> - constexpr void operator()(_Tp& __x, _Tp& __y) const - noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Tp>) - { - __y = _VSTD::exchange(__x, _VSTD::move(__y)); - } - }; + } + + // 2.3 Otherwise, if `E1` and `E2` are lvalues of the same type `T` that models... + template <__exchangeable _Tp> + _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Tp& __x, _Tp& __y) const + noexcept(is_nothrow_move_constructible_v<_Tp>&& is_nothrow_move_assignable_v<_Tp>) { + __y = _VSTD::exchange(__x, _VSTD::move(__y)); + } +}; } // namespace __swap inline namespace __cpo { - inline constexpr auto swap = __swap::__fn{}; +inline constexpr auto swap = __swap::__fn{}; } // namespace __cpo } // namespace ranges -template<class _Tp> +template <class _Tp> concept swappable = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); }; -template<class _Tp, class _Up> -concept swappable_with = - common_reference_with<_Tp, _Up> && - requires(_Tp&& __t, _Up&& __u) { - ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Tp>(__t)); - ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Up>(__u)); - ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); - ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t)); - }; +template <class _Tp, class _Up> +concept swappable_with = common_reference_with<_Tp, _Up> && requires(_Tp&& __t, _Up&& __u) { + ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Tp>(__t)); + ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Up>(__u)); + ranges::swap(_VSTD::forward<_Tp>(__t), _VSTD::forward<_Up>(__u)); + ranges::swap(_VSTD::forward<_Up>(__u), _VSTD::forward<_Tp>(__t)); +}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___CONCEPTS_SWAPPABLE_H diff --git a/libcxx/include/__concepts/totally_ordered.h b/libcxx/include/__concepts/totally_ordered.h index f12d26b10827..186c3b430dd5 100644 --- a/libcxx/include/__concepts/totally_ordered.h +++ b/libcxx/include/__concepts/totally_ordered.h @@ -21,37 +21,38 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [concept.totallyordered] -template<class _Tp, class _Up> -concept __partially_ordered_with = - requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { - { __t < __u } -> __boolean_testable; - { __t > __u } -> __boolean_testable; - { __t <= __u } -> __boolean_testable; - { __t >= __u } -> __boolean_testable; - { __u < __t } -> __boolean_testable; - { __u > __t } -> __boolean_testable; - { __u <= __t } -> __boolean_testable; - { __u >= __t } -> __boolean_testable; - }; - -template<class _Tp> +template <class _Tp, class _Up> +concept __partially_ordered_with = requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) { + { __t < __u } -> __boolean_testable; + { __t > __u } -> __boolean_testable; + { __t <= __u } -> __boolean_testable; + { __t >= __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + { __u > __t } -> __boolean_testable; + { __u <= __t } -> __boolean_testable; + { __u >= __t } -> __boolean_testable; +}; + +template <class _Tp> concept totally_ordered = equality_comparable<_Tp> && __partially_ordered_with<_Tp, _Tp>; -template<class _Tp, class _Up> +// clang-format off +template <class _Tp, class _Up> concept totally_ordered_with = - totally_ordered<_Tp> && totally_ordered<_Up> && - equality_comparable_with<_Tp, _Up> && - totally_ordered< - common_reference_t< - __make_const_lvalue_ref<_Tp>, - __make_const_lvalue_ref<_Up>>> && - __partially_ordered_with<_Tp, _Up>; - -#endif // _LIBCPP_STD_VER > 17 + totally_ordered<_Tp> && totally_ordered<_Up> && + equality_comparable_with<_Tp, _Up> && + totally_ordered< + common_reference_t< + __make_const_lvalue_ref<_Tp>, + __make_const_lvalue_ref<_Up>>> && + __partially_ordered_with<_Tp, _Up>; +// clang-format on + +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__condition_variable/condition_variable.h b/libcxx/include/__condition_variable/condition_variable.h new file mode 100644 index 000000000000..7cbf21fe7311 --- /dev/null +++ b/libcxx/include/__condition_variable/condition_variable.h @@ -0,0 +1,245 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___CONDITION_VARIABLE_CONDITION_VARIABLE_H +#define _LIBCPP___CONDITION_VARIABLE_CONDITION_VARIABLE_H + +#include <__chrono/steady_clock.h> +#include <__chrono/system_clock.h> +#include <__chrono/time_point.h> +#include <__config> +#include <__mutex/mutex.h> +#include <__mutex/unique_lock.h> +#include <__system_error/system_error.h> +#include <__threading_support> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_floating_point.h> +#include <__utility/move.h> +#include <limits> +#include <ratio> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_THREADS + +// enum class cv_status +_LIBCPP_DECLARE_STRONG_ENUM(cv_status){no_timeout, timeout}; +_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) + +class _LIBCPP_EXPORTED_FROM_ABI condition_variable { + __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; + +public: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; + +# ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION + ~condition_variable() = default; +# else + ~condition_variable(); +# endif + + condition_variable(const condition_variable&) = delete; + condition_variable& operator=(const condition_variable&) = delete; + + void notify_one() _NOEXCEPT; + void notify_all() _NOEXCEPT; + + void wait(unique_lock<mutex>& __lk) _NOEXCEPT; + template <class _Predicate> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(unique_lock<mutex>& __lk, _Predicate __pred); + + template <class _Clock, class _Duration> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status + wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t); + + template <class _Clock, class _Duration, class _Predicate> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool + wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred); + + template <class _Rep, class _Period> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status + wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d); + + template <class _Rep, class _Period, class _Predicate> + bool _LIBCPP_HIDE_FROM_ABI + wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred); + + typedef __libcpp_condvar_t* native_handle_type; + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; } + +private: + void + __do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT; +# if defined(_LIBCPP_HAS_COND_CLOCKWAIT) + _LIBCPP_HIDE_FROM_ABI void + __do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT; +# endif + template <class _Clock> + _LIBCPP_HIDE_FROM_ABI void + __do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; +}; +#endif // !_LIBCPP_HAS_NO_THREADS + +template <class _Rep, class _Period> +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<is_floating_point<_Rep>::value, chrono::nanoseconds> +__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) { + using namespace chrono; + using __ratio = ratio_divide<_Period, nano>; + using __ns_rep = nanoseconds::rep; + _Rep __result_float = __d.count() * __ratio::num / __ratio::den; + + _Rep __result_max = numeric_limits<__ns_rep>::max(); + if (__result_float >= __result_max) { + return nanoseconds::max(); + } + + _Rep __result_min = numeric_limits<__ns_rep>::min(); + if (__result_float <= __result_min) { + return nanoseconds::min(); + } + + return nanoseconds(static_cast<__ns_rep>(__result_float)); +} + +template <class _Rep, class _Period> +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<!is_floating_point<_Rep>::value, chrono::nanoseconds> +__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) { + using namespace chrono; + if (__d.count() == 0) { + return nanoseconds(0); + } + + using __ratio = ratio_divide<_Period, nano>; + using __ns_rep = nanoseconds::rep; + __ns_rep __result_max = numeric_limits<__ns_rep>::max(); + if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) { + return nanoseconds::max(); + } + + __ns_rep __result_min = numeric_limits<__ns_rep>::min(); + if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) { + return nanoseconds::min(); + } + + __ns_rep __result = __d.count() * __ratio::num / __ratio::den; + if (__result == 0) { + return nanoseconds(1); + } + + return nanoseconds(__result); +} + +#ifndef _LIBCPP_HAS_NO_THREADS +template <class _Predicate> +void condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) { + while (!__pred()) + wait(__lk); +} + +template <class _Clock, class _Duration> +cv_status condition_variable::wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t) { + using namespace chrono; + using __clock_tp_ns = time_point<_Clock, nanoseconds>; + + typename _Clock::time_point __now = _Clock::now(); + if (__t <= __now) + return cv_status::timeout; + + __clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch())); + + __do_timed_wait(__lk, __t_ns); + return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; +} + +template <class _Clock, class _Duration, class _Predicate> +bool condition_variable::wait_until( + unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) { + while (!__pred()) { + if (wait_until(__lk, __t) == cv_status::timeout) + return __pred(); + } + return true; +} + +template <class _Rep, class _Period> +cv_status condition_variable::wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d) { + using namespace chrono; + if (__d <= __d.zero()) + return cv_status::timeout; + using __ns_rep = nanoseconds::rep; + steady_clock::time_point __c_now = steady_clock::now(); + +# if defined(_LIBCPP_HAS_COND_CLOCKWAIT) + using __clock_tp_ns = time_point<steady_clock, nanoseconds>; + __ns_rep __now_count_ns = std::__safe_nanosecond_cast(__c_now.time_since_epoch()).count(); +# else + using __clock_tp_ns = time_point<system_clock, nanoseconds>; + __ns_rep __now_count_ns = std::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); +# endif + + __ns_rep __d_ns_count = std::__safe_nanosecond_cast(__d).count(); + + if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) { + __do_timed_wait(__lk, __clock_tp_ns::max()); + } else { + __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count))); + } + + return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout; +} + +template <class _Rep, class _Period, class _Predicate> +inline bool +condition_variable::wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred) { + return wait_until(__lk, chrono::steady_clock::now() + __d, std::move(__pred)); +} + +# if defined(_LIBCPP_HAS_COND_CLOCKWAIT) +inline void condition_variable::__do_timed_wait( + unique_lock<mutex>& __lk, chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT { + using namespace chrono; + if (!__lk.owns_lock()) + __throw_system_error(EPERM, "condition_variable::timed wait: mutex not locked"); + nanoseconds __d = __tp.time_since_epoch(); + timespec __ts; + seconds __s = duration_cast<seconds>(__d); + using __ts_sec = decltype(__ts.tv_sec); + const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); + if (__s.count() < __ts_sec_max) { + __ts.tv_sec = static_cast<__ts_sec>(__s.count()); + __ts.tv_nsec = (__d - __s).count(); + } else { + __ts.tv_sec = __ts_sec_max; + __ts.tv_nsec = giga::num - 1; + } + int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts); + if (__ec != 0 && __ec != ETIMEDOUT) + __throw_system_error(__ec, "condition_variable timed_wait failed"); +} +# endif // _LIBCPP_HAS_COND_CLOCKWAIT + +template <class _Clock> +inline void condition_variable::__do_timed_wait(unique_lock<mutex>& __lk, + chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT { + wait_for(__lk, __tp - _Clock::now()); +} + +#endif // _LIBCPP_HAS_NO_THREADS + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___CONDITION_VARIABLE_CONDITION_VARIABLE_H diff --git a/libcxx/include/__config b/libcxx/include/__config index b9203e640a3e..9759d3b9e8e0 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -23,6 +23,7 @@ #endif #if defined(__apple_build_version__) +// Given AppleClang XX.Y.Z, _LIBCPP_APPLE_CLANG_VER is XXYZ (e.g. AppleClang 14.0.3 => 1403) # define _LIBCPP_COMPILER_CLANG_BASED # define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000) #elif defined(__clang__) @@ -34,10 +35,12 @@ #ifdef __cplusplus +// The attributes supported by clang are documented at https://clang.llvm.org/docs/AttributeReference.html + // _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM. -// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 16.0.1 == 16.00.01), _LIBCPP_VERSION is +// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is // defined to XXYYZZ. -# define _LIBCPP_VERSION 160000 +# define _LIBCPP_VERSION 170000 # define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y # define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y) @@ -50,6 +53,7 @@ # define _LIBCPP_FREESTANDING # endif +// NOLINTBEGIN(libcpp-cpp-version-check) # ifndef _LIBCPP_STD_VER # if __cplusplus <= 201103L # define _LIBCPP_STD_VER 11 @@ -59,11 +63,14 @@ # define _LIBCPP_STD_VER 17 # elif __cplusplus <= 202002L # define _LIBCPP_STD_VER 20 +# elif __cplusplus <= 202302L +# define _LIBCPP_STD_VER 23 # else // Expected release year of the next C++ standard -# define _LIBCPP_STD_VER 23 +# define _LIBCPP_STD_VER 26 # endif # endif // _LIBCPP_STD_VER +// NOLINTEND(libcpp-cpp-version-check) # if defined(__ELF__) # define _LIBCPP_OBJECT_FORMAT_ELF 1 @@ -79,6 +86,8 @@ // ... add new file formats here ... # endif +// ABI { + # if _LIBCPP_ABI_VERSION >= 2 // Change short string representation so that string data starts at offset 0, // improving its alignment in some cases. @@ -134,6 +143,15 @@ # define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON // According to the Standard, `bitset::operator[] const` returns bool # define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL +// Fix the implementation of CityHash used for std::hash<fundamental-type>. +// This is an ABI break because `std::hash` will return a different result, +// which means that hashing the same object in translation units built against +// different versions of libc++ can return inconsistent results. This is especially +// tricky since std::hash is used in the implementation of unordered containers. +// +// The incorrect implementation of CityHash has the problem that it drops some +// bits on the floor. +# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION // Remove the base 10 implementation of std::to_chars from the dylib. // The implementation moved to the header, but we still export the symbols from // the dylib for backwards compatibility. @@ -155,6 +173,12 @@ # if defined(__FreeBSD__) # define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR # endif +// For XCOFF linkers, we have problems if we see a weak hidden version of a symbol +// in user code (like you get with -fvisibility-inlines-hidden) and then a strong def +// in the library, so we need to always rely on the library version. +# if defined(_AIX) +# define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION +# endif # endif # if defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_ABI_VERSION >= 2 @@ -169,9 +193,137 @@ # define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION # endif +// Changes the iterator type of select containers (see below) to a bounded iterator that keeps track of whether it's +// within the bounds of the original container and asserts it on every dereference. +// +// ABI impact: changes the iterator type of the relevant containers. +// +// Supported containers: +// - `span`; +// - `string_view`; +// - `array`. +// #define _LIBCPP_ABI_BOUNDED_ITERATORS + +// } ABI + +// HARDENING { + +// TODO(hardening): remove this in LLVM 18. +// This is for backward compatibility -- make enabling `_LIBCPP_ENABLE_ASSERTIONS` (which predates hardening modes) +// equivalent to setting the hardened mode. +# ifdef _LIBCPP_ENABLE_ASSERTIONS +# warning "_LIBCPP_ENABLE_ASSERTIONS is deprecated, please use _LIBCPP_ENABLE_HARDENED_MODE instead." +# if _LIBCPP_ENABLE_ASSERTIONS != 0 && _LIBCPP_ENABLE_ASSERTIONS != 1 +# error "_LIBCPP_ENABLE_ASSERTIONS must be set to 0 or 1" +# endif +# if _LIBCPP_ENABLE_ASSERTIONS +# define _LIBCPP_ENABLE_HARDENED_MODE 1 +# endif +# endif + +// Enables the hardened mode which consists of all checks intended to be used in production. Hardened mode prioritizes +// security-critical checks that can be done with relatively little overhead in constant time. Mutually exclusive with +// `_LIBCPP_ENABLE_DEBUG_MODE`. +// +// #define _LIBCPP_ENABLE_HARDENED_MODE 1 + +// Enables the debug mode which contains all the checks from the hardened mode and additionally more expensive checks +// that may affect the complexity of algorithms. The debug mode is intended to be used for testing, not in production. +// Mutually exclusive with `_LIBCPP_ENABLE_HARDENED_MODE`. +// +// #define _LIBCPP_ENABLE_DEBUG_MODE 1 + +// Inside the library, assertions are categorized so they can be cherry-picked based on the chosen hardening mode. These +// macros are only for internal use -- users should only pick one of the high-level hardening modes described above. +// +// - `_LIBCPP_ASSERT_VALID_INPUT_RANGE` -- checks that ranges (whether expressed as an iterator pair, an iterator and +// a sentinel, an iterator and a count, or a `std::range`) given as input to library functions are valid: +// - the sentinel is reachable from the begin iterator; +// - TODO(hardening): both iterators refer to the same container. +// +// - `_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS` -- checks that any attempts to access a container element, whether through +// the container object or through an iterator, are valid and do not attempt to go out of bounds or otherwise access +// a non-existent element. For iterator checks to work, bounded iterators must be enabled in the ABI. Types like +// `optional` and `function` are considered one-element containers for the purposes of this check. +// +// - `_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES` -- for functions that take several ranges as arguments, checks that the +// given ranges do not overlap. +// +// - `_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR` -- checks any operations that exchange nodes between containers to make sure +// the containers have compatible allocators. +// +// - `_LIBCPP_ASSERT_INTERNAL` -- checks that internal invariants of the library hold. These assertions don't depend on +// user input. +// +// - `_LIBCPP_ASSERT_UNCATEGORIZED` -- for assertions that haven't been properly classified yet. + +# ifndef _LIBCPP_ENABLE_HARDENED_MODE +# define _LIBCPP_ENABLE_HARDENED_MODE _LIBCPP_ENABLE_HARDENED_MODE_DEFAULT +# endif +# if _LIBCPP_ENABLE_HARDENED_MODE != 0 && _LIBCPP_ENABLE_HARDENED_MODE != 1 +# error "_LIBCPP_ENABLE_HARDENED_MODE must be set to 0 or 1." +# endif + +# ifndef _LIBCPP_ENABLE_DEBUG_MODE +# define _LIBCPP_ENABLE_DEBUG_MODE _LIBCPP_ENABLE_DEBUG_MODE_DEFAULT +# endif +# if _LIBCPP_ENABLE_DEBUG_MODE != 0 && _LIBCPP_ENABLE_DEBUG_MODE != 1 +# error "_LIBCPP_ENABLE_DEBUG_MODE must be set to 0 or 1." +# endif + +# if _LIBCPP_ENABLE_HARDENED_MODE && _LIBCPP_ENABLE_DEBUG_MODE +# error "Only one of _LIBCPP_ENABLE_HARDENED_MODE and _LIBCPP_ENABLE_DEBUG_MODE can be enabled." +# endif + +// Hardened mode checks. + +// clang-format off +# if _LIBCPP_ENABLE_HARDENED_MODE + +// Enabled checks. +# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message) +// Disabled checks. +// Overlapping ranges will make algorithms produce incorrect results but don't directly lead to a security +// vulnerability. +# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression) + +// Debug mode checks. + +# elif _LIBCPP_ENABLE_DEBUG_MODE + +// All checks enabled. +# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSERT(expression, message) +# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSERT(expression, message) + +// Disable all checks if hardening is not enabled. + +# else + +// All checks disabled. +# define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_INTERNAL(expression, message) _LIBCPP_ASSUME(expression) +# define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message) _LIBCPP_ASSUME(expression) + +# endif // _LIBCPP_ENABLE_HARDENED_MODE +// clang-format on + +// } HARDENING + # define _LIBCPP_TOSTRING2(x) #x # define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x) +// NOLINTNEXTLINE(libcpp-cpp-version-check) # if __cplusplus < 201103L # define _LIBCPP_CXX03_LANG # endif @@ -252,7 +404,11 @@ // Incomplete features get their own specific disabling flags. This makes it // easier to grep for target specific flags once the feature is complete. # if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY) -# define _LIBCPP_HAS_NO_INCOMPLETE_FORMAT +# define _LIBCPP_HAS_NO_INCOMPLETE_PSTL +# endif + +# if !defined(_LIBCPP_ENABLE_EXPERIMENTAL) && !defined(_LIBCPP_BUILDING_LIBRARY) +# define _LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN # endif // Need to detect which libc we're using if we're on Linux. @@ -290,8 +446,8 @@ # endif // __BYTE_ORDER__ # ifdef __FreeBSD__ -# include <sys/endian.h> # include <osreldate.h> +# include <sys/endian.h> # if _BYTE_ORDER == _LITTLE_ENDIAN # define _LIBCPP_LITTLE_ENDIAN # else // _BYTE_ORDER == _LITTLE_ENDIAN @@ -325,15 +481,6 @@ # define _LIBCPP_HAS_OPEN_WITH_WCHAR # endif // defined(_WIN32) -# ifdef __sun__ -# include <sys/isa_defs.h> -# ifdef _LITTLE_ENDIAN -# define _LIBCPP_LITTLE_ENDIAN -# else -# define _LIBCPP_BIG_ENDIAN -# endif -# endif // __sun__ - # if defined(_AIX) && !defined(__64BIT__) // The size of wchar is 2 byte on 32-bit mode on AIX. # define _LIBCPP_SHORT_WCHAR 1 @@ -378,7 +525,7 @@ // When this option is used, the token passed to `std::random_device`'s // constructor *must* be "/dev/urandom" -- anything else is an error. # if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ - defined(__DragonFly__) || defined(__sun__) + defined(__DragonFly__) # define _LIBCPP_USING_ARC4_RANDOM # elif defined(__wasi__) || defined(__EMSCRIPTEN__) # define _LIBCPP_USING_GETENTROPY @@ -439,15 +586,24 @@ typedef __char32_t char32_t; # endif # if !defined(__cpp_exceptions) || __cpp_exceptions < 199711L -# define _LIBCPP_NO_EXCEPTIONS +# define _LIBCPP_HAS_NO_EXCEPTIONS # endif # define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp) # if defined(_LIBCPP_COMPILER_CLANG_BASED) -# if defined(__APPLE__) && !defined(__i386__) && !defined(__x86_64__) && (!defined(__arm__) || __ARM_ARCH_7K__ >= 2) -# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# if defined(__APPLE__) +# if defined(__i386__) || defined(__x86_64__) +// use old string layout on x86_64 and i386 +# elif defined(__arm__) +// use old string layout on arm (which does not include aarch64/arm64), except on watch ABIs +# if defined(__ARM_ARCH_7K__) && __ARM_ARCH_7K__ >= 2 +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# endif +# else +# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +# endif # endif // Objective-C++ features (opt-in) @@ -525,9 +681,6 @@ typedef __char32_t char32_t; # define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllimport) # endif -# define _LIBCPP_TYPE_VIS _LIBCPP_DLL_VIS -# define _LIBCPP_FUNC_VIS _LIBCPP_DLL_VIS -# define _LIBCPP_EXCEPTION_ABI _LIBCPP_DLL_VIS # define _LIBCPP_HIDDEN # define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS # define _LIBCPP_TEMPLATE_VIS @@ -543,11 +696,8 @@ typedef __char32_t char32_t; # endif # define _LIBCPP_HIDDEN _LIBCPP_VISIBILITY("hidden") -# define _LIBCPP_FUNC_VIS _LIBCPP_VISIBILITY("default") -# define _LIBCPP_TYPE_VIS _LIBCPP_VISIBILITY("default") # define _LIBCPP_TEMPLATE_DATA_VIS _LIBCPP_VISIBILITY("default") # define _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_VISIBILITY("default") -# define _LIBCPP_EXCEPTION_ABI _LIBCPP_VISIBILITY("default") # define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_VISIBILITY("default") # define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS @@ -629,7 +779,11 @@ typedef __char32_t char32_t; # else # define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION # endif -# define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION +# define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION + +// This macro provides a HIDE_FROM_ABI equivalent that can be applied to extern +// "C" function, as those lack mangling. +# define _LIBCPP_HIDE_FROM_ABI_C _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION # ifdef _LIBCPP_BUILDING_LIBRARY # if _LIBCPP_ABI_VERSION > 1 @@ -652,7 +806,7 @@ typedef __char32_t char32_t; _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD -# if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 # define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ _LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem { # else @@ -669,16 +823,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_PREFERRED_OVERLOAD __attribute__((__enable_if__(true, ""))) # endif -# ifndef __SIZEOF_INT128__ +# if !defined(__SIZEOF_INT128__) || defined(_MSC_VER) # define _LIBCPP_HAS_NO_INT128 # endif -# ifndef __cpp_consteval -# define _LIBCPP_CONSTEVAL _LIBCPP_CONSTEXPR -# else -# define _LIBCPP_CONSTEVAL consteval -# endif - # if __has_attribute(__malloc__) # define _LIBCPP_NOALIAS __attribute__((__malloc__)) # else @@ -693,7 +841,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # ifdef _LIBCPP_CXX03_LANG # define _LIBCPP_DECLARE_STRONG_ENUM(x) \ - struct _LIBCPP_TYPE_VIS x { \ + struct _LIBCPP_EXPORTED_FROM_ABI x { \ enum __lx // clang-format off # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \ @@ -709,8 +857,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) # endif // _LIBCPP_CXX03_LANG -# if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT_LIKE) || defined(__sun__) || \ - defined(__NetBSD__) +# if defined(__APPLE__) || defined(__FreeBSD__) || defined(_LIBCPP_MSVCRT_LIKE) || defined(__NetBSD__) # define _LIBCPP_LOCALE__L_EXTENSIONS 1 # endif @@ -750,7 +897,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_HAS_DEFAULTRUNELOCALE # endif -# if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun__) +# if defined(__APPLE__) || defined(__FreeBSD__) # define _LIBCPP_WCTYPE_IS_MASK # endif @@ -763,10 +910,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // Deprecations warnings are always enabled, except when users explicitly opt-out // by defining _LIBCPP_DISABLE_DEPRECATION_WARNINGS. # if !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) -# if __has_attribute(deprecated) -# define _LIBCPP_DEPRECATED __attribute__((deprecated)) -# define _LIBCPP_DEPRECATED_(m) __attribute__((deprecated(m))) -# elif _LIBCPP_STD_VER > 11 +# if __has_attribute(__deprecated__) +# define _LIBCPP_DEPRECATED __attribute__((__deprecated__)) +# define _LIBCPP_DEPRECATED_(m) __attribute__((__deprecated__(m))) +# elif _LIBCPP_STD_VER >= 14 # define _LIBCPP_DEPRECATED [[deprecated]] # define _LIBCPP_DEPRECATED_(m) [[deprecated(m)]] # else @@ -784,29 +931,29 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_DEPRECATED_IN_CXX11 # endif -# if _LIBCPP_STD_VER > 11 +# if _LIBCPP_STD_VER >= 14 # define _LIBCPP_DEPRECATED_IN_CXX14 _LIBCPP_DEPRECATED # else # define _LIBCPP_DEPRECATED_IN_CXX14 # endif -# if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 # define _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_DEPRECATED # else # define _LIBCPP_DEPRECATED_IN_CXX17 # endif -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 # define _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_DEPRECATED # else # define _LIBCPP_DEPRECATED_IN_CXX20 # endif -#if _LIBCPP_STD_VER >= 23 -# define _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_DEPRECATED -#else -# define _LIBCPP_DEPRECATED_IN_CXX23 -#endif +# if _LIBCPP_STD_VER >= 23 +# define _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_DEPRECATED +# else +# define _LIBCPP_DEPRECATED_IN_CXX23 +# endif # if !defined(_LIBCPP_HAS_NO_CHAR8_T) # define _LIBCPP_DEPRECATED_WITH_CHAR8_T _LIBCPP_DEPRECATED @@ -826,37 +973,43 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # endif # if _LIBCPP_STD_VER <= 11 -# define _LIBCPP_EXPLICIT_AFTER_CXX11 +# define _LIBCPP_EXPLICIT_SINCE_CXX14 # else -# define _LIBCPP_EXPLICIT_AFTER_CXX11 explicit +# define _LIBCPP_EXPLICIT_SINCE_CXX14 explicit # endif -# if _LIBCPP_STD_VER > 11 +# if _LIBCPP_STD_VER >= 23 +# define _LIBCPP_EXPLICIT_SINCE_CXX23 explicit +# else +# define _LIBCPP_EXPLICIT_SINCE_CXX23 +# endif + +# if _LIBCPP_STD_VER >= 14 # define _LIBCPP_CONSTEXPR_SINCE_CXX14 constexpr # else # define _LIBCPP_CONSTEXPR_SINCE_CXX14 # endif -# if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 # define _LIBCPP_CONSTEXPR_SINCE_CXX17 constexpr # else # define _LIBCPP_CONSTEXPR_SINCE_CXX17 # endif -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 # define _LIBCPP_CONSTEXPR_SINCE_CXX20 constexpr # else # define _LIBCPP_CONSTEXPR_SINCE_CXX20 # endif -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 # define _LIBCPP_CONSTEXPR_SINCE_CXX23 constexpr # else # define _LIBCPP_CONSTEXPR_SINCE_CXX23 # endif # if __has_cpp_attribute(nodiscard) -# define _LIBCPP_NODISCARD [[nodiscard]] +# define _LIBCPP_NODISCARD [[__nodiscard__]] # else // We can't use GCC's [[gnu::warn_unused_result]] and // __attribute__((warn_unused_result)), because GCC does not silence them via @@ -872,7 +1025,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_NODISCARD_EXT # endif -# if _LIBCPP_STD_VER > 17 || !defined(_LIBCPP_DISABLE_NODISCARD_EXT) +# if _LIBCPP_STD_VER >= 20 || !defined(_LIBCPP_DISABLE_NODISCARD_EXT) # define _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_NODISCARD # else # define _LIBCPP_NODISCARD_AFTER_CXX17 @@ -885,13 +1038,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # endif # ifndef _LIBCPP_HAS_NO_ASAN - extern "C" _LIBCPP_FUNC_VIS void + extern "C" _LIBCPP_EXPORTED_FROM_ABI void __sanitizer_annotate_contiguous_container(const void*, const void*, const void*, const void*); +# if _LIBCPP_CLANG_VER >= 1600 +extern "C" _LIBCPP_EXPORTED_FROM_ABI void __sanitizer_annotate_double_ended_contiguous_container( + const void*, const void*, const void*, const void*, const void*, const void*); +extern "C" _LIBCPP_EXPORTED_FROM_ABI int +__sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*); +# endif # endif // Try to find out if RTTI is disabled. # if !defined(__cpp_rtti) || __cpp_rtti < 199711L -# define _LIBCPP_NO_RTTI +# define _LIBCPP_HAS_NO_RTTI # endif # ifndef _LIBCPP_WEAK @@ -913,7 +1072,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD defined(__linux__) || \ defined(__GNU__) || \ defined(__APPLE__) || \ - defined(__sun__) || \ defined(__MVS__) || \ defined(_AIX) || \ defined(__EMSCRIPTEN__) @@ -1020,6 +1178,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK # endif +# if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(__no_thread_safety_analysis__) +# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((__no_thread_safety_analysis__)) +# else +# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS +# endif + # if defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) # if defined(__clang__) && __has_attribute(acquire_capability) // Work around the attribute handling in clang. When both __declspec and @@ -1038,7 +1202,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) # endif -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 # define _LIBCPP_CONSTINIT constinit # elif __has_attribute(__require_constant_initialization__) # define _LIBCPP_CONSTINIT __attribute__((__require_constant_initialization__)) @@ -1085,6 +1249,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_PREFERRED_NAME(x) # endif +# if __has_attribute(__no_sanitize__) +# define _LIBCPP_NO_SANITIZE(...) __attribute__((__no_sanitize__(__VA_ARGS__))) +# else +# define _LIBCPP_NO_SANITIZE(...) +# endif + // We often repeat things just for handling wide characters in the library. // When wide characters are disabled, it can be useful to have a quick way of // disabling it without having to resort to #if-#endif, which has a larger @@ -1118,8 +1288,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD # define _LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS # endif // _LIBCPP_ENABLE_CXX20_REMOVED_FEATURES -# define _LIBCPP_PUSH_MACROS _Pragma("push_macro(\"min\")") _Pragma("push_macro(\"max\")") -# define _LIBCPP_POP_MACROS _Pragma("pop_macro(\"min\")") _Pragma("pop_macro(\"max\")") +// clang-format off +# define _LIBCPP_PUSH_MACROS _Pragma("push_macro(\"min\")") _Pragma("push_macro(\"max\")") _Pragma("push_macro(\"refresh()\")") _Pragma("push_macro(\"move(int, int)\")") _Pragma("push_macro(\"erase()\")") +# define _LIBCPP_POP_MACROS _Pragma("pop_macro(\"min\")") _Pragma("pop_macro(\"max\")") _Pragma("pop_macro(\"refresh()\")") _Pragma("pop_macro(\"move(int, int)\")") _Pragma("pop_macro(\"erase()\")") +// clang-format on # ifndef _LIBCPP_NO_AUTO_LINK # if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_BUILDING_LIBRARY) @@ -1175,7 +1347,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // [[msvc::no_unique_address]], this should be preferred though. # define _LIBCPP_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] # elif __has_cpp_attribute(no_unique_address) -# define _LIBCPP_NO_UNIQUE_ADDRESS [[no_unique_address]] +# define _LIBCPP_NO_UNIQUE_ADDRESS [[__no_unique_address__]] # else # define _LIBCPP_NO_UNIQUE_ADDRESS /* nothing */ // Note that this can be replaced by #error as soon as clang-cl @@ -1223,12 +1395,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // functions are declared by the C library. # define _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8 // GNU libc 2.36 and newer declare c8rtomb() and mbrtoc8() in C++ modes if -// __cpp_char8_t is defined or if C2X extensions are enabled. Unfortunately, -// determining the latter depends on internal GNU libc details. If the -// __cpp_char8_t feature test macro is not defined, then a char8_t typedef -// will be declared as well. -# if defined(_LIBCPP_GLIBC_PREREQ) && defined(__GLIBC_USE) -# if _LIBCPP_GLIBC_PREREQ(2, 36) && (defined(__cpp_char8_t) || __GLIBC_USE(ISOC2X)) +// __cpp_char8_t is defined or if C2X extensions are enabled. Determining +// the latter depends on internal GNU libc details that are not appropriate +// to depend on here, so any declarations present when __cpp_char8_t is not +// defined are ignored. +# if defined(_LIBCPP_GLIBC_PREREQ) +# if _LIBCPP_GLIBC_PREREQ(2, 36) && defined(__cpp_char8_t) # undef _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8 # endif # endif @@ -1238,13 +1410,62 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD // macro is used to mark them as such, which suppresses the // '-Wctad-maybe-unsupported' compiler warning when CTAD is used in user code // with these classes. -#if _LIBCPP_STD_VER >= 17 -# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) \ - template <class ..._Tag> \ - _ClassName(typename _Tag::__allow_ctad...) -> _ClassName<_Tag...> -#else -# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "") -#endif +# if _LIBCPP_STD_VER >= 17 +# ifdef _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) \ + template <class... _Tag> \ + [[maybe_unused]] _ClassName(typename _Tag::__allow_ctad...)->_ClassName<_Tag...> +# else +# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(ClassName) \ + template <class... _Tag> \ + ClassName(typename _Tag::__allow_ctad...)->ClassName<_Tag...> +# endif +# else +# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "") +# endif + +// TODO(varconst): currently, there are bugs in Clang's intrinsics when handling Objective-C++ `id`, so don't use +// compiler intrinsics in the Objective-C++ mode. +# ifdef __OBJC__ +# define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS +# endif + +# define _PSTL_PRAGMA(x) _Pragma(#x) + +// Enable SIMD for compilers that support OpenMP 4.0 +# if (defined(_OPENMP) && _OPENMP >= 201307) + +# define _PSTL_UDR_PRESENT +# define _PSTL_PRAGMA_SIMD _PSTL_PRAGMA(omp simd) +# define _PSTL_PRAGMA_DECLARE_SIMD _PSTL_PRAGMA(omp declare simd) +# define _PSTL_PRAGMA_SIMD_REDUCTION(PRM) _PSTL_PRAGMA(omp simd reduction(PRM)) +# define _PSTL_PRAGMA_SIMD_SCAN(PRM) _PSTL_PRAGMA(omp simd reduction(inscan, PRM)) +# define _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(PRM) _PSTL_PRAGMA(omp scan inclusive(PRM)) +# define _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(PRM) _PSTL_PRAGMA(omp scan exclusive(PRM)) + +// Declaration of reduction functor, where +// NAME - the name of the functor +// OP - type of the callable object with the reduction operation +// omp_in - refers to the local partial result +// omp_out - refers to the final value of the combiner operator +// omp_priv - refers to the private copy of the initial value +// omp_orig - refers to the original variable to be reduced +# define _PSTL_PRAGMA_DECLARE_REDUCTION(NAME, OP) \ + _PSTL_PRAGMA(omp declare reduction(NAME:OP : omp_out(omp_in)) initializer(omp_priv = omp_orig)) + +# else // (defined(_OPENMP) && _OPENMP >= 201307) + +# define _PSTL_PRAGMA_SIMD +# define _PSTL_PRAGMA_DECLARE_SIMD +# define _PSTL_PRAGMA_SIMD_REDUCTION(PRM) +# define _PSTL_PRAGMA_SIMD_SCAN(PRM) +# define _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(PRM) +# define _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(PRM) +# define _PSTL_PRAGMA_DECLARE_REDUCTION(NAME, OP) + +# endif // (defined(_OPENMP) && _OPENMP >= 201307) + +# define _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED #endif // __cplusplus diff --git a/libcxx/include/__coroutine/coroutine_handle.h b/libcxx/include/__coroutine/coroutine_handle.h index 0a6cc1cab690..7a4eff745eb7 100644 --- a/libcxx/include/__coroutine/coroutine_handle.h +++ b/libcxx/include/__coroutine/coroutine_handle.h @@ -21,7 +21,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -33,7 +33,6 @@ template <> struct _LIBCPP_TEMPLATE_VIS coroutine_handle<void> { public: // [coroutine.handle.con], construct/reset - _LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle() noexcept = default; _LIBCPP_HIDE_FROM_ABI @@ -64,7 +63,7 @@ public: _LIBCPP_HIDE_FROM_ABI bool done() const { - _LIBCPP_ASSERT(__is_suspended(), "done() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "done() can be called only on suspended coroutines"); return __builtin_coro_done(__handle_); } @@ -74,19 +73,19 @@ public: _LIBCPP_HIDE_FROM_ABI void resume() const { - _LIBCPP_ASSERT(__is_suspended(), "resume() can be called only on suspended coroutines"); - _LIBCPP_ASSERT(!done(), "resume() has undefined behavior when the coroutine is done"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "resume() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(!done(), "resume() has undefined behavior when the coroutine is done"); __builtin_coro_resume(__handle_); } _LIBCPP_HIDE_FROM_ABI void destroy() const { - _LIBCPP_ASSERT(__is_suspended(), "destroy() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "destroy() can be called only on suspended coroutines"); __builtin_coro_destroy(__handle_); } private: - bool __is_suspended() const { + _LIBCPP_HIDE_FROM_ABI bool __is_suspended() const { // FIXME actually implement a check for if the coro is suspended. return __handle_ != nullptr; } @@ -108,7 +107,6 @@ template <class _Promise> struct _LIBCPP_TEMPLATE_VIS coroutine_handle { public: // [coroutine.handle.con], construct/reset - _LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle() noexcept = default; _LIBCPP_HIDE_FROM_ABI @@ -154,7 +152,7 @@ public: _LIBCPP_HIDE_FROM_ABI bool done() const { - _LIBCPP_ASSERT(__is_suspended(), "done() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "done() can be called only on suspended coroutines"); return __builtin_coro_done(__handle_); } @@ -164,14 +162,14 @@ public: _LIBCPP_HIDE_FROM_ABI void resume() const { - _LIBCPP_ASSERT(__is_suspended(), "resume() can be called only on suspended coroutines"); - _LIBCPP_ASSERT(!done(), "resume() has undefined behavior when the coroutine is done"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "resume() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(!done(), "resume() has undefined behavior when the coroutine is done"); __builtin_coro_resume(__handle_); } _LIBCPP_HIDE_FROM_ABI void destroy() const { - _LIBCPP_ASSERT(__is_suspended(), "destroy() can be called only on suspended coroutines"); + _LIBCPP_ASSERT_UNCATEGORIZED(__is_suspended(), "destroy() can be called only on suspended coroutines"); __builtin_coro_destroy(__handle_); } @@ -182,7 +180,7 @@ public: } private: - bool __is_suspended() const { + _LIBCPP_HIDE_FROM_ABI bool __is_suspended() const { // FIXME actually implement a check for if the coro is suspended. return __handle_ != nullptr; } @@ -198,6 +196,6 @@ struct hash<coroutine_handle<_Tp>> { _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER > 17 +#endif // __LIBCPP_STD_VER >= 20 #endif // _LIBCPP___COROUTINE_COROUTINE_HANDLE_H diff --git a/libcxx/include/__coroutine/coroutine_traits.h b/libcxx/include/__coroutine/coroutine_traits.h index d513075098c6..7122cc8ea8fb 100644 --- a/libcxx/include/__coroutine/coroutine_traits.h +++ b/libcxx/include/__coroutine/coroutine_traits.h @@ -16,7 +16,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -48,6 +48,6 @@ struct coroutine_traits _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER > 17 +#endif // __LIBCPP_STD_VER >= 20 #endif // _LIBCPP___COROUTINE_COROUTINE_TRAITS_H diff --git a/libcxx/include/__coroutine/noop_coroutine_handle.h b/libcxx/include/__coroutine/noop_coroutine_handle.h index 299304794ccb..9b7802d1e282 100644 --- a/libcxx/include/__coroutine/noop_coroutine_handle.h +++ b/libcxx/include/__coroutine/noop_coroutine_handle.h @@ -16,7 +16,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -107,6 +107,6 @@ noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle() _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER > 17 +#endif // __LIBCPP_STD_VER >= 20 #endif // _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H diff --git a/libcxx/include/__coroutine/trivial_awaitables.h b/libcxx/include/__coroutine/trivial_awaitables.h index bbbae7a47f23..0e4b08e377c0 100644 --- a/libcxx/include/__coroutine/trivial_awaitables.h +++ b/libcxx/include/__coroutine/trivial_awaitables.h @@ -16,7 +16,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_BEGIN_NAMESPACE_STD @@ -41,6 +41,6 @@ struct suspend_always { _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_STD_VER > 17 +#endif // __LIBCPP_STD_VER >= 20 #endif // __LIBCPP___COROUTINE_TRIVIAL_AWAITABLES_H diff --git a/libcxx/include/__debug b/libcxx/include/__debug deleted file mode 100644 index 140cc9142a82..000000000000 --- a/libcxx/include/__debug +++ /dev/null @@ -1,266 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___DEBUG -#define _LIBCPP___DEBUG - -#include <__assert> -#include <__config> -#include <__type_traits/is_constant_evaluated.h> -#include <cstddef> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY) -# define _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY -#endif - -#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING) -# define _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING -#endif - -#ifdef _LIBCPP_ENABLE_DEBUG_MODE -# define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(::std::__libcpp_is_constant_evaluated() || (x), m) -#else -# define _LIBCPP_DEBUG_ASSERT(x, m) ((void)0) -#endif - -#if defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY) - -_LIBCPP_BEGIN_NAMESPACE_STD - -struct _LIBCPP_TYPE_VIS __c_node; - -struct _LIBCPP_TYPE_VIS __i_node -{ - void* __i_; - __i_node* __next_; - __c_node* __c_; - - __i_node(const __i_node&) = delete; - __i_node& operator=(const __i_node&) = delete; - - _LIBCPP_INLINE_VISIBILITY - __i_node(void* __i, __i_node* __next, __c_node* __c) - : __i_(__i), __next_(__next), __c_(__c) {} - ~__i_node(); -}; - -struct _LIBCPP_TYPE_VIS __c_node -{ - void* __c_; - __c_node* __next_; - __i_node** beg_; - __i_node** end_; - __i_node** cap_; - - __c_node(const __c_node&) = delete; - __c_node& operator=(const __c_node&) = delete; - - _LIBCPP_INLINE_VISIBILITY - explicit __c_node(void* __c, __c_node* __next) - : __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {} - virtual ~__c_node(); - - virtual bool __dereferenceable(const void*) const = 0; - virtual bool __decrementable(const void*) const = 0; - virtual bool __addable(const void*, ptrdiff_t) const = 0; - virtual bool __subscriptable(const void*, ptrdiff_t) const = 0; - - void __add(__i_node* __i); - _LIBCPP_HIDDEN void __remove(__i_node* __i); -}; - -template <class _Cont> -struct _C_node - : public __c_node -{ - explicit _C_node(void* __c, __c_node* __n) - : __c_node(__c, __n) {} - - bool __dereferenceable(const void*) const override; - bool __decrementable(const void*) const override; - bool __addable(const void*, ptrdiff_t) const override; - bool __subscriptable(const void*, ptrdiff_t) const override; -}; - -template <class _Cont> -inline bool -_C_node<_Cont>::__dereferenceable(const void* __i) const -{ - typedef typename _Cont::const_iterator iterator; - const iterator* __j = static_cast<const iterator*>(__i); - _Cont* _Cp = static_cast<_Cont*>(__c_); - return _Cp->__dereferenceable(__j); -} - -template <class _Cont> -inline bool -_C_node<_Cont>::__decrementable(const void* __i) const -{ - typedef typename _Cont::const_iterator iterator; - const iterator* __j = static_cast<const iterator*>(__i); - _Cont* _Cp = static_cast<_Cont*>(__c_); - return _Cp->__decrementable(__j); -} - -template <class _Cont> -inline bool -_C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const -{ - typedef typename _Cont::const_iterator iterator; - const iterator* __j = static_cast<const iterator*>(__i); - _Cont* _Cp = static_cast<_Cont*>(__c_); - return _Cp->__addable(__j, __n); -} - -template <class _Cont> -inline bool -_C_node<_Cont>::__subscriptable(const void* __i, ptrdiff_t __n) const -{ - typedef typename _Cont::const_iterator iterator; - const iterator* __j = static_cast<const iterator*>(__i); - _Cont* _Cp = static_cast<_Cont*>(__c_); - return _Cp->__subscriptable(__j, __n); -} - -class _LIBCPP_TYPE_VIS __libcpp_db -{ - __c_node** __cbeg_; - __c_node** __cend_; - size_t __csz_; - __i_node** __ibeg_; - __i_node** __iend_; - size_t __isz_; - - explicit __libcpp_db(); -public: - __libcpp_db(const __libcpp_db&) = delete; - __libcpp_db& operator=(const __libcpp_db&) = delete; - - ~__libcpp_db(); - - class __db_c_iterator; - class __db_c_const_iterator; - class __db_i_iterator; - class __db_i_const_iterator; - - __db_c_const_iterator __c_end() const; - __db_i_const_iterator __i_end() const; - - typedef __c_node*(_InsertConstruct)(void*, void*, __c_node*); - - template <class _Cont> - _LIBCPP_INLINE_VISIBILITY static __c_node* __create_C_node(void *__mem, void *__c, __c_node *__next) { - return ::new (__mem) _C_node<_Cont>(__c, __next); - } - - template <class _Cont> - _LIBCPP_INLINE_VISIBILITY - void __insert_c(_Cont* __c) - { - __insert_c(static_cast<void*>(__c), &__create_C_node<_Cont>); - } - - void __insert_i(void* __i); - void __insert_c(void* __c, _InsertConstruct* __fn); - void __erase_c(void* __c); - - void __insert_ic(void* __i, const void* __c); - void __iterator_copy(void* __i, const void* __i0); - void __erase_i(void* __i); - - void* __find_c_from_i(void* __i) const; - void __invalidate_all(void* __c); - __c_node* __find_c_and_lock(void* __c) const; - __c_node* __find_c(void* __c) const; - void unlock() const; - - void swap(void* __c1, void* __c2); - - - bool __dereferenceable(const void* __i) const; - bool __decrementable(const void* __i) const; - bool __addable(const void* __i, ptrdiff_t __n) const; - bool __subscriptable(const void* __i, ptrdiff_t __n) const; - bool __less_than_comparable(const void* __i, const void* __j) const; -private: - _LIBCPP_HIDDEN - __i_node* __insert_iterator(void* __i); - _LIBCPP_HIDDEN - __i_node* __find_iterator(const void* __i) const; - - friend _LIBCPP_FUNC_VIS __libcpp_db* __get_db(); -}; - -_LIBCPP_FUNC_VIS __libcpp_db* __get_db(); -_LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db(); - -_LIBCPP_END_NAMESPACE_STD - -#endif // defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY) - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_insert_c(_Tp* __c) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__insert_c(__c); -#else - (void)(__c); -#endif -} - -template <class _Tp> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_insert_i(_Tp* __i) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__insert_i(__i); -#else - (void)(__i); -#endif -} - -template <class _Tp> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_erase_c(_Tp* __c) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__erase_c(__c); -#else - (void)(__c); -#endif -} - -template <class _Tp> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_swap(_Tp* __lhs, _Tp* __rhs) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->swap(__lhs, __rhs); -#else - (void)(__lhs); - (void)(__rhs); -#endif -} - -template <class _Tp> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_invalidate_all(_Tp* __c) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__invalidate_all(__c); -#else - (void)(__c); -#endif -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___DEBUG diff --git a/libcxx/include/__debug_utils/strict_weak_ordering_check.h b/libcxx/include/__debug_utils/strict_weak_ordering_check.h new file mode 100644 index 000000000000..99200ad65eac --- /dev/null +++ b/libcxx/include/__debug_utils/strict_weak_ordering_check.h @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LIBCXX_DEBUG_STRICT_WEAK_ORDERING_CHECK +#define _LIBCPP___LIBCXX_DEBUG_STRICT_WEAK_ORDERING_CHECK + +#include <__config> + +#include <__algorithm/comp_ref_type.h> +#include <__algorithm/is_sorted.h> +#include <__assert> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_constant_evaluated.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _RandomAccessIterator, class _Comp> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void +__check_strict_weak_ordering_sorted(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) { +#ifdef _LIBCPP_DEBUG_STRICT_WEAK_ORDERING_CHECK + using __diff_t = __iter_diff_t<_RandomAccessIterator>; + using _Comp_ref = __comp_ref_type<_Comp>; + if (!__libcpp_is_constant_evaluated()) { + // Check if the range is actually sorted. + _LIBCPP_ASSERT_UNCATEGORIZED( + (std::is_sorted<_RandomAccessIterator, _Comp_ref>(__first, __last, _Comp_ref(__comp))), + "The range is not sorted after the sort, your comparator is not a valid strict-weak ordering"); + // Limit the number of elements we need to check. + __diff_t __size = __last - __first > __diff_t(100) ? __diff_t(100) : __last - __first; + __diff_t __p = 0; + while (__p < __size) { + __diff_t __q = __p + __diff_t(1); + // Find first element that is greater than *(__first+__p). + while (__q < __size && !__comp(*(__first + __p), *(__first + __q))) { + ++__q; + } + // Check that the elements from __p to __q are equal between each other. + for (__diff_t __b = __p; __b < __q; ++__b) { + for (__diff_t __a = __p; __a <= __b; ++__a) { + _LIBCPP_ASSERT_UNCATEGORIZED( + !__comp(*(__first + __a), *(__first + __b)), "Your comparator is not a valid strict-weak ordering"); + _LIBCPP_ASSERT_UNCATEGORIZED( + !__comp(*(__first + __b), *(__first + __a)), "Your comparator is not a valid strict-weak ordering"); + } + } + // Check that elements between __p and __q are less than between __q and __size. + for (__diff_t __a = __p; __a < __q; ++__a) { + for (__diff_t __b = __q; __b < __size; ++__b) { + _LIBCPP_ASSERT_UNCATEGORIZED( + __comp(*(__first + __a), *(__first + __b)), "Your comparator is not a valid strict-weak ordering"); + _LIBCPP_ASSERT_UNCATEGORIZED( + !__comp(*(__first + __b), *(__first + __a)), "Your comparator is not a valid strict-weak ordering"); + } + } + // Skip these equal elements. + __p = __q; + } + } +#else + (void)__first; + (void)__last; + (void)__comp; +#endif +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___LIBCXX_DEBUG_STRICT_WEAK_ORDERING_CHECK diff --git a/libcxx/include/__exception/exception.h b/libcxx/include/__exception/exception.h new file mode 100644 index 000000000000..3db0126da296 --- /dev/null +++ b/libcxx/include/__exception/exception.h @@ -0,0 +1,91 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___EXCEPTION_EXCEPTION_H +#define _LIBCPP___EXCEPTION_EXCEPTION_H + +#include <__config> + +// <vcruntime_exception.h> defines its own std::exception and std::bad_exception types, +// which we use in order to be ABI-compatible with other STLs on Windows. +#if defined(_LIBCPP_ABI_VCRUNTIME) +# include <vcruntime_exception.h> +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +namespace std { // purposefully not using versioning namespace + +#if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0) +// The std::exception class was already included above, but we're explicit about this condition here for clarity. + +#elif defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0 +// However, <vcruntime_exception.h> does not define std::exception and std::bad_exception +// when _HAS_EXCEPTIONS == 0. +// +// Since libc++ still wants to provide the std::exception hierarchy even when _HAS_EXCEPTIONS == 0 +// (after all those are simply types like any other), we define an ABI-compatible version +// of the VCRuntime std::exception and std::bad_exception types in that mode. + +struct __std_exception_data { + char const* _What; + bool _DoFree; +}; + +class exception { // base of all library exceptions +public: + exception() _NOEXCEPT : __data_() {} + + explicit exception(char const* __message) _NOEXCEPT : __data_() { + __data_._What = __message; + __data_._DoFree = true; + } + + exception(exception const&) _NOEXCEPT {} + + exception& operator=(exception const&) _NOEXCEPT { return *this; } + + virtual ~exception() _NOEXCEPT {} + + virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; } + +private: + __std_exception_data __data_; +}; + +class bad_exception : public exception { +public: + bad_exception() _NOEXCEPT : exception("bad exception") {} +}; + +#else // !defined(_LIBCPP_ABI_VCRUNTIME) +// On all other platforms, we define our own std::exception and std::bad_exception types +// regardless of whether exceptions are turned on as a language feature. + +class _LIBCPP_EXPORTED_FROM_ABI exception { +public: + _LIBCPP_HIDE_FROM_ABI exception() _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI exception(const exception&) _NOEXCEPT = default; + + virtual ~exception() _NOEXCEPT; + virtual const char* what() const _NOEXCEPT; +}; + +class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception { +public: + _LIBCPP_HIDE_FROM_ABI bad_exception() _NOEXCEPT {} + ~bad_exception() _NOEXCEPT override; + const char* what() const _NOEXCEPT override; +}; +#endif // !_LIBCPP_ABI_VCRUNTIME + +} // namespace std + +#endif // _LIBCPP___EXCEPTION_EXCEPTION_H diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h new file mode 100644 index 000000000000..970d8196724b --- /dev/null +++ b/libcxx/include/__exception/exception_ptr.h @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___EXCEPTION_EXCEPTION_PTR_H +#define _LIBCPP___EXCEPTION_EXCEPTION_PTR_H + +#include <__config> +#include <__exception/operations.h> +#include <__memory/addressof.h> +#include <cstddef> +#include <cstdlib> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +namespace std { // purposefully not using versioning namespace + +#ifndef _LIBCPP_ABI_MICROSOFT + +class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { + void* __ptr_; + +public: + _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {} + _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} + + exception_ptr(const exception_ptr&) _NOEXCEPT; + exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; + ~exception_ptr() _NOEXCEPT; + + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; } + + friend _LIBCPP_HIDE_FROM_ABI bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { + return __x.__ptr_ == __y.__ptr_; + } + + friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { + return !(__x == __y); + } + + friend _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; + friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); +}; + +template <class _Ep> +_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { + throw __e; + } catch (...) { + return current_exception(); + } +# else + ((void)__e); + std::abort(); +# endif +} + +#else // _LIBCPP_ABI_MICROSOFT + +class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { + _LIBCPP_DIAGNOSTIC_PUSH + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field") + void* __ptr1_; + void* __ptr2_; + _LIBCPP_DIAGNOSTIC_POP + +public: + exception_ptr() _NOEXCEPT; + exception_ptr(nullptr_t) _NOEXCEPT; + exception_ptr(const exception_ptr& __other) _NOEXCEPT; + exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; + exception_ptr& operator=(nullptr_t) _NOEXCEPT; + ~exception_ptr() _NOEXCEPT; + explicit operator bool() const _NOEXCEPT; +}; + +_LIBCPP_EXPORTED_FROM_ABI bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; + +inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { + return !(__x == __y); +} + +_LIBCPP_EXPORTED_FROM_ABI void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; + +_LIBCPP_EXPORTED_FROM_ABI exception_ptr __copy_exception_ptr(void* __except, const void* __ptr); +_LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); + +// This is a built-in template function which automagically extracts the required +// information. +template <class _E> +void* __GetExceptionInfo(_E); + +template <class _Ep> +_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { + return __copy_exception_ptr(std::addressof(__e), __GetExceptionInfo(__e)); +} + +#endif // _LIBCPP_ABI_MICROSOFT +} // namespace std + +#endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H diff --git a/libcxx/include/__exception/nested_exception.h b/libcxx/include/__exception/nested_exception.h new file mode 100644 index 000000000000..1136c9274888 --- /dev/null +++ b/libcxx/include/__exception/nested_exception.h @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H +#define _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H + +#include <__config> +#include <__exception/exception_ptr.h> +#include <__memory/addressof.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_base_of.h> +#include <__type_traits/is_class.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_final.h> +#include <__type_traits/is_polymorphic.h> +#include <__utility/forward.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +namespace std { // purposefully not using versioning namespace + +class _LIBCPP_EXPORTED_FROM_ABI nested_exception { + exception_ptr __ptr_; + +public: + nested_exception() _NOEXCEPT; + // nested_exception(const nested_exception&) noexcept = default; + // nested_exception& operator=(const nested_exception&) noexcept = default; + virtual ~nested_exception() _NOEXCEPT; + + // access functions + _LIBCPP_NORETURN void rethrow_nested() const; + _LIBCPP_HIDE_FROM_ABI exception_ptr nested_ptr() const _NOEXCEPT { return __ptr_; } +}; + +template <class _Tp> +struct __nested : public _Tp, public nested_exception { + _LIBCPP_HIDE_FROM_ABI explicit __nested(const _Tp& __t) : _Tp(__t) {} +}; + +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS +template <class _Tp, class _Up, bool> +struct __throw_with_nested; + +template <class _Tp, class _Up> +struct __throw_with_nested<_Tp, _Up, true> { + _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void __do_throw(_Tp&& __t) { + throw __nested<_Up>(std::forward<_Tp>(__t)); + } +}; + +template <class _Tp, class _Up> +struct __throw_with_nested<_Tp, _Up, false> { + _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void __do_throw(_Tp&& __t) { throw std::forward<_Tp>(__t); } +}; +#endif + +template <class _Tp> +_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void throw_with_nested(_Tp&& __t) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + using _Up = __decay_t<_Tp>; + static_assert(is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible"); + __throw_with_nested<_Tp, + _Up, + is_class<_Up>::value && !is_base_of<nested_exception, _Up>::value && + !__libcpp_is_final<_Up>::value>::__do_throw(std::forward<_Tp>(__t)); +#else + ((void)__t); + // FIXME: Make this abort +#endif +} + +template <class _From, class _To> +struct __can_dynamic_cast + : _BoolConstant< is_polymorphic<_From>::value && + (!is_base_of<_To, _From>::value || is_convertible<const _From*, const _To*>::value)> {}; + +template <class _Ep> +inline _LIBCPP_HIDE_FROM_ABI void +rethrow_if_nested(const _Ep& __e, __enable_if_t< __can_dynamic_cast<_Ep, nested_exception>::value>* = 0) { + const nested_exception* __nep = dynamic_cast<const nested_exception*>(std::addressof(__e)); + if (__nep) + __nep->rethrow_nested(); +} + +template <class _Ep> +inline _LIBCPP_HIDE_FROM_ABI void +rethrow_if_nested(const _Ep&, __enable_if_t<!__can_dynamic_cast<_Ep, nested_exception>::value>* = 0) {} + +} // namespace std + +#endif // _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H diff --git a/libcxx/include/__exception/operations.h b/libcxx/include/__exception/operations.h new file mode 100644 index 000000000000..78e7c7a5d0b5 --- /dev/null +++ b/libcxx/include/__exception/operations.h @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___EXCEPTION_OPERATIONS_H +#define _LIBCPP___EXCEPTION_OPERATIONS_H + +#include <__availability> +#include <__config> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +namespace std { // purposefully not using versioning namespace +#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) || \ + defined(_LIBCPP_BUILDING_LIBRARY) +using unexpected_handler = void (*)(); +_LIBCPP_EXPORTED_FROM_ABI unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI unexpected_handler get_unexpected() _NOEXCEPT; +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void unexpected(); +#endif + +using terminate_handler = void (*)(); +_LIBCPP_EXPORTED_FROM_ABI terminate_handler set_terminate(terminate_handler) _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI terminate_handler get_terminate() _NOEXCEPT; + +_LIBCPP_EXPORTED_FROM_ABI bool uncaught_exception() _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT; + +class _LIBCPP_EXPORTED_FROM_ABI exception_ptr; + +_LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); +} // namespace std + +#endif // _LIBCPP___EXCEPTION_OPERATIONS_H diff --git a/libcxx/include/__exception/terminate.h b/libcxx/include/__exception/terminate.h new file mode 100644 index 000000000000..e672471dc526 --- /dev/null +++ b/libcxx/include/__exception/terminate.h @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___EXCEPTION_TERMINATE_H +#define _LIBCPP___EXCEPTION_TERMINATE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +namespace std { // purposefully not using versioning namespace +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void terminate() _NOEXCEPT; +} // namespace std + +#endif // _LIBCPP___EXCEPTION_TERMINATE_H diff --git a/libcxx/include/__expected/bad_expected_access.h b/libcxx/include/__expected/bad_expected_access.h index 361eab4b6018..27f01d9350ee 100644 --- a/libcxx/include/__expected/bad_expected_access.h +++ b/libcxx/include/__expected/bad_expected_access.h @@ -10,14 +10,16 @@ #define _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H #include <__config> +#include <__exception/exception.h> #include <__utility/move.h> -#include <exception> - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + #if _LIBCPP_STD_VER >= 23 _LIBCPP_BEGIN_NAMESPACE_STD @@ -33,14 +35,14 @@ protected: _LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) = default; _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) = default; _LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) = default; - ~bad_expected_access() override = default; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_expected_access() override = default; public: // The way this has been designed (by using a class template below) means that we'll already // have a profusion of these vtables in TUs, and the dynamic linker will already have a bunch // of work to do. So it is not worth hiding the <void> specialization in the dylib, given that // it adds deployment target restrictions. - const char* what() const noexcept override { return "bad access to std::expected"; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const char* what() const noexcept override { return "bad access to std::expected"; } }; template <class _Err> @@ -61,4 +63,6 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 +_LIBCPP_POP_MACROS + #endif // _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h index e1f590c65efe..7d57aa4db5f9 100644 --- a/libcxx/include/__expected/expected.h +++ b/libcxx/include/__expected/expected.h @@ -14,10 +14,12 @@ #include <__expected/bad_expected_access.h> #include <__expected/unexpect.h> #include <__expected/unexpected.h> +#include <__functional/invoke.h> #include <__memory/addressof.h> #include <__memory/construct_at.h> #include <__type_traits/conjunction.h> #include <__type_traits/disjunction.h> +#include <__type_traits/integral_constant.h> #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> @@ -44,36 +46,48 @@ #include <__type_traits/negation.h> #include <__type_traits/remove_cv.h> #include <__type_traits/remove_cvref.h> +#include <__utility/as_const.h> #include <__utility/exception_guard.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> #include <__utility/swap.h> -#include <cstdlib> // for std::abort +#include <__verbose_abort> #include <initializer_list> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + #if _LIBCPP_STD_VER >= 23 _LIBCPP_BEGIN_NAMESPACE_STD -namespace __expected { +template <class _Tp, class _Err> +class expected; + +template <class _Tp> +struct __is_std_expected : false_type {}; + +template <class _Tp, class _Err> +struct __is_std_expected<expected<_Tp, _Err>> : true_type {}; + +struct __expected_construct_in_place_from_invoke_tag {}; +struct __expected_construct_unexpected_from_invoke_tag {}; template <class _Err, class _Arg> _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) { -# ifndef _LIBCPP_NO_EXCEPTIONS +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_expected_access<_Err>(std::forward<_Arg>(__arg)); # else (void)__arg; - std::abort(); + _LIBCPP_VERBOSE_ABORT("bad_expected_access was thrown in -fno-exceptions mode"); # endif } -} // namespace __expected - template <class _Tp, class _Err> class expected { static_assert( @@ -166,6 +180,15 @@ private: _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>, _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>> >; + template <class _Func, class... _Args> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( + std::__expected_construct_in_place_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) + : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(true) {} + + template <class _Func, class... _Args> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( + std::__expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) + : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {} public: template <class _Up, class _OtherErr> @@ -292,7 +315,8 @@ private: "be reverted to the previous state in case an exception is thrown during the assignment."); _T2 __tmp(std::move(__oldval)); std::destroy_at(std::addressof(__oldval)); - __exception_guard __trans([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); }); + auto __trans = + std::__make_exception_guard([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); }); std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...); __trans.__complete(); } @@ -451,7 +475,7 @@ public: if constexpr (is_nothrow_move_constructible_v<_Err>) { _Err __tmp(std::move(__with_err.__union_.__unex_)); std::destroy_at(std::addressof(__with_err.__union_.__unex_)); - __exception_guard __trans([&] { + auto __trans = std::__make_exception_guard([&] { std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp)); }); std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_)); @@ -464,7 +488,7 @@ public: "that it can be reverted to the previous state in case an exception is thrown during swap."); _Tp __tmp(std::move(__with_val.__union_.__val_)); std::destroy_at(std::addressof(__with_val.__union_.__val_)); - __exception_guard __trans([&] { + auto __trans = std::__make_exception_guard([&] { std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp)); }); std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_)); @@ -502,32 +526,32 @@ public: // [expected.object.obs], observers _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value"); return std::addressof(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value"); return std::addressof(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return std::move(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); return std::move(__union_.__val_); } @@ -536,50 +560,56 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { + static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); + std::__throw_bad_expected_access<_Err>(std::as_const(error())); } return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { + static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); + std::__throw_bad_expected_access<_Err>(std::as_const(error())); } return __union_.__val_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { + static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, + "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); + std::__throw_bad_expected_access<_Err>(std::move(error())); } return std::move(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { + static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, + "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); + std::__throw_bad_expected_access<_Err>(std::move(error())); } return std::move(__union_.__val_); } _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } @@ -597,6 +627,245 @@ public: return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v)); } + template <class _Up = _Err> + _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { + static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); + static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); + if (has_value()) + return std::forward<_Up>(__error); + return error(); + } + + template <class _Up = _Err> + _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { + static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); + static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); + if (has_value()) + return std::forward<_Up>(__error); + return std::move(error()); + } + + // [expected.void.monadic], monadic + template <class _Func> + requires is_constructible_v<_Err, _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { + using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>; + static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Up::error_type, _Err>, + "The result of f(value()) must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f), value()); + } + return _Up(unexpect, error()); + } + + template <class _Func> + requires is_constructible_v<_Err, const _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { + using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&>>; + static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Up::error_type, _Err>, + "The result of f(value()) must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f), value()); + } + return _Up(unexpect, error()); + } + + template <class _Func> + requires is_constructible_v<_Err, _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { + using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&&>>; + static_assert( + __is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Up::error_type, _Err>, + "The result of f(std::move(value())) must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f), std::move(value())); + } + return _Up(unexpect, std::move(error())); + } + + template <class _Func> + requires is_constructible_v<_Err, const _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { + using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&&>>; + static_assert( + __is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Up::error_type, _Err>, + "The result of f(std::move(value())) must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f), std::move(value())); + } + return _Up(unexpect, std::move(error())); + } + + template <class _Func> + requires is_constructible_v<_Tp, _Tp&> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { + using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>; + static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Gp::value_type, _Tp>, + "The result of f(error()) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(in_place, value()); + } + return std::invoke(std::forward<_Func>(__f), error()); + } + + template <class _Func> + requires is_constructible_v<_Tp, const _Tp&> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { + using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>; + static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Gp::value_type, _Tp>, + "The result of f(error()) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(in_place, value()); + } + return std::invoke(std::forward<_Func>(__f), error()); + } + + template <class _Func> + requires is_constructible_v<_Tp, _Tp&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { + using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>; + static_assert( + __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Gp::value_type, _Tp>, + "The result of f(std::move(error())) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(in_place, std::move(value())); + } + return std::invoke(std::forward<_Func>(__f), std::move(error())); + } + + template <class _Func> + requires is_constructible_v<_Tp, const _Tp&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { + using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>; + static_assert( + __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Gp::value_type, _Tp>, + "The result of f(std::move(error())) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(in_place, std::move(value())); + } + return std::invoke(std::forward<_Func>(__f), std::move(error())); + } + + template <class _Func> + requires is_constructible_v<_Err, _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { + using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, error()); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), value()); + } else { + std::invoke(std::forward<_Func>(__f), value()); + return expected<_Up, _Err>(); + } + } + + template <class _Func> + requires is_constructible_v<_Err, const _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { + using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, error()); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), value()); + } else { + std::invoke(std::forward<_Func>(__f), value()); + return expected<_Up, _Err>(); + } + } + + template <class _Func> + requires is_constructible_v<_Err, _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { + using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, std::move(error())); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>( + __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); + } else { + std::invoke(std::forward<_Func>(__f), std::move(value())); + return expected<_Up, _Err>(); + } + } + + template <class _Func> + requires is_constructible_v<_Err, const _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { + using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, std::move(error())); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>( + __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(value())); + } else { + std::invoke(std::forward<_Func>(__f), std::move(value())); + return expected<_Up, _Err>(); + } + } + + template <class _Func> + requires is_constructible_v<_Tp, _Tp&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { + using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(error()) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(in_place, value()); + } + return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); + } + + template <class _Func> + requires is_constructible_v<_Tp, const _Tp&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { + using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(error()) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(in_place, value()); + } + return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); + } + + template <class _Func> + requires is_constructible_v<_Tp, _Tp&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { + using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(std::move(error())) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(in_place, std::move(value())); + } + return expected<_Tp, _Gp>( + __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); + } + + template <class _Func> + requires is_constructible_v<_Tp, const _Tp&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { + using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(std::move(error())) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(in_place, std::move(value())); + } + return expected<_Tp, _Gp>( + __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); + } + // [expected.object.eq], equality operators template <class _T2, class _E2> requires(!is_void_v<_T2>) @@ -624,24 +893,66 @@ public: private: struct __empty_t {}; - // use named union because [[no_unique_address]] cannot be applied to an unnamed union - _LIBCPP_NO_UNIQUE_ADDRESS union __union_t { + + template <class _ValueType, class _ErrorType> + union __union_t { + _LIBCPP_HIDE_FROM_ABI constexpr __union_t() {} + + template <class _Func, class... _Args> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + + template <class _Func, class... _Args> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() + requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>) + = default; + + // the expected's destructor handles this + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} + + _ValueType __val_; + _ErrorType __unex_; + }; + + // use named union because [[no_unique_address]] cannot be applied to an unnamed union, + // also guaranteed elision into a potentially-overlapping subobject is unsettled (and + // it's not clear that it's implementable, given that the function is allowed to clobber + // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. + template <class _ValueType, class _ErrorType> + requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>) + union __union_t<_ValueType, _ErrorType> { _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} + template <class _Func, class... _Args> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + + template <class _Func, class... _Args> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() - requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) + requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>) = default; // the expected's destructor handles this _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() - requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) + requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>) {} _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; - _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; - _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_; - } __union_; + _LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_; + _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_; + }; + _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_; bool __has_val_; }; @@ -761,6 +1072,19 @@ public: std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...); } +private: + template <class _Func> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(__expected_construct_in_place_from_invoke_tag, _Func&& __f) + : __has_val_(true) { + std::invoke(std::forward<_Func>(__f)); + } + + template <class _Func, class... _Args> + _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( + __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) + : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {} + +public: // [expected.void.dtor], destructor _LIBCPP_HIDE_FROM_ABI constexpr ~expected() @@ -893,41 +1217,270 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; } _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept { - _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value"); } _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(__union_.__unex_); + std::__throw_bad_expected_access<_Err>(__union_.__unex_); } } _LIBCPP_HIDE_FROM_ABI constexpr void value() && { if (!__has_val_) { - __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); + std::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); } } _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return __union_.__unex_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { - _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error"); return std::move(__union_.__unex_); } + template <class _Up = _Err> + _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { + static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); + static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); + if (has_value()) { + return std::forward<_Up>(__error); + } + return error(); + } + + template <class _Up = _Err> + _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { + static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); + static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); + if (has_value()) { + return std::forward<_Up>(__error); + } + return std::move(error()); + } + + // [expected.void.monadic], monadic + template <class _Func> + requires is_constructible_v<_Err, _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { + using _Up = remove_cvref_t<invoke_result_t<_Func>>; + static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); + static_assert( + is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f)); + } + return _Up(unexpect, error()); + } + + template <class _Func> + requires is_constructible_v<_Err, const _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { + using _Up = remove_cvref_t<invoke_result_t<_Func>>; + static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); + static_assert( + is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f)); + } + return _Up(unexpect, error()); + } + + template <class _Func> + requires is_constructible_v<_Err, _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { + using _Up = remove_cvref_t<invoke_result_t<_Func>>; + static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); + static_assert( + is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f)); + } + return _Up(unexpect, std::move(error())); + } + + template <class _Func> + requires is_constructible_v<_Err, const _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { + using _Up = remove_cvref_t<invoke_result_t<_Func>>; + static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); + static_assert( + is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); + if (has_value()) { + return std::invoke(std::forward<_Func>(__f)); + } + return _Up(unexpect, std::move(error())); + } + + template <class _Func> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { + using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>; + static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Gp::value_type, _Tp>, + "The result of f(error()) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(); + } + return std::invoke(std::forward<_Func>(__f), error()); + } + + template <class _Func> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { + using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>; + static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Gp::value_type, _Tp>, + "The result of f(error()) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(); + } + return std::invoke(std::forward<_Func>(__f), error()); + } + + template <class _Func> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { + using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>; + static_assert(__is_std_expected<_Gp>::value, + "The result of f(std::move(error())) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Gp::value_type, _Tp>, + "The result of f(std::move(error())) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(); + } + return std::invoke(std::forward<_Func>(__f), std::move(error())); + } + + template <class _Func> + _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { + using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>; + static_assert(__is_std_expected<_Gp>::value, + "The result of f(std::move(error())) must be a specialization of std::expected"); + static_assert(is_same_v<typename _Gp::value_type, _Tp>, + "The result of f(std::move(error())) must have the same value_type as this expected"); + if (has_value()) { + return _Gp(); + } + return std::invoke(std::forward<_Func>(__f), std::move(error())); + } + + template <class _Func> + requires is_constructible_v<_Err, _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { + using _Up = remove_cv_t<invoke_result_t<_Func>>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, error()); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); + } else { + std::invoke(std::forward<_Func>(__f)); + return expected<_Up, _Err>(); + } + } + + template <class _Func> + requires is_constructible_v<_Err, const _Err&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { + using _Up = remove_cv_t<invoke_result_t<_Func>>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, error()); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); + } else { + std::invoke(std::forward<_Func>(__f)); + return expected<_Up, _Err>(); + } + } + + template <class _Func> + requires is_constructible_v<_Err, _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { + using _Up = remove_cv_t<invoke_result_t<_Func>>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, std::move(error())); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); + } else { + std::invoke(std::forward<_Func>(__f)); + return expected<_Up, _Err>(); + } + } + + template <class _Func> + requires is_constructible_v<_Err, const _Err&&> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { + using _Up = remove_cv_t<invoke_result_t<_Func>>; + if (!has_value()) { + return expected<_Up, _Err>(unexpect, std::move(error())); + } + if constexpr (!is_void_v<_Up>) { + return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); + } else { + std::invoke(std::forward<_Func>(__f)); + return expected<_Up, _Err>(); + } + } + + template <class _Func> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { + using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(error()) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(); + } + return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); + } + + template <class _Func> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { + using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(error()) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(); + } + return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); + } + + template <class _Func> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { + using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(std::move(error())) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(); + } + return expected<_Tp, _Gp>( + __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); + } + + template <class _Func> + _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { + using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>; + static_assert(__valid_std_unexpected<_Gp>::value, + "The result of f(std::move(error())) must be a valid template argument for unexpected"); + if (has_value()) { + return expected<_Tp, _Gp>(); + } + return expected<_Tp, _Gp>( + __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); + } + // [expected.void.eq], equality operators template <class _T2, class _E2> requires is_void_v<_T2> @@ -946,23 +1499,55 @@ public: private: struct __empty_t {}; - // use named union because [[no_unique_address]] cannot be applied to an unnamed union - _LIBCPP_NO_UNIQUE_ADDRESS union __union_t { + + template <class _ErrorType> + union __union_t { _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} + template <class _Func, class... _Args> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() - requires(is_trivially_destructible_v<_Err>) + requires(is_trivially_destructible_v<_ErrorType>) = default; // the expected's destructor handles this + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} + + __empty_t __empty_; + _ErrorType __unex_; + }; + + // use named union because [[no_unique_address]] cannot be applied to an unnamed union, + // also guaranteed elision into a potentially-overlapping subobject is unsettled (and + // it's not clear that it's implementable, given that the function is allowed to clobber + // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. + template <class _ErrorType> + requires is_trivially_move_constructible_v<_ErrorType> + union __union_t<_ErrorType> { + _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {} + + template <class _Func, class... _Args> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( + __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) + : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() - requires(!is_trivially_destructible_v<_Err>) + requires(is_trivially_destructible_v<_ErrorType>) + = default; + + // the expected's destructor handles this + _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() + requires(!is_trivially_destructible_v<_ErrorType>) {} _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; - _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_; - } __union_; + _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_; + }; + _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_; bool __has_val_; }; @@ -970,4 +1555,6 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 +_LIBCPP_POP_MACROS + #endif // _LIBCPP___EXPECTED_EXPECTED_H diff --git a/libcxx/include/__expected/unexpect.h b/libcxx/include/__expected/unexpect.h index 20bafc1107c0..df52787d36fa 100644 --- a/libcxx/include/__expected/unexpect.h +++ b/libcxx/include/__expected/unexpect.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD struct unexpect_t { - _LIBCPP_HIDE_FROM_ABI explicit unexpect_t() = default; + explicit unexpect_t() = default; }; inline constexpr unexpect_t unexpect{}; diff --git a/libcxx/include/__expected/unexpected.h b/libcxx/include/__expected/unexpected.h index 075963a84ded..c7fe3c52e431 100644 --- a/libcxx/include/__expected/unexpected.h +++ b/libcxx/include/__expected/unexpected.h @@ -31,6 +31,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + #if _LIBCPP_STD_VER >= 23 _LIBCPP_BEGIN_NAMESPACE_STD @@ -119,4 +122,6 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 +_LIBCPP_POP_MACROS + #endif // _LIBCPP___EXPECTED_UNEXPECTED_H diff --git a/libcxx/include/__filesystem/copy_options.h b/libcxx/include/__filesystem/copy_options.h index 96c7535812e2..11962e494c9d 100644 --- a/libcxx/include/__filesystem/copy_options.h +++ b/libcxx/include/__filesystem/copy_options.h @@ -21,8 +21,6 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - enum class _LIBCPP_ENUM_VIS copy_options : unsigned short { none = 0, skip_existing = 1, @@ -75,8 +73,6 @@ inline copy_options& operator^=(copy_options& __lhs, copy_options __rhs) { return __lhs = __lhs ^ __rhs; } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__filesystem/directory_entry.h b/libcxx/include/__filesystem/directory_entry.h index b17eaaab4c54..bb7a061db4ce 100644 --- a/libcxx/include/__filesystem/directory_entry.h +++ b/libcxx/include/__filesystem/directory_entry.h @@ -12,8 +12,8 @@ #include <__availability> #include <__chrono/time_point.h> +#include <__compare/ordering.h> #include <__config> -#include <__errc> #include <__filesystem/file_status.h> #include <__filesystem/file_time_type.h> #include <__filesystem/file_type.h> @@ -21,11 +21,12 @@ #include <__filesystem/operations.h> #include <__filesystem/path.h> #include <__filesystem/perms.h> +#include <__system_error/errc.h> +#include <__system_error/error_code.h> +#include <__utility/move.h> #include <__utility/unreachable.h> #include <cstdint> -#include <cstdlib> #include <iosfwd> -#include <system_error> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -34,21 +35,20 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> -#ifndef _LIBCPP_CXX03_LANG +#if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH class directory_entry { typedef _VSTD_FS::path _Path; public: // constructors and destructors - directory_entry() noexcept = default; - directory_entry(directory_entry const&) = default; - directory_entry(directory_entry&&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI directory_entry() noexcept = default; + _LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry const&) = default; + _LIBCPP_HIDE_FROM_ABI directory_entry(directory_entry&&) noexcept = default; _LIBCPP_INLINE_VISIBILITY explicit directory_entry(_Path const& __p) : __p_(__p) { @@ -61,10 +61,10 @@ public: __refresh(&__ec); } - ~directory_entry() {} + _LIBCPP_HIDE_FROM_ABI ~directory_entry() {} - directory_entry& operator=(directory_entry const&) = default; - directory_entry& operator=(directory_entry&&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry const&) = default; + _LIBCPP_HIDE_FROM_ABI directory_entry& operator=(directory_entry&&) noexcept = default; _LIBCPP_INLINE_VISIBILITY void assign(_Path const& __p) { @@ -321,8 +321,7 @@ private: __data_ = __dt; } - _LIBCPP_FUNC_VIS - error_code __do_refresh() noexcept; + _LIBCPP_EXPORTED_FROM_ABI error_code __do_refresh() noexcept; _LIBCPP_INLINE_VISIBILITY static bool __is_dne_error(error_code const& __ec) { @@ -510,17 +509,17 @@ public: private: friend class directory_iterator; friend class recursive_directory_iterator; - explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {} - __dir_element_proxy(__dir_element_proxy&& __o) + _LIBCPP_HIDE_FROM_ABI explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {} + _LIBCPP_HIDE_FROM_ABI __dir_element_proxy(__dir_element_proxy&& __o) : __elem_(_VSTD::move(__o.__elem_)) {} directory_entry __elem_; }; -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM -#endif // _LIBCPP_CXX03_LANG +#endif // !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_POP_MACROS diff --git a/libcxx/include/__filesystem/directory_iterator.h b/libcxx/include/__filesystem/directory_iterator.h index 5ff2f01ac7b2..632c2c806369 100644 --- a/libcxx/include/__filesystem/directory_iterator.h +++ b/libcxx/include/__filesystem/directory_iterator.h @@ -16,22 +16,24 @@ #include <__filesystem/directory_entry.h> #include <__filesystem/directory_options.h> #include <__filesystem/path.h> +#include <__iterator/default_sentinel.h> #include <__iterator/iterator_traits.h> #include <__memory/shared_ptr.h> #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> +#include <__system_error/error_code.h> +#include <__utility/move.h> #include <cstddef> -#include <system_error> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#ifndef _LIBCPP_CXX03_LANG +#if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH class _LIBCPP_HIDDEN __dir_stream; class directory_iterator { @@ -81,7 +83,7 @@ public: _LIBCPP_HIDE_FROM_ABI const directory_entry& operator*() const { - _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced"); + _LIBCPP_ASSERT_UNCATEGORIZED(__imp_, "The end iterator cannot be dereferenced"); return __dereference(); } @@ -101,21 +103,23 @@ public: _LIBCPP_HIDE_FROM_ABI directory_iterator& increment(error_code& __ec) { return __increment(&__ec); } +# if _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI bool operator==(default_sentinel_t) const noexcept { return *this == directory_iterator(); } + +# endif + private: inline _LIBCPP_HIDE_FROM_ABI friend bool operator==(const directory_iterator& __lhs, const directory_iterator& __rhs) noexcept; // construct the dir_stream - _LIBCPP_FUNC_VIS - directory_iterator(const path&, error_code*, - directory_options = directory_options::none); + _LIBCPP_EXPORTED_FROM_ABI directory_iterator(const path&, error_code*, directory_options = directory_options::none); - _LIBCPP_FUNC_VIS - directory_iterator& __increment(error_code* __ec = nullptr); + _LIBCPP_EXPORTED_FROM_ABI directory_iterator& __increment(error_code* __ec = nullptr); - _LIBCPP_FUNC_VIS - const directory_entry& __dereference() const; + _LIBCPP_EXPORTED_FROM_ABI const directory_entry& __dereference() const; private: shared_ptr<__dir_stream> __imp_; @@ -144,22 +148,22 @@ end(directory_iterator) noexcept { return directory_iterator(); } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <> -_LIBCPP_AVAILABILITY_FILESYSTEM +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::directory_iterator> = true; template <> -_LIBCPP_AVAILABILITY_FILESYSTEM +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::directory_iterator> = true; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#endif // _LIBCPP_CXX03_LANG +#endif // !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) #endif // _LIBCPP___FILESYSTEM_DIRECTORY_ITERATOR_H diff --git a/libcxx/include/__filesystem/directory_options.h b/libcxx/include/__filesystem/directory_options.h index c5c031a567cf..4c323ccb0cfe 100644 --- a/libcxx/include/__filesystem/directory_options.h +++ b/libcxx/include/__filesystem/directory_options.h @@ -21,8 +21,6 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - enum class _LIBCPP_ENUM_VIS directory_options : unsigned char { none = 0, follow_directory_symlink = 1, @@ -73,8 +71,6 @@ inline directory_options& operator^=(directory_options& __lhs, return __lhs = __lhs ^ __rhs; } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__filesystem/file_status.h b/libcxx/include/__filesystem/file_status.h index ac3f6cbed9d7..0cf405b9c29e 100644 --- a/libcxx/include/__filesystem/file_status.h +++ b/libcxx/include/__filesystem/file_status.h @@ -23,9 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - -class _LIBCPP_TYPE_VIS file_status { +class _LIBCPP_EXPORTED_FROM_ABI file_status { public: // constructors _LIBCPP_INLINE_VISIBILITY @@ -35,14 +33,14 @@ public: : __ft_(__ft), __prms_(__prms) {} - file_status(const file_status&) noexcept = default; - file_status(file_status&&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI file_status(const file_status&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI file_status(file_status&&) noexcept = default; _LIBCPP_INLINE_VISIBILITY ~file_status() {} - file_status& operator=(const file_status&) noexcept = default; - file_status& operator=(file_status&&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI file_status& operator=(const file_status&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI file_status& operator=(file_status&&) noexcept = default; // observers _LIBCPP_INLINE_VISIBILITY @@ -58,13 +56,19 @@ public: _LIBCPP_INLINE_VISIBILITY void permissions(perms __p) noexcept { __prms_ = __p; } +# if _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const file_status& __lhs, const file_status& __rhs) noexcept { + return __lhs.type() == __rhs.type() && __lhs.permissions() == __rhs.permissions(); + } + +# endif + private: file_type __ft_; perms __prms_; }; -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__filesystem/filesystem_error.h b/libcxx/include/__filesystem/filesystem_error.h index effe6998338c..713cc357ee82 100644 --- a/libcxx/include/__filesystem/filesystem_error.h +++ b/libcxx/include/__filesystem/filesystem_error.h @@ -14,11 +14,13 @@ #include <__config> #include <__filesystem/path.h> #include <__memory/shared_ptr.h> +#include <__system_error/error_code.h> +#include <__system_error/system_error.h> #include <__utility/forward.h> +#include <__verbose_abort> #include <iosfwd> #include <new> -#include <system_error> -#include <type_traits> +#include <string> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -28,50 +30,38 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -class _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error { +class _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_EXPORTED_FROM_ABI filesystem_error : public system_error { public: - _LIBCPP_INLINE_VISIBILITY - filesystem_error(const string& __what, error_code __ec) - : system_error(__ec, __what), - __storage_(make_shared<_Storage>(path(), path())) { + _LIBCPP_HIDE_FROM_ABI filesystem_error(const string& __what, error_code __ec) + : system_error(__ec, __what), __storage_(make_shared<_Storage>(path(), path())) { __create_what(0); } - _LIBCPP_INLINE_VISIBILITY - filesystem_error(const string& __what, const path& __p1, error_code __ec) - : system_error(__ec, __what), - __storage_(make_shared<_Storage>(__p1, path())) { + _LIBCPP_HIDE_FROM_ABI filesystem_error(const string& __what, const path& __p1, error_code __ec) + : system_error(__ec, __what), __storage_(make_shared<_Storage>(__p1, path())) { __create_what(1); } - _LIBCPP_INLINE_VISIBILITY - filesystem_error(const string& __what, const path& __p1, const path& __p2, - error_code __ec) - : system_error(__ec, __what), - __storage_(make_shared<_Storage>(__p1, __p2)) { + _LIBCPP_HIDE_FROM_ABI filesystem_error(const string& __what, const path& __p1, const path& __p2, error_code __ec) + : system_error(__ec, __what), __storage_(make_shared<_Storage>(__p1, __p2)) { __create_what(2); } - _LIBCPP_INLINE_VISIBILITY - const path& path1() const noexcept { return __storage_->__p1_; } + _LIBCPP_HIDE_FROM_ABI const path& path1() const noexcept { return __storage_->__p1_; } - _LIBCPP_INLINE_VISIBILITY - const path& path2() const noexcept { return __storage_->__p2_; } + _LIBCPP_HIDE_FROM_ABI const path& path2() const noexcept { return __storage_->__p2_; } - filesystem_error(const filesystem_error&) = default; + _LIBCPP_HIDE_FROM_ABI filesystem_error(const filesystem_error&) = default; ~filesystem_error() override; // key function _LIBCPP_HIDE_FROM_ABI_VIRTUAL - const char* what() const noexcept override { - return __storage_->__what_.c_str(); - } + const char* what() const noexcept override { return __storage_->__what_.c_str(); } void __create_what(int __num_paths); private: struct _LIBCPP_HIDDEN _Storage { - _LIBCPP_INLINE_VISIBILITY - _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {} + _LIBCPP_HIDE_FROM_ABI _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {} path __p1_; path __p2_; @@ -80,22 +70,19 @@ private: shared_ptr<_Storage> __storage_; }; -// TODO(ldionne): We need to pop the pragma and push it again after -// filesystem_error to work around PR41078. -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS template <class... _Args> -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY -#ifndef _LIBCPP_NO_EXCEPTIONS -void __throw_filesystem_error(_Args&&... __args) { +_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY void +__throw_filesystem_error(_Args&&... __args) { throw filesystem_error(_VSTD::forward<_Args>(__args)...); } -#else -void __throw_filesystem_error(_Args&&...) { - _VSTD::abort(); +# else +template <class... _Args> +_LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY void +__throw_filesystem_error(_Args&&...) { + _LIBCPP_VERBOSE_ABORT("filesystem_error was thrown in -fno-exceptions mode"); } -#endif -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +# endif _LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/libcxx/include/__filesystem/operations.h b/libcxx/include/__filesystem/operations.h index f48d301d090c..71b3fb859d49 100644 --- a/libcxx/include/__filesystem/operations.h +++ b/libcxx/include/__filesystem/operations.h @@ -21,46 +21,46 @@ #include <__filesystem/perm_options.h> #include <__filesystem/perms.h> #include <__filesystem/space_info.h> +#include <__system_error/error_code.h> #include <cstdint> -#include <system_error> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#ifndef _LIBCPP_CXX03_LANG +#if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - -_LIBCPP_FUNC_VIS path __absolute(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS path __canonical(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS bool __copy_file(const path& __from, const path& __to, copy_options __opt, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __copy_symlink(const path& __existing_symlink, const path& __new_symlink, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __copy(const path& __from, const path& __to, copy_options __opt, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS bool __create_directories(const path&, error_code* = nullptr); -_LIBCPP_FUNC_VIS void __create_directory_symlink(const path& __to, const path& __new_symlink, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS bool __create_directory(const path&, error_code* = nullptr); -_LIBCPP_FUNC_VIS bool __create_directory(const path&, const path& __attributes, error_code* = nullptr); -_LIBCPP_FUNC_VIS void __create_hard_link(const path& __to, const path& __new_hard_link, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __create_symlink(const path& __to, const path& __new_symlink, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS path __current_path(error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __current_path(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS bool __equivalent(const path&, const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS file_status __status(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS uintmax_t __file_size(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS file_status __symlink_status(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS file_time_type __last_write_time(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __last_write_time(const path&, file_time_type __new_time, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS path __weakly_canonical(path const& __p, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS path __read_symlink(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS uintmax_t __remove_all(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS bool __remove(const path&, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __rename(const path& __from, const path& __to, error_code* __ec = nullptr); -_LIBCPP_FUNC_VIS void __resize_file(const path&, uintmax_t __size, error_code* = nullptr); -_LIBCPP_FUNC_VIS path __temp_directory_path(error_code* __ec = nullptr); +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH + +_LIBCPP_EXPORTED_FROM_ABI path __absolute(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI path __canonical(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __copy_file(const path& __from, const path& __to, copy_options __opt, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __copy_symlink(const path& __existing_symlink, const path& __new_symlink, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __copy(const path& __from, const path& __to, copy_options __opt, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __create_directories(const path&, error_code* = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __create_directory_symlink(const path& __to, const path& __new_symlink, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __create_directory(const path&, error_code* = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __create_directory(const path&, const path& __attributes, error_code* = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __create_hard_link(const path& __to, const path& __new_hard_link, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __create_symlink(const path& __to, const path& __new_symlink, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI path __current_path(error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __current_path(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __equivalent(const path&, const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI file_status __status(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI uintmax_t __file_size(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI file_status __symlink_status(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI file_time_type __last_write_time(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __last_write_time(const path&, file_time_type __new_time, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI path __weakly_canonical(path const& __p, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI path __read_symlink(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI uintmax_t __remove_all(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __remove(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __rename(const path& __from, const path& __to, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __resize_file(const path&, uintmax_t __size, error_code* = nullptr); +_LIBCPP_EXPORTED_FROM_ABI path __temp_directory_path(error_code* __ec = nullptr); inline _LIBCPP_HIDE_FROM_ABI path absolute(const path& __p) { return __absolute(__p); } inline _LIBCPP_HIDE_FROM_ABI path absolute(const path& __p, error_code& __ec) { return __absolute(__p, &__ec); } @@ -118,7 +118,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool is_character_file(const path& __p, error_code& inline _LIBCPP_HIDE_FROM_ABI bool is_directory(file_status __s) noexcept { return __s.type() == file_type::directory; } inline _LIBCPP_HIDE_FROM_ABI bool is_directory(const path& __p) { return is_directory(__status(__p)); } inline _LIBCPP_HIDE_FROM_ABI bool is_directory(const path& __p, error_code& __ec) noexcept { return is_directory(__status(__p, &__ec)); } -_LIBCPP_FUNC_VIS bool __fs_is_empty(const path& __p, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI bool __fs_is_empty(const path& __p, error_code* __ec = nullptr); inline _LIBCPP_HIDE_FROM_ABI bool is_empty(const path& __p) { return __fs_is_empty(__p); } inline _LIBCPP_HIDE_FROM_ABI bool is_empty(const path& __p, error_code& __ec) { return __fs_is_empty(__p, &__ec); } inline _LIBCPP_HIDE_FROM_ABI bool is_fifo(file_status __s) noexcept { return __s.type() == file_type::fifo; } @@ -140,7 +140,7 @@ inline _LIBCPP_HIDE_FROM_ABI file_time_type last_write_time(const path& __p) { r inline _LIBCPP_HIDE_FROM_ABI file_time_type last_write_time(const path& __p, error_code& __ec) noexcept { return __last_write_time(__p, &__ec); } inline _LIBCPP_HIDE_FROM_ABI void last_write_time(const path& __p, file_time_type __t) { __last_write_time(__p, __t); } inline _LIBCPP_HIDE_FROM_ABI void last_write_time(const path& __p, file_time_type __t, error_code& __ec) noexcept { __last_write_time(__p, __t, &__ec); } -_LIBCPP_FUNC_VIS void __permissions(const path&, perms, perm_options, error_code* = nullptr); +_LIBCPP_EXPORTED_FROM_ABI void __permissions(const path&, perms, perm_options, error_code* = nullptr); inline _LIBCPP_HIDE_FROM_ABI void permissions(const path& __p, perms __prms, perm_options __opts = perm_options::replace) { __permissions(__p, __prms, __opts); } inline _LIBCPP_HIDE_FROM_ABI void permissions(const path& __p, perms __prms, error_code& __ec) noexcept { __permissions(__p, __prms, perm_options::replace, &__ec); } inline _LIBCPP_HIDE_FROM_ABI void permissions(const path& __p, perms __prms, perm_options __opts, error_code& __ec) { __permissions(__p, __prms, __opts, &__ec); } @@ -180,7 +180,7 @@ inline _LIBCPP_HIDE_FROM_ABI void rename(const path& __from, const path& __to) { inline _LIBCPP_HIDE_FROM_ABI void rename(const path& __from, const path& __to, error_code& __ec) noexcept { return __rename(__from, __to, &__ec); } inline _LIBCPP_HIDE_FROM_ABI void resize_file(const path& __p, uintmax_t __ns) { return __resize_file(__p, __ns); } inline _LIBCPP_HIDE_FROM_ABI void resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept { return __resize_file(__p, __ns, &__ec); } -_LIBCPP_FUNC_VIS space_info __space(const path&, error_code* __ec = nullptr); +_LIBCPP_EXPORTED_FROM_ABI space_info __space(const path&, error_code* __ec = nullptr); inline _LIBCPP_HIDE_FROM_ABI space_info space(const path& __p) { return __space(__p); } inline _LIBCPP_HIDE_FROM_ABI space_info space(const path& __p, error_code& __ec) noexcept { return __space(__p, &__ec); } inline _LIBCPP_HIDE_FROM_ABI file_status status(const path& __p) { return __status(__p); } @@ -192,10 +192,10 @@ inline _LIBCPP_HIDE_FROM_ABI path temp_directory_path(error_code& __ec) { return inline _LIBCPP_HIDE_FROM_ABI path weakly_canonical(path const& __p) { return __weakly_canonical(__p); } inline _LIBCPP_HIDE_FROM_ABI path weakly_canonical(path const& __p, error_code& __ec) { return __weakly_canonical(__p, &__ec); } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM -#endif // _LIBCPP_CXX03_LANG +#endif // !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) #endif // _LIBCPP___FILESYSTEM_OPERATIONS_H diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index 4e6912fcf3e7..77699c5ae47f 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -14,12 +14,18 @@ #include <__algorithm/replace_copy.h> #include <__availability> #include <__config> +#include <__functional/hash.h> +#include <__functional/unary_function.h> +#include <__fwd/hash.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_pointer.h> #include <cstddef> #include <string> #include <string_view> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include <iomanip> // for quoted @@ -34,7 +40,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH template <class _Tp> struct __can_convert_char { @@ -139,7 +145,7 @@ struct __is_pathable_string< } }; -template <class _Source, class _DS = typename decay<_Source>::type, +template <class _Source, class _DS = __decay_t<_Source>, class _UnqualPtrType = __remove_const_t<__remove_pointer_t<_DS> >, bool _IsCharPtr = is_pointer<_DS>::value&& @@ -168,7 +174,7 @@ struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> static _ECharT __first_or_null(const _ECharT* __b) { return *__b; } }; -template <class _Iter, bool _IsIt = __is_cpp17_input_iterator<_Iter>::value, +template <class _Iter, bool _IsIt = __has_input_iterator_category<_Iter>::value, class = void> struct __is_pathable_iter : false_type {}; @@ -217,10 +223,8 @@ typedef char __path_value; #endif #if defined(_LIBCPP_WIN32API) -_LIBCPP_FUNC_VIS -size_t __wide_to_char(const wstring&, char*, size_t); -_LIBCPP_FUNC_VIS -size_t __char_to_wide(const string&, wchar_t*, size_t); +_LIBCPP_EXPORTED_FROM_ABI size_t __wide_to_char(const wstring&, char*, size_t); +_LIBCPP_EXPORTED_FROM_ABI size_t __char_to_wide(const string&, wchar_t*, size_t); #endif template <class _ECharT> @@ -303,7 +307,7 @@ struct _PathCVT<__path_value> { template <class _Iter> _LIBCPP_HIDE_FROM_ABI - static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type + static typename enable_if<__has_exactly_input_iterator_category<_Iter>::value>::type __append_range(__path_string& __dest, _Iter __b, _Iter __e) { for (; __b != __e; ++__b) __dest.push_back(*__b); @@ -311,7 +315,7 @@ struct _PathCVT<__path_value> { template <class _Iter> _LIBCPP_HIDE_FROM_ABI - static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type + static typename enable_if<__has_forward_iterator_category<_Iter>::value>::type __append_range(__path_string& __dest, _Iter __b, _Iter __e) { __dest.append(__b, __e); } @@ -348,7 +352,7 @@ struct _PathCVT<char> { template <class _Iter> _LIBCPP_HIDE_FROM_ABI - static typename enable_if<__is_exactly_cpp17_input_iterator<_Iter>::value>::type + static typename enable_if<__has_exactly_input_iterator_category<_Iter>::value>::type __append_range(__path_string& __dest, _Iter __b, _Iter __e) { basic_string<char> __tmp(__b, __e); __append_string(__dest, __tmp); @@ -356,7 +360,7 @@ struct _PathCVT<char> { template <class _Iter> _LIBCPP_HIDE_FROM_ABI - static typename enable_if<__is_cpp17_forward_iterator<_Iter>::value>::type + static typename enable_if<__has_forward_iterator_category<_Iter>::value>::type __append_range(__path_string& __dest, _Iter __b, _Iter __e) { basic_string<char> __tmp(__b, __e); __append_string(__dest, __tmp); @@ -439,7 +443,7 @@ struct _PathExport<char8_t> { #endif /* !_LIBCPP_HAS_NO_CHAR8_T */ #endif /* _LIBCPP_WIN32API */ -class _LIBCPP_TYPE_VIS path { +class _LIBCPP_EXPORTED_FROM_ABI path { template <class _SourceOrIter, class _Tp = path&> using _EnableIfPathable = typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type; @@ -1029,7 +1033,7 @@ public: } // iterators - class _LIBCPP_TYPE_VIS iterator; + class _LIBCPP_EXPORTED_FROM_ABI iterator; typedef iterator const_iterator; iterator begin() const; @@ -1079,13 +1083,23 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); } -_LIBCPP_FUNC_VIS -size_t hash_value(const path& __p) noexcept; +_LIBCPP_EXPORTED_FROM_ABI size_t hash_value(const path& __p) noexcept; -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM +_LIBCPP_BEGIN_NAMESPACE_STD + +template <> +struct _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY hash<_VSTD_FS::path> : __unary_function<_VSTD_FS::path, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(_VSTD_FS::path const& __p) const noexcept { + return _VSTD_FS::hash_value(__p); + } +}; + +_LIBCPP_END_NAMESPACE_STD + #endif // _LIBCPP_CXX03_LANG #endif // _LIBCPP___FILESYSTEM_PATH_H diff --git a/libcxx/include/__filesystem/path_iterator.h b/libcxx/include/__filesystem/path_iterator.h index 6f2baf8f7a29..9961b46cf81c 100644 --- a/libcxx/include/__filesystem/path_iterator.h +++ b/libcxx/include/__filesystem/path_iterator.h @@ -27,9 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - -class _LIBCPP_TYPE_VIS path::iterator { +class _LIBCPP_EXPORTED_FROM_ABI path::iterator { public: enum _ParserState : unsigned char { _Singular, @@ -56,10 +54,10 @@ public: : __stashed_elem_(), __path_ptr_(nullptr), __entry_(), __state_(_Singular) {} - iterator(const iterator&) = default; - ~iterator() = default; + _LIBCPP_HIDE_FROM_ABI iterator(const iterator&) = default; + _LIBCPP_HIDE_FROM_ABI ~iterator() = default; - iterator& operator=(const iterator&) = default; + _LIBCPP_HIDE_FROM_ABI iterator& operator=(const iterator&) = default; _LIBCPP_INLINE_VISIBILITY reference operator*() const { return __stashed_elem_; } @@ -69,10 +67,10 @@ public: _LIBCPP_INLINE_VISIBILITY iterator& operator++() { - _LIBCPP_ASSERT(__state_ != _Singular, - "attempting to increment a singular iterator"); - _LIBCPP_ASSERT(__state_ != _AtEnd, - "attempting to increment the end iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__state_ != _Singular, + "attempting to increment a singular iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__state_ != _AtEnd, + "attempting to increment the end iterator"); return __increment(); } @@ -85,10 +83,10 @@ public: _LIBCPP_INLINE_VISIBILITY iterator& operator--() { - _LIBCPP_ASSERT(__state_ != _Singular, - "attempting to decrement a singular iterator"); - _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(), - "attempting to decrement the begin iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__state_ != _Singular, + "attempting to decrement a singular iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__entry_.data() != __path_ptr_->native().data(), + "attempting to decrement the begin iterator"); return __decrement(); } @@ -114,19 +112,19 @@ private: _ParserState __state_; }; +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs, const path::iterator& __rhs) { return __lhs.__path_ptr_ == __rhs.__path_ptr_ && __lhs.__entry_.data() == __rhs.__entry_.data(); } +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs, const path::iterator& __rhs) { return !(__lhs == __rhs); } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__filesystem/perm_options.h b/libcxx/include/__filesystem/perm_options.h index 4aba302edfbe..e77af9ef97e1 100644 --- a/libcxx/include/__filesystem/perm_options.h +++ b/libcxx/include/__filesystem/perm_options.h @@ -21,8 +21,6 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - enum class _LIBCPP_ENUM_VIS perm_options : unsigned char { replace = 1, add = 2, @@ -68,8 +66,6 @@ inline perm_options& operator^=(perm_options& __lhs, perm_options __rhs) { return __lhs = __lhs ^ __rhs; } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__filesystem/perms.h b/libcxx/include/__filesystem/perms.h index df4590057ee1..77bc65210342 100644 --- a/libcxx/include/__filesystem/perms.h +++ b/libcxx/include/__filesystem/perms.h @@ -21,8 +21,6 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - // On Windows, these permission bits map to one single readonly flag per // file, and the executable bit is always returned as set. When setting // permissions, as long as the write bit is set for either owner, group or @@ -86,8 +84,6 @@ inline perms& operator|=(perms& __lhs, perms __rhs) { return __lhs = __lhs | __r _LIBCPP_INLINE_VISIBILITY inline perms& operator^=(perms& __lhs, perms __rhs) { return __lhs = __lhs ^ __rhs; } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__filesystem/recursive_directory_iterator.h b/libcxx/include/__filesystem/recursive_directory_iterator.h index b20d201f5836..c38d58e50215 100644 --- a/libcxx/include/__filesystem/recursive_directory_iterator.h +++ b/libcxx/include/__filesystem/recursive_directory_iterator.h @@ -15,22 +15,24 @@ #include <__filesystem/directory_entry.h> #include <__filesystem/directory_options.h> #include <__filesystem/path.h> +#include <__iterator/default_sentinel.h> #include <__iterator/iterator_traits.h> #include <__memory/shared_ptr.h> #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> +#include <__system_error/error_code.h> +#include <__utility/move.h> #include <cstddef> -#include <system_error> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#ifndef _LIBCPP_CXX03_LANG +#if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH class recursive_directory_iterator { public: @@ -59,10 +61,10 @@ public: recursive_directory_iterator(const path& __p, error_code& __ec) : recursive_directory_iterator(__p, directory_options::none, &__ec) {} - recursive_directory_iterator(const recursive_directory_iterator&) = default; - recursive_directory_iterator(recursive_directory_iterator&&) = default; + _LIBCPP_HIDE_FROM_ABI recursive_directory_iterator(const recursive_directory_iterator&) = default; + _LIBCPP_HIDE_FROM_ABI recursive_directory_iterator(recursive_directory_iterator&&) = default; - recursive_directory_iterator& + _LIBCPP_HIDE_FROM_ABI recursive_directory_iterator& operator=(const recursive_directory_iterator&) = default; _LIBCPP_INLINE_VISIBILITY @@ -76,7 +78,7 @@ public: return *this; } - ~recursive_directory_iterator() = default; + _LIBCPP_HIDE_FROM_ABI ~recursive_directory_iterator() = default; _LIBCPP_INLINE_VISIBILITY const directory_entry& operator*() const { return __dereference(); } @@ -84,7 +86,7 @@ public: _LIBCPP_INLINE_VISIBILITY const directory_entry* operator->() const { return &__dereference(); } - recursive_directory_iterator& operator++() { return __increment(); } + _LIBCPP_HIDE_FROM_ABI recursive_directory_iterator& operator++() { return __increment(); } _LIBCPP_INLINE_VISIBILITY __dir_element_proxy operator++(int) { @@ -98,8 +100,8 @@ public: return __increment(&__ec); } - _LIBCPP_FUNC_VIS directory_options options() const; - _LIBCPP_FUNC_VIS int depth() const; + _LIBCPP_EXPORTED_FROM_ABI directory_options options() const; + _LIBCPP_EXPORTED_FROM_ABI int depth() const; _LIBCPP_INLINE_VISIBILITY void pop() { __pop(); } @@ -113,25 +115,21 @@ public: _LIBCPP_INLINE_VISIBILITY void disable_recursion_pending() { __rec_ = false; } -private: - _LIBCPP_FUNC_VIS - recursive_directory_iterator(const path& __p, directory_options __opt, - error_code* __ec); - - _LIBCPP_FUNC_VIS - const directory_entry& __dereference() const; +# if _LIBCPP_STD_VER >= 20 - _LIBCPP_FUNC_VIS - bool __try_recursion(error_code* __ec); - - _LIBCPP_FUNC_VIS - void __advance(error_code* __ec = nullptr); + _LIBCPP_HIDE_FROM_ABI bool operator==(default_sentinel_t) const noexcept { + return *this == recursive_directory_iterator(); + } - _LIBCPP_FUNC_VIS - recursive_directory_iterator& __increment(error_code* __ec = nullptr); +# endif - _LIBCPP_FUNC_VIS - void __pop(error_code* __ec = nullptr); +private: + _LIBCPP_EXPORTED_FROM_ABI recursive_directory_iterator(const path& __p, directory_options __opt, error_code* __ec); + _LIBCPP_EXPORTED_FROM_ABI const directory_entry& __dereference() const; + _LIBCPP_EXPORTED_FROM_ABI bool __try_recursion(error_code* __ec); + _LIBCPP_EXPORTED_FROM_ABI void __advance(error_code* __ec = nullptr); + _LIBCPP_EXPORTED_FROM_ABI recursive_directory_iterator& __increment(error_code* __ec = nullptr); + _LIBCPP_EXPORTED_FROM_ABI void __pop(error_code* __ec = nullptr); inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const recursive_directory_iterator&, @@ -164,22 +162,22 @@ end(recursive_directory_iterator) noexcept { return recursive_directory_iterator(); } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <> -_LIBCPP_AVAILABILITY_FILESYSTEM +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline constexpr bool _VSTD::ranges::enable_borrowed_range<_VSTD_FS::recursive_directory_iterator> = true; template <> -_LIBCPP_AVAILABILITY_FILESYSTEM +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY inline constexpr bool _VSTD::ranges::enable_view<_VSTD_FS::recursive_directory_iterator> = true; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#endif // _LIBCPP_CXX03_LANG +#endif // !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) #endif // _LIBCPP___FILESYSTEM_RECURSIVE_DIRECTORY_ITERATOR_H diff --git a/libcxx/include/__filesystem/space_info.h b/libcxx/include/__filesystem/space_info.h index d0747e35ebf0..929f51466424 100644 --- a/libcxx/include/__filesystem/space_info.h +++ b/libcxx/include/__filesystem/space_info.h @@ -22,20 +22,16 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH - -struct _LIBCPP_TYPE_VIS space_info { +struct _LIBCPP_EXPORTED_FROM_ABI space_info { uintmax_t capacity; uintmax_t free; uintmax_t available; -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const space_info&, const space_info&) = default; # endif }; -_LIBCPP_AVAILABILITY_FILESYSTEM_POP - _LIBCPP_END_NAMESPACE_FILESYSTEM #endif // _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__filesystem/u8path.h b/libcxx/include/__filesystem/u8path.h index d35faa14bb8a..90b879aec28e 100644 --- a/libcxx/include/__filesystem/u8path.h +++ b/libcxx/include/__filesystem/u8path.h @@ -15,7 +15,6 @@ #include <__config> #include <__filesystem/path.h> #include <string> -#include <type_traits> // Only required on Windows for __widen_from_utf8, and included conservatively // because it requires support for localization. @@ -31,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -_LIBCPP_AVAILABILITY_FILESYSTEM_PUSH +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_PUSH template <class _InputIt> _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T @@ -99,7 +98,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T #endif } -_LIBCPP_AVAILABILITY_FILESYSTEM_POP +_LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY_POP _LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h index ddfe76728e9b..45f9da801722 100644 --- a/libcxx/include/__format/buffer.h +++ b/libcxx/include/__format/buffer.h @@ -27,11 +27,18 @@ #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> #include <__iterator/wrap_iter.h> +#include <__memory/addressof.h> +#include <__memory/allocate_at_least.h> +#include <__memory/allocator_traits.h> +#include <__memory/construct_at.h> +#include <__memory/ranges_construct_at.h> +#include <__memory/uninitialized_algorithms.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/conditional.h> +#include <__utility/exception_guard.h> #include <__utility/move.h> #include <cstddef> #include <string_view> -#include <type_traits> -#include <vector> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -42,7 +49,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format { @@ -100,7 +107,7 @@ public: size_t __n = __str.size(); __flush_on_overflow(__n); - if (__n <= __capacity_) { + if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). _VSTD::copy_n(__str.data(), __n, _VSTD::addressof(__ptr_[__size_])); __size_ += __n; return; @@ -108,7 +115,7 @@ public: // The output doesn't fit in the internal buffer. // Copy the data in "__capacity_" sized chunks. - _LIBCPP_ASSERT(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); + _LIBCPP_ASSERT_UNCATEGORIZED(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); const _InCharT* __first = __str.data(); do { size_t __chunk = _VSTD::min(__n, __capacity_); @@ -125,11 +132,11 @@ public: /// Like @ref __copy it may need to do type conversion. template <__fmt_char_type _InCharT, class _UnaryOperation> _LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) { - _LIBCPP_ASSERT(__first <= __last, "not a valid range"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "not a valid range"); size_t __n = static_cast<size_t>(__last - __first); __flush_on_overflow(__n); - if (__n <= __capacity_) { + if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). _VSTD::transform(__first, __last, _VSTD::addressof(__ptr_[__size_]), _VSTD::move(__operation)); __size_ += __n; return; @@ -137,7 +144,7 @@ public: // The output doesn't fit in the internal buffer. // Transform the data in "__capacity_" sized chunks. - _LIBCPP_ASSERT(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); + _LIBCPP_ASSERT_UNCATEGORIZED(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); do { size_t __chunk = _VSTD::min(__n, __capacity_); _VSTD::transform(__first, __first + __chunk, _VSTD::addressof(__ptr_[__size_]), __operation); @@ -151,7 +158,7 @@ public: /// A \c fill_n wrapper. _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { __flush_on_overflow(__n); - if (__n <= __capacity_) { + if (__n < __capacity_) { // push_back requires the buffer to have room for at least one character (so use <). _VSTD::fill_n(_VSTD::addressof(__ptr_[__size_]), __n, __value); __size_ += __n; return; @@ -159,7 +166,7 @@ public: // The output doesn't fit in the internal buffer. // Fill the buffer in "__capacity_" sized chunks. - _LIBCPP_ASSERT(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); + _LIBCPP_ASSERT_UNCATEGORIZED(__size_ == 0, "the buffer should be flushed by __flush_on_overflow"); do { size_t __chunk = _VSTD::min(__n, __capacity_); _VSTD::fill_n(_VSTD::addressof(__ptr_[__size_]), __chunk, __value); @@ -246,9 +253,9 @@ class _LIBCPP_TEMPLATE_VIS __direct_storage {}; template <class _OutIt, class _CharT> concept __enable_direct_output = __fmt_char_type<_CharT> && (same_as<_OutIt, _CharT*> -#ifndef _LIBCPP_ENABLE_DEBUG_MODE + // TODO(hardening): the following check might not apply to hardened iterators and might need to be wrapped in an + // `#ifdef`. || same_as<_OutIt, __wrap_iter<_CharT*>> -#endif ); /// Write policy for directly writing to the underlying output. @@ -510,13 +517,19 @@ public: // context and the format arguments need to be retargeted to the new context. // This retargeting is done by a basic_format_context specialized for the // __iterator of this container. +// +// This class uses its own buffer management, since using vector +// would lead to a circular include with formatter for vector<bool>. template <__fmt_char_type _CharT> class _LIBCPP_TEMPLATE_VIS __retarget_buffer { + using _Alloc = allocator<_CharT>; + public: using value_type = _CharT; struct __iterator { using difference_type = ptrdiff_t; + using value_type = _CharT; _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(__retarget_buffer& __buffer) : __buffer_(std::addressof(__buffer)) {} @@ -535,36 +548,101 @@ public: __retarget_buffer* __buffer_; }; - _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) { __buffer_.reserve(__size_hint); } + __retarget_buffer(const __retarget_buffer&) = delete; + __retarget_buffer& operator=(const __retarget_buffer&) = delete; + + _LIBCPP_HIDE_FROM_ABI explicit __retarget_buffer(size_t __size_hint) { + // When the initial size is very small a lot of resizes happen + // when elements added. So use a hard-coded minimum size. + // + // Note a size < 2 will not work + // - 0 there is no buffer, while push_back requires 1 empty element. + // - 1 multiplied by the grow factor is 1 and thus the buffer never + // grows. + auto __result = std::__allocate_at_least(__alloc_, std::max(__size_hint, 256 / sizeof(_CharT))); + __ptr_ = __result.ptr; + __capacity_ = __result.count; + } + + _LIBCPP_HIDE_FROM_ABI ~__retarget_buffer() { + ranges::destroy_n(__ptr_, __size_); + allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_); + } _LIBCPP_HIDE_FROM_ABI __iterator __make_output_iterator() { return __iterator{*this}; } - _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { __buffer_.push_back(__c); } + _LIBCPP_HIDE_FROM_ABI void push_back(_CharT __c) { + std::construct_at(__ptr_ + __size_, __c); + ++__size_; + + if (__size_ == __capacity_) + __grow_buffer(); + } template <__fmt_char_type _InCharT> _LIBCPP_HIDE_FROM_ABI void __copy(basic_string_view<_InCharT> __str) { - __buffer_.insert(__buffer_.end(), __str.begin(), __str.end()); + size_t __n = __str.size(); + if (__size_ + __n >= __capacity_) + // Push_back requires the buffer to have room for at least one character. + __grow_buffer(__size_ + __n + 1); + + std::uninitialized_copy_n(__str.data(), __n, __ptr_ + __size_); + __size_ += __n; } template <__fmt_char_type _InCharT, class _UnaryOperation> _LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) { - _LIBCPP_ASSERT(__first <= __last, "not a valid range"); - std::transform(__first, __last, std::back_inserter(__buffer_), std::move(__operation)); + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "not a valid range"); + + size_t __n = static_cast<size_t>(__last - __first); + if (__size_ + __n >= __capacity_) + // Push_back requires the buffer to have room for at least one character. + __grow_buffer(__size_ + __n + 1); + + std::uninitialized_default_construct_n(__ptr_ + __size_, __n); + std::transform(__first, __last, __ptr_ + __size_, std::move(__operation)); + __size_ += __n; } - _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { __buffer_.insert(__buffer_.end(), __n, __value); } + _LIBCPP_HIDE_FROM_ABI void __fill(size_t __n, _CharT __value) { + if (__size_ + __n >= __capacity_) + // Push_back requires the buffer to have room for at least one character. + __grow_buffer(__size_ + __n + 1); + + std::uninitialized_fill_n(__ptr_ + __size_, __n, __value); + __size_ += __n; + } - _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__buffer_.data(), __buffer_.size()}; } + _LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT> __view() { return {__ptr_, __size_}; } private: - // Use vector instead of string to avoid adding zeros after every append - // operation. The buffer is exposed as a string_view and not as a c-string. - vector<_CharT> __buffer_; + _LIBCPP_HIDE_FROM_ABI void __grow_buffer() { __grow_buffer(__capacity_ * 1.6); } + + _LIBCPP_HIDE_FROM_ABI void __grow_buffer(size_t __capacity) { + _LIBCPP_ASSERT_UNCATEGORIZED(__capacity > __capacity_, "the buffer must grow"); + auto __result = std::__allocate_at_least(__alloc_, __capacity); + auto __guard = std::__make_exception_guard([&] { + allocator_traits<_Alloc>::deallocate(__alloc_, __result.ptr, __result.count); + }); + // This shouldn't throw, but just to be safe. Note that at -O1 this + // guard is optimized away so there is no runtime overhead. + std::uninitialized_move_n(__ptr_, __size_, __result.ptr); + __guard.__complete(); + ranges::destroy_n(__ptr_, __size_); + allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_); + + __ptr_ = __result.ptr; + __capacity_ = __result.count; + } + _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_; + _CharT* __ptr_; + size_t __capacity_; + size_t __size_{0}; }; } // namespace __format -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/concepts.h b/libcxx/include/__format/concepts.h index fe4a7b9625ce..ae96b6a19811 100644 --- a/libcxx/include/__format/concepts.h +++ b/libcxx/include/__format/concepts.h @@ -16,9 +16,9 @@ #include <__format/format_fwd.h> #include <__format/format_parse_context.h> #include <__type_traits/is_specialization.h> +#include <__type_traits/remove_const.h> #include <__utility/pair.h> #include <tuple> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 /// The character type specializations of \ref formatter. template <class _CharT> @@ -44,19 +44,23 @@ concept __fmt_char_type = template <class _CharT> using __fmt_iter_for = _CharT*; +template <class _Tp, class _Context, class _Formatter = typename _Context::template formatter_type<remove_const_t<_Tp>>> +concept __formattable_with = + semiregular<_Formatter> && + requires(_Formatter& __f, + const _Formatter& __cf, + _Tp&& __t, + _Context __fc, + basic_format_parse_context<typename _Context::char_type> __pc) { + { __f.parse(__pc) } -> same_as<typename decltype(__pc)::iterator>; + { __cf.format(__t, __fc) } -> same_as<typename _Context::iterator>; + }; + template <class _Tp, class _CharT> concept __formattable = - (semiregular<formatter<remove_cvref_t<_Tp>, _CharT>>) && - requires(formatter<remove_cvref_t<_Tp>, _CharT> __f, - const formatter<remove_cvref_t<_Tp>, _CharT> __cf, - _Tp __t, - basic_format_context<__fmt_iter_for<_CharT>, _CharT> __fc, - basic_format_parse_context<_CharT> __pc) { - { __f.parse(__pc) } -> same_as<typename basic_format_parse_context<_CharT>::iterator>; - { __cf.format(__t, __fc) } -> same_as<__fmt_iter_for<_CharT>>; - }; + __formattable_with<remove_reference_t<_Tp>, basic_format_context<__fmt_iter_for<_CharT>, _CharT>>; -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 template <class _Tp, class _CharT> concept formattable = __formattable<_Tp, _CharT>; @@ -66,12 +70,11 @@ concept formattable = __formattable<_Tp, _CharT>; // TODO FMT Add a test to validate we fail when using that concept after P2165 // has been implemented. template <class _Tp> -concept __fmt_pair_like = __is_specialization_v<_Tp, pair> || - // Use a requires since tuple_size_v may fail to instantiate, - (__is_specialization_v<_Tp, tuple> && requires { tuple_size_v<_Tp> == 2; }); +concept __fmt_pair_like = + __is_specialization_v<_Tp, pair> || (__is_specialization_v<_Tp, tuple> && tuple_size_v<_Tp> == 2); -# endif //_LIBCPP_STD_VER > 20 -#endif //_LIBCPP_STD_VER > 17 +# endif //_LIBCPP_STD_VER >= 23 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/container_adaptor.h b/libcxx/include/__format/container_adaptor.h index 62b698186ea1..ec806ef16bf5 100644 --- a/libcxx/include/__format/container_adaptor.h +++ b/libcxx/include/__format/container_adaptor.h @@ -14,17 +14,19 @@ # pragma GCC system_header #endif -#include <__availability> #include <__config> #include <__format/concepts.h> #include <__format/formatter.h> #include <__format/range_default_formatter.h> +#include <__ranges/ref_view.h> +#include <__type_traits/is_const.h> +#include <__type_traits/maybe_const.h> #include <queue> #include <stack> _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 // [container.adaptors.format] only specifies the library should provide the // formatter specializations, not which header should provide them. @@ -33,10 +35,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD // adaptor headers. To use the format functions users already include <format>. template <class _Adaptor, class _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_container_adaptor { +struct _LIBCPP_TEMPLATE_VIS __formatter_container_adaptor { private: - using __maybe_const_adaptor = __fmt_maybe_const<_Adaptor, _CharT>; - formatter<typename _Adaptor::container_type, _CharT> __underlying_; + using __maybe_const_container = __fmt_maybe_const<typename _Adaptor::container_type, _CharT>; + using __maybe_const_adaptor = __maybe_const<is_const_v<__maybe_const_container>, _Adaptor>; + formatter<ranges::ref_view<__maybe_const_container>, _CharT> __underlying_; public: template <class _ParseContext> @@ -52,18 +55,18 @@ public: }; template <class _CharT, class _Tp, formattable<_CharT> _Container> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<queue<_Tp, _Container>, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<queue<_Tp, _Container>, _CharT> : public __formatter_container_adaptor<queue<_Tp, _Container>, _CharT> {}; template <class _CharT, class _Tp, class _Container, class _Compare> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<priority_queue<_Tp, _Container, _Compare>, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<priority_queue<_Tp, _Container, _Compare>, _CharT> : public __formatter_container_adaptor<priority_queue<_Tp, _Container, _Compare>, _CharT> {}; template <class _CharT, class _Tp, formattable<_CharT> _Container> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<stack<_Tp, _Container>, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<stack<_Tp, _Container>, _CharT> : public __formatter_container_adaptor<stack<_Tp, _Container>, _CharT> {}; -#endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/enable_insertable.h b/libcxx/include/__format/enable_insertable.h index 71b4252930de..86ef94a325b1 100644 --- a/libcxx/include/__format/enable_insertable.h +++ b/libcxx/include/__format/enable_insertable.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format { @@ -28,7 +28,7 @@ inline constexpr bool __enable_insertable = false; } // namespace __format -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/escaped_output_table.h b/libcxx/include/__format/escaped_output_table.h index bd2994bdc66d..222847e6af67 100644 --- a/libcxx/include/__format/escaped_output_table.h +++ b/libcxx/include/__format/escaped_output_table.h @@ -72,7 +72,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 namespace __escaped_output_table { @@ -1031,7 +1031,7 @@ inline constexpr uint32_t __unallocated_region_lower_bound = 0x000323b0; } // namespace __escaped_output_table -#endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/extended_grapheme_cluster_table.h b/libcxx/include/__format/extended_grapheme_cluster_table.h index 1ffcfeb54968..bd6d39fdc7c2 100644 --- a/libcxx/include/__format/extended_grapheme_cluster_table.h +++ b/libcxx/include/__format/extended_grapheme_cluster_table.h @@ -73,7 +73,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __extended_grapheme_custer_property_boundary { @@ -1654,7 +1654,7 @@ inline constexpr uint32_t __entries[1496] = { } // namespace __extended_grapheme_custer_property_boundary -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/format_arg.h b/libcxx/include/__format/format_arg.h index 771a03ff2fa9..5cbfe812341b 100644 --- a/libcxx/include/__format/format_arg.h +++ b/libcxx/include/__format/format_arg.h @@ -13,15 +13,17 @@ #include <__assert> #include <__concepts/arithmetic.h> #include <__config> -#include <__format/format_error.h> +#include <__format/concepts.h> #include <__format/format_fwd.h> #include <__format/format_parse_context.h> #include <__functional/invoke.h> #include <__memory/addressof.h> +#include <__type_traits/conditional.h> #include <__utility/forward.h> +#include <__utility/move.h> #include <__utility/unreachable.h> #include <__variant/monostate.h> -#include <string> +#include <cstdint> #include <string_view> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -30,7 +32,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format { /// The type stored in @ref basic_format_arg. @@ -81,7 +83,7 @@ constexpr bool __use_packed_format_arg_store(size_t __size) { return __size <= _ _LIBCPP_HIDE_FROM_ABI constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) { - _LIBCPP_ASSERT(__id <= __packed_types_max, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__id <= __packed_types_max, ""); if (__id > 0) __types >>= __id * __packed_arg_t_bits; @@ -94,7 +96,7 @@ constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) { // This function is not user obervable, so it can directly use the non-standard // types of the "variant". See __arg_t for more details. template <class _Visitor, class _Context> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) +_LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { switch (__arg.__type_) { case __format::__arg_t::__none: @@ -155,18 +157,14 @@ public: /// Contains the implementation for basic_format_arg::handle. struct __handle { template <class _Tp> - _LIBCPP_HIDE_FROM_ABI explicit __handle(_Tp&& __v) noexcept + _LIBCPP_HIDE_FROM_ABI explicit __handle(_Tp& __v) noexcept : __ptr_(_VSTD::addressof(__v)), __format_([](basic_format_parse_context<_CharT>& __parse_ctx, _Context& __ctx, const void* __ptr) { - using _Dp = remove_cvref_t<_Tp>; - using _Formatter = typename _Context::template formatter_type<_Dp>; - constexpr bool __const_formattable = - requires { _Formatter().format(std::declval<const _Dp&>(), std::declval<_Context&>()); }; - using _Qp = conditional_t<__const_formattable, const _Dp, _Dp>; + using _Dp = remove_const_t<_Tp>; + using _Qp = conditional_t<__formattable_with<const _Dp, _Context>, const _Dp, _Dp>; + static_assert(__formattable_with<_Qp, _Context>, "Mandated by [format.arg]/10"); - static_assert(__const_formattable || !is_const_v<remove_reference_t<_Tp>>, "Mandated by [format.arg]/18"); - - _Formatter __f; + typename _Context::template formatter_type<_Dp> __f; __parse_ctx.advance_to(__f.parse(__parse_ctx)); __ctx.advance_to(__f.format(*const_cast<_Qp*>(static_cast<const _Dp*>(__ptr)), __ctx)); }) {} @@ -218,13 +216,11 @@ public: _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(basic_string_view<_CharT> __value) noexcept : __string_view_(__value) {} _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const void* __value) noexcept : __ptr_(__value) {} - _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__handle __value) noexcept - // TODO FMT Investigate why it doesn't work without the forward. - : __handle_(std::forward<__handle>(__value)) {} + _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__handle&& __value) noexcept : __handle_(std::move(__value)) {} }; template <class _Context> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg { +class _LIBCPP_TEMPLATE_VIS basic_format_arg { public: class _LIBCPP_TEMPLATE_VIS handle; @@ -276,7 +272,7 @@ private: // This function is user facing, so it must wrap the non-standard types of // the "variant" in a handle to stay conforming. See __arg_t for more details. template <class _Visitor, class _Context> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) +_LIBCPP_HIDE_FROM_ABI decltype(auto) visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { switch (__arg.__type_) { # ifndef _LIBCPP_HAS_NO_INT128 @@ -295,7 +291,7 @@ visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { } } -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/format_arg_store.h b/libcxx/include/__format/format_arg_store.h index 6f4f4c3617ad..15ec8eb0a7d8 100644 --- a/libcxx/include/__format/format_arg_store.h +++ b/libcxx/include/__format/format_arg_store.h @@ -19,15 +19,15 @@ #include <__config> #include <__format/concepts.h> #include <__format/format_arg.h> -#include <__utility/forward.h> -#include <cstring> +#include <__type_traits/conditional.h> +#include <__type_traits/extent.h> +#include <__type_traits/remove_const.h> #include <string> #include <string_view> -#include <type_traits> _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format { @@ -142,21 +142,31 @@ consteval __arg_t __determine_arg_t() { // // Note this version can't be constrained avoiding ambiguous overloads. // That means it can be instantiated by disabled formatters. To solve this, a -// constrained version for not formattable formatters is added. That overload -// is marked as deleted to fail creating a storage type for disabled formatters. +// constrained version for not formattable formatters is added. template <class _Context, class _Tp> consteval __arg_t __determine_arg_t() { return __arg_t::__handle; } +// The overload for not formattable types allows triggering the static +// assertion below. template <class _Context, class _Tp> requires(!__formattable<_Tp, typename _Context::char_type>) -consteval __arg_t __determine_arg_t() = delete; +consteval __arg_t __determine_arg_t() { + return __arg_t::__none; +} +// Pseudo constuctor for basic_format_arg +// +// Modeled after template<class T> explicit basic_format_arg(T& v) noexcept; +// [format.arg]/4-6 template <class _Context, class _Tp> -_LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp&& __value) noexcept { - constexpr __arg_t __arg = __determine_arg_t<_Context, remove_cvref_t<_Tp>>(); - static_assert(__arg != __arg_t::__none); +_LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp& __value) noexcept { + using _Dp = remove_const_t<_Tp>; + constexpr __arg_t __arg = __determine_arg_t<_Context, _Dp>(); + static_assert(__arg != __arg_t::__none, "the supplied type is not formattable"); + + static_assert(__formattable_with<_Tp, _Context>); // Not all types can be used to directly initialize the // __basic_format_arg_value. First handle all types needing adjustment, the @@ -175,9 +185,9 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp&& __val return basic_format_arg<_Context>{__arg, static_cast<unsigned long long>(__value)}; else if constexpr (__arg == __arg_t::__string_view) // Using std::size on a character array will add the NUL-terminator to the size. - if constexpr (is_array_v<remove_cvref_t<_Tp>>) + if constexpr (is_array_v<_Dp>) return basic_format_arg<_Context>{ - __arg, basic_string_view<typename _Context::char_type>{__value, extent_v<remove_cvref_t<_Tp>> - 1}}; + __arg, basic_string_view<typename _Context::char_type>{__value, extent_v<_Dp> - 1}}; else // When the _Traits or _Allocator are different an implicit conversion will // fail. @@ -186,8 +196,7 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp&& __val else if constexpr (__arg == __arg_t::__ptr) return basic_format_arg<_Context>{__arg, static_cast<const void*>(__value)}; else if constexpr (__arg == __arg_t::__handle) - return basic_format_arg<_Context>{ - __arg, typename __basic_format_arg_value<_Context>::__handle{_VSTD::forward<_Tp>(__value)}}; + return basic_format_arg<_Context>{__arg, typename __basic_format_arg_value<_Context>::__handle{__value}}; else return basic_format_arg<_Context>{__arg, __value}; } @@ -218,7 +227,7 @@ _LIBCPP_HIDE_FROM_ABI void __store_basic_format_arg(basic_format_arg<_Context>* template <class _Context, size_t N> struct __packed_format_arg_store { __basic_format_arg_value<_Context> __values_[N]; - uint64_t __types_; + uint64_t __types_ = 0; }; template <class _Context, size_t N> @@ -247,7 +256,7 @@ struct _LIBCPP_TEMPLATE_VIS __format_arg_store { _Storage __storage; }; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/format_args.h b/libcxx/include/__format/format_args.h index 8b8fbde92fe6..defb42a4ab00 100644 --- a/libcxx/include/__format/format_args.h +++ b/libcxx/include/__format/format_args.h @@ -24,12 +24,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Context> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_args { +class _LIBCPP_TEMPLATE_VIS basic_format_args { public: - _LIBCPP_HIDE_FROM_ABI basic_format_args() noexcept = default; + basic_format_args() noexcept = default; template <class... _Args> _LIBCPP_HIDE_FROM_ABI basic_format_args(const __format_arg_store<_Context, _Args...>& __store) noexcept @@ -71,9 +71,11 @@ private: const basic_format_arg<_Context>* __args_; }; }; -_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_args); -#endif //_LIBCPP_STD_VER > 17 +template <class _Context, class... _Args> +basic_format_args(__format_arg_store<_Context, _Args...>) -> basic_format_args<_Context>; + +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/format_context.h b/libcxx/include/__format/format_context.h index 85e00eb222cf..9d50cee2483f 100644 --- a/libcxx/include/__format/format_context.h +++ b/libcxx/include/__format/format_context.h @@ -37,11 +37,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _OutIt, class _CharT> requires output_iterator<_OutIt, const _CharT&> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context; +class _LIBCPP_TEMPLATE_VIS basic_format_context; #ifndef _LIBCPP_HAS_NO_LOCALIZATION /** @@ -80,7 +80,6 @@ requires output_iterator<_OutIt, const _CharT&> class // clang-format off _LIBCPP_TEMPLATE_VIS - _LIBCPP_AVAILABILITY_FORMAT _LIBCPP_PREFERRED_NAME(format_context) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context)) // clang-format on @@ -121,9 +120,9 @@ private: // TODO FMT Validate whether lazy creation is the best solution. optional<_VSTD::locale> __loc_; - template <class __OutIt, class __CharT> - friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT> - __format_context_create(__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>, + template <class _OtherOutIt, class _OtherCharT> + friend _LIBCPP_HIDE_FROM_ABI basic_format_context<_OtherOutIt, _OtherCharT> + __format_context_create(_OtherOutIt, basic_format_args<basic_format_context<_OtherOutIt, _OtherCharT>>, optional<_VSTD::locale>&&); // Note: the Standard doesn't specify the required constructors. @@ -134,9 +133,9 @@ private: : __out_it_(_VSTD::move(__out_it)), __args_(__args), __loc_(_VSTD::move(__loc)) {} #else - template <class __OutIt, class __CharT> - friend _LIBCPP_HIDE_FROM_ABI basic_format_context<__OutIt, __CharT> - __format_context_create(__OutIt, basic_format_args<basic_format_context<__OutIt, __CharT>>); + template <class _OtherOutIt, class _OtherCharT> + friend _LIBCPP_HIDE_FROM_ABI basic_format_context<_OtherOutIt, _OtherCharT> + __format_context_create(_OtherOutIt, basic_format_args<basic_format_context<_OtherOutIt, _OtherCharT>>); _LIBCPP_HIDE_FROM_ABI explicit basic_format_context(_OutIt __out_it, @@ -162,7 +161,7 @@ private: // Here the width of an element in input is determined dynamically. // Note when the top-level element has no width the retargeting is not needed. template <class _CharT> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT +class _LIBCPP_TEMPLATE_VIS basic_format_context<typename __format::__retarget_buffer<_CharT>::__iterator, _CharT> { public: using iterator = typename __format::__retarget_buffer<_CharT>::__iterator; @@ -216,7 +215,7 @@ private: }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_context); -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/format_error.h b/libcxx/include/__format/format_error.h index 002d1a40a226..f22cb0b81ec2 100644 --- a/libcxx/include/__format/format_error.h +++ b/libcxx/include/__format/format_error.h @@ -11,7 +11,7 @@ #define _LIBCPP___FORMAT_FORMAT_ERROR_H #include <__config> -#include <cstdlib> +#include <__verbose_abort> #include <stdexcept> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -20,35 +20,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 -class _LIBCPP_EXCEPTION_ABI format_error : public runtime_error { +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables") +class _LIBCPP_EXPORTED_FROM_ABI format_error : public runtime_error { public: _LIBCPP_HIDE_FROM_ABI explicit format_error(const string& __s) : runtime_error(__s) {} _LIBCPP_HIDE_FROM_ABI explicit format_error(const char* __s) : runtime_error(__s) {} - // TODO FMT Remove when format is no longer experimental. - // Avoids linker errors when building the Clang-cl Windows DLL which doesn't - // support the experimental library. -# ifndef _LIBCPP_INLINE_FORMAT_ERROR_DTOR - ~format_error() noexcept override; -# else - ~format_error() noexcept override {} -# endif + _LIBCPP_HIDE_FROM_ABI_VIRTUAL + ~format_error() noexcept override = default; }; +_LIBCPP_DIAGNOSTIC_POP _LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI void __throw_format_error(const char* __s) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw format_error(__s); #else - (void)__s; - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("format_error was thrown in -fno-exceptions mode with message \"%s\"", __s); #endif } -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h index 185148ccba53..27ec0a295f4f 100644 --- a/libcxx/include/__format/format_functions.h +++ b/libcxx/include/__format/format_functions.h @@ -10,16 +10,10 @@ #ifndef _LIBCPP___FORMAT_FORMAT_FUNCTIONS #define _LIBCPP___FORMAT_FORMAT_FUNCTIONS -// TODO FMT This is added to fix Apple back-deployment. -#include <version> -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) - #include <__algorithm/clamp.h> -#include <__availability> #include <__concepts/convertible_to.h> #include <__concepts/same_as.h> #include <__config> -#include <__debug> #include <__format/buffer.h> #include <__format/format_arg.h> #include <__format/format_arg_store.h> @@ -38,7 +32,9 @@ #include <__format/formatter_string.h> #include <__format/parser_std_format_spec.h> #include <__iterator/back_insert_iterator.h> +#include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> // iter_value_t #include <__variant/monostate.h> #include <array> #include <string> @@ -54,7 +50,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // TODO FMT Evaluate which templates should be external templates. This // improves the efficiency of the header. However since the header is still @@ -67,16 +63,17 @@ using wformat_args = basic_format_args<wformat_context>; #endif template <class _Context = format_context, class... _Args> -_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { return _VSTD::__format_arg_store<_Context, _Args...>(__args...); } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class... _Args> -_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&&... __args) { +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> +make_wformat_args(_Args&&... __args) { return _VSTD::__format_arg_store<wformat_context, _Args...>(__args...); } -#endif +# endif namespace __format { @@ -87,14 +84,16 @@ namespace __format { template <class _CharT> class _LIBCPP_TEMPLATE_VIS __compile_time_handle { public: - _LIBCPP_HIDE_FROM_ABI - constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); } + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr void __parse(_ParseContext& __ctx) const { + __parse_(__ctx); + } template <class _Tp> _LIBCPP_HIDE_FROM_ABI constexpr void __enable() { - __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) { + __parse_ = [](basic_format_parse_context<_CharT>& __ctx) { formatter<_Tp, _CharT> __f; - __parse_ctx.advance_to(__f.parse(__parse_ctx)); + __ctx.advance_to(__f.parse(__ctx)); }; } @@ -128,13 +127,13 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const { if (__id >= __size_) - std::__throw_format_error("Argument index out of bounds"); + std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); return __args_[__id]; } _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const { if (__id >= __size_) - std::__throw_format_error("Argument index out of bounds"); + std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); return __handles_[__id]; } @@ -147,41 +146,44 @@ private: size_t __size_; }; -_LIBCPP_HIDE_FROM_ABI -constexpr void __compile_time_validate_integral(__arg_t __type) { - switch (__type) { - case __arg_t::__int: - case __arg_t::__long_long: - case __arg_t::__i128: - case __arg_t::__unsigned: - case __arg_t::__unsigned_long_long: - case __arg_t::__u128: - return; - - default: - std::__throw_format_error("Argument isn't an integral type"); - } -} - +// [format.string.std]/8 +// If { arg-idopt } is used in a width or precision, the value of the +// corresponding formatting argument is used in its place. If the +// corresponding formatting argument is not of standard signed or unsigned +// integer type, or its value is negative for precision or non-positive for +// width, an exception of type format_error is thrown. +// // _HasPrecision does the formatter have a precision? template <class _CharT, class _Tp, bool _HasPrecision = false> -_LIBCPP_HIDE_FROM_ABI constexpr void -__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx, - __compile_time_basic_format_context<_CharT>& __ctx) { +_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_validate_argument( + basic_format_parse_context<_CharT>& __parse_ctx, __compile_time_basic_format_context<_CharT>& __ctx) { + auto __validate_type = [](__arg_t __type) { + // LWG3720 originally allowed "signed or unsigned integer types", however + // the final version explicitly changed it to "*standard* signed or unsigned + // integer types". It's trivial to use 128-bit integrals in libc++'s + // implementation, but other implementations may not implement it. + // (Using a width or precision, that does not fit in 64-bits, sounds very + // unlikely in real world code.) + switch (__type) { + case __arg_t::__int: + case __arg_t::__long_long: + case __arg_t::__unsigned: + case __arg_t::__unsigned_long_long: + return; + + default: + std::__throw_format_error("Replacement argument isn't a standard signed or unsigned integer type"); + } + }; + formatter<_Tp, _CharT> __formatter; __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); - // [format.string.std]/7 - // ... If the corresponding formatting argument is not of integral type, or - // its value is negative for precision or non-positive for width, an - // exception of type format_error is thrown. - // - // Validate whether the arguments are integrals. if (__formatter.__parser_.__width_as_arg_) - __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_)); + __validate_type(__ctx.arg(__formatter.__parser_.__width_)); if constexpr (_HasPrecision) if (__formatter.__parser_.__precision_as_arg_) - __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_)); + __validate_type(__ctx.arg(__formatter.__parser_.__precision_)); } // This function is not user facing, so it can directly use the non-standard types of the "variant". @@ -236,37 +238,40 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_forma std::__throw_format_error("Invalid argument"); } -template <class _CharT, class _ParseCtx, class _Ctx> -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__handle_replacement_field(const _CharT* __begin, const _CharT* __end, +template <contiguous_iterator _Iterator, class _ParseCtx, class _Ctx> +_LIBCPP_HIDE_FROM_ABI constexpr _Iterator +__handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __parse_ctx, _Ctx& __ctx) { + using _CharT = iter_value_t<_Iterator>; __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); - bool __parse = *__r.__ptr == _CharT(':'); - switch (*__r.__ptr) { + bool __parse = *__r.__last == _CharT(':'); + switch (*__r.__last) { case _CharT(':'): // The arg-id has a format-specifier, advance the input to the format-spec. - __parse_ctx.advance_to(__r.__ptr + 1); + __parse_ctx.advance_to(__r.__last + 1); break; case _CharT('}'): // The arg-id has no format-specifier. - __parse_ctx.advance_to(__r.__ptr); + __parse_ctx.advance_to(__r.__last); break; default: - std::__throw_format_error("The replacement field arg-id should terminate at a ':' or '}'"); + std::__throw_format_error("The argument index should end with a ':' or a '}'"); } if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) { __arg_t __type = __ctx.arg(__r.__value); - if (__type == __arg_t::__handle) + if (__type == __arg_t::__none) + std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); + else if (__type == __arg_t::__handle) __ctx.__handle(__r.__value).__parse(__parse_ctx); - else - __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); + else if (__parse) + __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); } else _VSTD::__visit_format_arg( [&](auto __arg) { if constexpr (same_as<decltype(__arg), monostate>) - std::__throw_format_error("Argument index out of bounds"); + std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>) __arg.format(__parse_ctx, __ctx); else { @@ -291,8 +296,8 @@ __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { using _CharT = typename _ParseCtx::char_type; static_assert(same_as<typename _Ctx::char_type, _CharT>); - const _CharT* __begin = __parse_ctx.begin(); - const _CharT* __end = __parse_ctx.end(); + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); typename _Ctx::iterator __out_it = __ctx.out(); while (__begin != __end) { switch (*__begin) { @@ -339,7 +344,7 @@ struct _LIBCPP_TEMPLATE_VIS basic_format_string { _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept { + _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT> get() const noexcept { return __str_; } @@ -351,20 +356,6 @@ private: static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; - // TODO FMT remove this work-around when the AIX ICE has been resolved. -# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400 - template <class _Tp> - static constexpr __format::__compile_time_handle<_CharT> __get_handle() { - __format::__compile_time_handle<_CharT> __handle; - if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle) - __handle.template __enable<_Tp>(); - - return __handle; - } - - static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{ - __get_handle<_Args>()...}; -# else static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] { using _Tp = remove_cvref_t<_Args>; __format::__compile_time_handle<_CharT> __handle; @@ -373,7 +364,6 @@ private: return __handle; }()...}; -# endif }; template <class... _Args> @@ -404,21 +394,21 @@ requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt // https://reviews.llvm.org/D110499#inline-1180704 // TODO FMT Evaluate whether we want to file a Clang bug report regarding this. template <output_iterator<const char&> _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); } #endif template <output_iterator<const char&> _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), _VSTD::make_format_args(__args...)); @@ -426,42 +416,48 @@ format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string +// TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup +// fires too eagerly, see http://llvm.org/PR61563. +template <class = void> +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) { string __res; _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); return __res; } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +// TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup +// fires too eagerly, see http://llvm.org/PR61563. +template <class = void> +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(wstring_view __fmt, wformat_args __args) { wstring __res; _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); return __res; } -#endif +# endif template <class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt, - _Args&&... __args) { +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string +format(format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...)); } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...)); } -#endif +# endif template <class _Context, class _OutIt, class _CharT> _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, @@ -474,14 +470,14 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, } template <output_iterator<const char&> _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...)); @@ -497,20 +493,20 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, } template <class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); } -#endif +# endif -#ifndef _LIBCPP_HAS_NO_LOCALIZATION +# ifndef _LIBCPP_HAS_NO_LOCALIZATION template <class _OutIt, class _CharT, class _FormatOutIt> requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt @@ -531,7 +527,7 @@ requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt } template <output_iterator<const char&> _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to( _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, __args); @@ -539,7 +535,7 @@ _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt v #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to( _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, __args); @@ -547,7 +543,7 @@ _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt v #endif template <output_iterator<const char&> _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); @@ -555,14 +551,17 @@ format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&. #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string +// TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup +// fires too eagerly, see http://llvm.org/PR61563. +template <class = void> +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(locale __loc, string_view __fmt, format_args __args) { string __res; _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, @@ -570,32 +569,34 @@ vformat(locale __loc, string_view __fmt, format_args __args) { return __res; } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +// TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup +// fires too eagerly, see http://llvm.org/PR61563. +template <class = void> +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring vformat(locale __loc, wstring_view __fmt, wformat_args __args) { wstring __res; _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt, __args); return __res; } -#endif +# endif template <class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, - format_string<_Args...> __fmt, - _Args&&... __args) { +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string +format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } -#endif +# endif template <class _Context, class _OutIt, class _CharT> _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, @@ -609,7 +610,7 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, } template <output_iterator<const char&> _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), @@ -618,7 +619,7 @@ format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <output_iterator<const wchar_t&> _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), @@ -636,26 +637,23 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_ } template <class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); } -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t +_LIBCPP_NODISCARD_EXT _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); } -#endif - -#endif // _LIBCPP_HAS_NO_LOCALIZATION +# endif +# endif // _LIBCPP_HAS_NO_LOCALIZATION -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) - #endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS diff --git a/libcxx/include/__format/format_fwd.h b/libcxx/include/__format/format_fwd.h index f7c72e21211a..120b2fc8d47d 100644 --- a/libcxx/include/__format/format_fwd.h +++ b/libcxx/include/__format/format_fwd.h @@ -20,19 +20,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Context> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_arg; +class _LIBCPP_TEMPLATE_VIS basic_format_arg; template <class _OutIt, class _CharT> requires output_iterator<_OutIt, const _CharT&> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context; +class _LIBCPP_TEMPLATE_VIS basic_format_context; template <class _Tp, class _CharT = char> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter; +struct _LIBCPP_TEMPLATE_VIS formatter; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/format_parse_context.h b/libcxx/include/__format/format_parse_context.h index 30e3a7dfdaf3..79f53f77d4a0 100644 --- a/libcxx/include/__format/format_parse_context.h +++ b/libcxx/include/__format/format_parse_context.h @@ -12,6 +12,7 @@ #include <__config> #include <__format/format_error.h> +#include <__type_traits/is_constant_evaluated.h> #include <string_view> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -20,10 +21,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _CharT> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_parse_context { +class _LIBCPP_TEMPLATE_VIS basic_format_parse_context { public: using char_type = _CharT; using const_iterator = typename basic_string_view<_CharT>::const_iterator; @@ -58,6 +59,18 @@ public: if (__indexing_ == __unknown) __indexing_ = __automatic; + + // Throws an exception to make the expression a non core constant + // expression as required by: + // [format.parse.ctx]/8 + // Remarks: Let cur-arg-id be the value of next_arg_id_ prior to this + // call. Call expressions where cur-arg-id >= num_args_ is true are not + // core constant expressions (7.7 [expr.const]). + // Note: the Throws clause [format.parse.ctx]/9 doesn't specify the + // behavior when id >= num_args_. + if (is_constant_evaluated() && __next_arg_id_ >= __num_args_) + std::__throw_format_error("Argument index outside the valid range"); + return __next_arg_id_++; } _LIBCPP_HIDE_FROM_ABI constexpr void check_arg_id(size_t __id) { @@ -93,7 +106,7 @@ using format_parse_context = basic_format_parse_context<char>; using wformat_parse_context = basic_format_parse_context<wchar_t>; #endif -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/format_string.h b/libcxx/include/__format/format_string.h index d9caf866a17d..2e1c71b3d01b 100644 --- a/libcxx/include/__format/format_string.h +++ b/libcxx/include/__format/format_string.h @@ -13,6 +13,8 @@ #include <__assert> #include <__config> #include <__format/format_error.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> // iter_value_t #include <cstddef> #include <cstdint> @@ -22,22 +24,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format { -template <class _CharT> +template <contiguous_iterator _Iterator> struct _LIBCPP_TEMPLATE_VIS __parse_number_result { - const _CharT* __ptr; + _Iterator __last; uint32_t __value; }; -template <class _CharT> -__parse_number_result(const _CharT*, uint32_t) -> __parse_number_result<_CharT>; +template <contiguous_iterator _Iterator> +__parse_number_result(_Iterator, uint32_t) -> __parse_number_result<_Iterator>; -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_number(const _CharT* __begin, const _CharT* __end); +template <contiguous_iterator _Iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_number(_Iterator __begin, _Iterator __end); /** * The maximum value of a numeric argument. @@ -53,27 +55,28 @@ __parse_number(const _CharT* __begin, const _CharT* __end); inline constexpr uint32_t __number_max = INT32_MAX; namespace __detail { -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_zero(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { +template <contiguous_iterator _Iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_zero(_Iterator __begin, _Iterator, auto& __parse_ctx) { __parse_ctx.check_arg_id(0); return {++__begin, 0}; // can never be larger than the maximum. } -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_automatic(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { +template <contiguous_iterator _Iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_automatic(_Iterator __begin, _Iterator, auto& __parse_ctx) { size_t __value = __parse_ctx.next_arg_id(); - _LIBCPP_ASSERT(__value <= __number_max, - "Compilers don't support this number of arguments"); + _LIBCPP_ASSERT_UNCATEGORIZED( + __value <= __number_max, + "Compilers don't support this number of arguments"); return {__begin, uint32_t(__value)}; } -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { - __parse_number_result<_CharT> __r = __format::__parse_number(__begin, __end); +template <contiguous_iterator _Iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_manual(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { + __parse_number_result<_Iterator> __r = __format::__parse_number(__begin, __end); __parse_ctx.check_arg_id(__r.__value); return __r; } @@ -86,9 +89,10 @@ __parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { * The number is used for the 31-bit values @em width and @em precision. This * allows a maximum value of 2147483647. */ -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_number(const _CharT* __begin, const _CharT* __end_input) { +template <contiguous_iterator _Iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_number(_Iterator __begin, _Iterator __end_input) { + using _CharT = iter_value_t<_Iterator>; static_assert(__format::__number_max == INT32_MAX, "The algorithm is implemented based on this value."); /* @@ -98,7 +102,7 @@ __parse_number(const _CharT* __begin, const _CharT* __end_input) { * - Does the value exceed width of an uint32_t? (Switching to uint64_t would * have the same issue, but with a higher maximum.) */ - const _CharT* __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; + _Iterator __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; uint32_t __value = *__begin - _CharT('0'); while (++__begin != __end) { if (*__begin < _CharT('0') || *__begin > _CharT('9')) @@ -120,7 +124,7 @@ __parse_number(const _CharT* __begin, const _CharT* __end_input) { if (__v > __number_max || (__begin != __end_input && *__begin >= _CharT('0') && *__begin <= _CharT('9'))) - std::__throw_format_error("The numeric value of the format-spec is too large"); + std::__throw_format_error("The numeric value of the format specifier is too large"); __value = __v; } @@ -134,9 +138,10 @@ __parse_number(const _CharT* __begin, const _CharT* __end_input) { * The parser will return a pointer beyond the last consumed character. This * should be the closing '}' of the arg-id. */ -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> -__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { +template <contiguous_iterator _Iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> +__parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { + using _CharT = iter_value_t<_Iterator>; switch (*__begin) { case _CharT('0'): return __detail::__parse_zero(__begin, __end, __parse_ctx); @@ -149,14 +154,14 @@ __parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { return __detail::__parse_automatic(__begin, __end, __parse_ctx); } if (*__begin < _CharT('0') || *__begin > _CharT('9')) - std::__throw_format_error("The arg-id of the format-spec starts with an invalid character"); + std::__throw_format_error("The argument index starts with an invalid character"); return __detail::__parse_manual(__begin, __end, __parse_ctx); } } // namespace __format -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/format_to_n_result.h b/libcxx/include/__format/format_to_n_result.h index f1ed9a0982ab..6f30546dec08 100644 --- a/libcxx/include/__format/format_to_n_result.h +++ b/libcxx/include/__format/format_to_n_result.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _OutIt> struct _LIBCPP_TEMPLATE_VIS format_to_n_result { @@ -28,7 +28,7 @@ struct _LIBCPP_TEMPLATE_VIS format_to_n_result { }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(format_to_n_result); -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/formatter.h b/libcxx/include/__format/formatter.h index 900a09af4e99..172b2d5f7b8a 100644 --- a/libcxx/include/__format/formatter.h +++ b/libcxx/include/__format/formatter.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 /// The default formatter template. /// @@ -32,13 +32,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD /// - is_copy_assignable<F>, and /// - is_move_assignable<F>. template <class _Tp, class _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter { +struct _LIBCPP_TEMPLATE_VIS formatter { formatter() = delete; formatter(const formatter&) = delete; formatter& operator=(const formatter&) = delete; }; -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 template <class _Tp> _LIBCPP_HIDE_FROM_ABI constexpr void __set_debug_format(_Tp& __formatter) { @@ -46,8 +46,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __set_debug_format(_Tp& __formatter) { __formatter.set_debug_format(); } -# endif // _LIBCPP_STD_VER > 20 -#endif // _LIBCPP_STD_VER > 17 +# endif // _LIBCPP_STD_VER >= 23 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/formatter_bool.h b/libcxx/include/__format/formatter_bool.h index 0d005a1bee23..3c8ae95f55fa 100644 --- a/libcxx/include/__format/formatter_bool.h +++ b/libcxx/include/__format/formatter_bool.h @@ -11,17 +11,15 @@ #define _LIBCPP___FORMAT_FORMATTER_BOOL_H #include <__algorithm/copy.h> +#include <__assert> #include <__availability> #include <__config> -#include <__debug> #include <__format/concepts.h> -#include <__format/format_error.h> #include <__format/format_parse_context.h> #include <__format/formatter.h> #include <__format/formatter_integral.h> #include <__format/parser_std_format_spec.h> #include <__utility/unreachable.h> -#include <string_view> #ifndef _LIBCPP_HAS_NO_LOCALIZATION # include <locale> @@ -33,19 +31,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<bool, _CharT> { +struct _LIBCPP_TEMPLATE_VIS formatter<bool, _CharT> { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto - parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral); - __format_spec::__process_parsed_bool(__parser_); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_integral); + __format_spec::__process_parsed_bool(__parser_, "a bool"); return __result; } - _LIBCPP_HIDE_FROM_ABI auto format(bool __value, auto& __ctx) const -> decltype(__ctx.out()) { + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(bool __value, _FormatContext& __ctx) const { switch (__parser_.__type_) { case __format_spec::__type::__default: case __format_spec::__type::__string: @@ -63,7 +62,7 @@ public: static_cast<unsigned>(__value), __ctx, __parser_.__get_parsed_std_specifications(__ctx)); default: - _LIBCPP_ASSERT(false, "The parse function should have validated the type"); + _LIBCPP_ASSERT_UNCATEGORIZED(false, "The parse function should have validated the type"); __libcpp_unreachable(); } } @@ -71,7 +70,7 @@ public: __format_spec::__parser<_CharT> __parser_; }; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/formatter_char.h b/libcxx/include/__format/formatter_char.h index 8a92e7445b49..d6e61e865449 100644 --- a/libcxx/include/__format/formatter_char.h +++ b/libcxx/include/__format/formatter_char.h @@ -19,6 +19,7 @@ #include <__format/formatter_integral.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> +#include <__format/write_escaped.h> #include <__type_traits/conditional.h> #include <__type_traits/is_signed.h> @@ -28,23 +29,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_char { +struct _LIBCPP_TEMPLATE_VIS __formatter_char { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto - parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral); - __format_spec::__process_parsed_char(__parser_); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_integral); + __format_spec::__process_parsed_char(__parser_, "a character"); return __result; } - _LIBCPP_HIDE_FROM_ABI auto format(_CharT __value, auto& __ctx) const -> decltype(__ctx.out()) { + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_CharT __value, _FormatContext& __ctx) const { if (__parser_.__type_ == __format_spec::__type::__default || __parser_.__type_ == __format_spec::__type::__char) return __formatter::__format_char(__value, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 if (__parser_.__type_ == __format_spec::__type::__debug) return __formatter::__format_escaped_char(__value, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); # endif @@ -60,13 +62,14 @@ public: return __formatter::__format_integer(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx)); } - _LIBCPP_HIDE_FROM_ABI auto format(char __value, auto& __ctx) const -> decltype(__ctx.out()) + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(char __value, _FormatContext& __ctx) const requires(same_as<_CharT, wchar_t>) { return format(static_cast<wchar_t>(__value), __ctx); } -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr void set_debug_format() { __parser_.__type_ = __format_spec::__type::__debug; } # endif @@ -74,19 +77,19 @@ public: }; template <> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<char, char> : public __formatter_char<char> {}; +struct _LIBCPP_TEMPLATE_VIS formatter<char, char> : public __formatter_char<char> {}; # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<char, wchar_t> : public __formatter_char<wchar_t> {}; +struct _LIBCPP_TEMPLATE_VIS formatter<char, wchar_t> : public __formatter_char<wchar_t> {}; template <> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<wchar_t, wchar_t> : public __formatter_char<wchar_t> { +struct _LIBCPP_TEMPLATE_VIS formatter<wchar_t, wchar_t> : public __formatter_char<wchar_t> { }; # endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h index a544b53f7e6d..fbb8aa9200a7 100644 --- a/libcxx/include/__format/formatter_floating_point.h +++ b/libcxx/include/__format/formatter_floating_point.h @@ -16,6 +16,9 @@ #include <__algorithm/min.h> #include <__algorithm/rotate.h> #include <__algorithm/transform.h> +#include <__charconv/chars_format.h> +#include <__charconv/to_chars_floating_point.h> +#include <__charconv/to_chars_result.h> #include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> @@ -25,10 +28,14 @@ #include <__format/formatter_integral.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> +#include <__iterator/concepts.h> #include <__memory/allocator.h> +#include <__system_error/errc.h> +#include <__type_traits/conditional.h> #include <__utility/move.h> #include <__utility/unreachable.h> -#include <charconv> +#include <cmath> +#include <cstddef> #ifndef _LIBCPP_HAS_NO_LOCALIZATION # include <locale> @@ -43,28 +50,28 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __formatter { template <floating_point _Tp> _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value) { to_chars_result __r = _VSTD::to_chars(__first, __last, __value); - _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + _LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small"); return __r.ptr; } template <floating_point _Tp> _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt) { to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __fmt); - _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + _LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small"); return __r.ptr; } template <floating_point _Tp> _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt, int __precision) { to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __fmt, __precision); - _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + _LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small"); return __r.ptr; } @@ -246,10 +253,10 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_default(const __float_buffe __result.__radix_point = __result.__last; // clang-format off - _LIBCPP_ASSERT((__result.__integral != __result.__last) && - (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && - (__result.__exponent == __result.__last || *__result.__exponent == 'e'), - "Post-condition failure."); + _LIBCPP_ASSERT_UNCATEGORIZED((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent == __result.__last || *__result.__exponent == 'e'), + "Post-condition failure."); // clang-format on return __result; @@ -299,10 +306,10 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_lower_case(cons } // clang-format off - _LIBCPP_ASSERT((__result.__integral != __result.__last) && - (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && - (__result.__exponent != __result.__last && *__result.__exponent == 'p'), - "Post-condition failure."); + _LIBCPP_ASSERT_UNCATEGORIZED((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent != __result.__last && *__result.__exponent == 'p'), + "Post-condition failure."); // clang-format on return __result; @@ -329,7 +336,7 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_lower_case(const __formatter::__to_buffer(__integral, __buffer.end(), __value, chars_format::scientific, __precision); char* __first = __integral + 1; - _LIBCPP_ASSERT(__first != __result.__last, "No exponent present"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __result.__last, "No exponent present"); if (*__first == '.') { __result.__radix_point = __first; __result.__exponent = __formatter::__find_exponent(__first + 1, __result.__last); @@ -339,10 +346,10 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_lower_case(const } // clang-format off - _LIBCPP_ASSERT((__result.__integral != __result.__last) && - (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && - (__result.__exponent != __result.__last && *__result.__exponent == 'e'), - "Post-condition failure."); + _LIBCPP_ASSERT_UNCATEGORIZED((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent != __result.__last && *__result.__exponent == 'e'), + "Post-condition failure."); // clang-format on return __result; } @@ -372,10 +379,10 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_fixed(const __float_buffer< __result.__exponent = __result.__last; // clang-format off - _LIBCPP_ASSERT((__result.__integral != __result.__last) && - (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && - (__result.__exponent == __result.__last), - "Post-condition failure."); + _LIBCPP_ASSERT_UNCATEGORIZED((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent == __result.__last), + "Post-condition failure."); // clang-format on return __result; } @@ -404,16 +411,15 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_ // In fixed mode the algorithm truncates trailing spaces and possibly the // radix point. There's no good guess for the position of the radix point // therefore scan the output after the first digit. - __result.__radix_point = _VSTD::find(__first, __result.__last, '.'); } } // clang-format off - _LIBCPP_ASSERT((__result.__integral != __result.__last) && - (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && - (__result.__exponent == __result.__last || *__result.__exponent == 'e'), - "Post-condition failure."); + _LIBCPP_ASSERT_UNCATEGORIZED((__result.__integral != __result.__last) && + (__result.__radix_point == __result.__last || *__result.__radix_point == '.') && + (__result.__exponent == __result.__last || *__result.__exponent == 'e'), + "Post-condition failure."); // clang-format on return __result; @@ -485,7 +491,7 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer( return __formatter::__format_buffer_general_upper_case(__buffer, __value, __buffer.__precision(), __first); default: - _LIBCPP_ASSERT(false, "The parser should have validated the type"); + _LIBCPP_ASSERT_UNCATEGORIZED(false, "The parser should have validated the type"); __libcpp_unreachable(); } } @@ -523,7 +529,7 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form( if (__size < __specs.__width_) { if (__zero_padding) { __specs.__alignment_ = __format_spec::__alignment::__right; - __specs.__fill_ = _CharT('0'); + __specs.__fill_.__data[0] = _CharT('0'); } __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); @@ -603,10 +609,40 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __format_floating_point_non_finite( return __formatter::__write(__buffer, __last, _VSTD::move(__out_it), __specs); } -template <floating_point _Tp, class _CharT> -_LIBCPP_HIDE_FROM_ABI auto -__format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) - -> decltype(__ctx.out()) { +/// Writes additional zero's for the precision before the exponent. +/// This is used when the precision requested in the format string is larger +/// than the maximum precision of the floating-point type. These precision +/// digits are always 0. +/// +/// \param __exponent The location of the exponent character. +/// \param __num_trailing_zeros The number of 0's to write before the exponent +/// character. +template <class _CharT, class _ParserCharT> +_LIBCPP_HIDE_FROM_ABI auto __write_using_trailing_zeros( + const _CharT* __first, + const _CharT* __last, + output_iterator<const _CharT&> auto __out_it, + __format_spec::__parsed_specifications<_ParserCharT> __specs, + size_t __size, + const _CharT* __exponent, + size_t __num_trailing_zeros) -> decltype(__out_it) { + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT_UNCATEGORIZED(__num_trailing_zeros > 0, + "The overload not writing trailing zeros should have been used"); + + __padding_size_result __padding = + __formatter::__padding_size(__size + __num_trailing_zeros, __specs.__width_, __specs.__alignment_); + __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); + __out_it = __formatter::__copy(__first, __exponent, _VSTD::move(__out_it)); + __out_it = __formatter::__fill(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0')); + __out_it = __formatter::__copy(__exponent, __last, _VSTD::move(__out_it)); + return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); +} + + +template <floating_point _Tp, class _CharT, class _FormatContext> +_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator +__format_floating_point(_Tp __value, _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) { bool __negative = _VSTD::signbit(__value); if (!_VSTD::isfinite(__value)) [[unlikely]] @@ -665,7 +701,7 @@ __format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specif if (__result.__exponent == __result.__last) // if P > X >= -4, the conversion is with style f or F and precision P - 1 - X. // By including the radix point it calculates P - (1 + X) - __p -= __result.__radix_point - __buffer.begin(); + __p -= __result.__radix_point - __result.__integral; else // otherwise, the conversion is with style e or E and precision P - 1. --__p; @@ -708,7 +744,7 @@ __format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specif // After the sign is written, zero padding is the same a right alignment // with '0'. __specs.__alignment_ = __format_spec::__alignment::__right; - __specs.__fill_ = _CharT('0'); + __specs.__fill_.__data[0] = _CharT('0'); } if (__num_trailing_zeros) @@ -723,15 +759,15 @@ __format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specif template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS __formatter_floating_point { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto - parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_floating_point); - __format_spec::__process_parsed_floating_point(__parser_); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_floating_point); + __format_spec::__process_parsed_floating_point(__parser_, "a floating-point"); return __result; } - template <floating_point _Tp> - _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) const -> decltype(__ctx.out()) { + template <floating_point _Tp, class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_Tp __value, _FormatContext& __ctx) const { return __formatter::__format_floating_point(__value, __ctx, __parser_.__get_parsed_std_specifications(__ctx)); } @@ -739,16 +775,16 @@ public: }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<float, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<float, _CharT> : public __formatter_floating_point<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<double, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<double, _CharT> : public __formatter_floating_point<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<long double, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<long double, _CharT> : public __formatter_floating_point<_CharT> {}; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/formatter_integer.h b/libcxx/include/__format/formatter_integer.h index b4be9f9a07ce..5590bff5aa98 100644 --- a/libcxx/include/__format/formatter_integer.h +++ b/libcxx/include/__format/formatter_integer.h @@ -19,8 +19,8 @@ #include <__format/formatter_integral.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> +#include <__type_traits/is_void.h> #include <__type_traits/make_32_64_or_128_bit.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -28,28 +28,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> - struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_integer { + struct _LIBCPP_TEMPLATE_VIS __formatter_integer { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto - parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_integral); - __format_spec::__process_parsed_integer(__parser_); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_integral); + __format_spec::__process_parsed_integer(__parser_, "an integer"); return __result; } - template <integral _Tp> - _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) const -> decltype(__ctx.out()) { + template <integral _Tp, class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_Tp __value, _FormatContext& __ctx) const { __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); if (__specs.__std_.__type_ == __format_spec::__type::__char) return __formatter::__format_char(__value, __ctx.out(), __specs); using _Type = __make_32_64_or_128_bit_t<_Tp>; - static_assert(!is_same<_Type, void>::value, "unsupported integral type used in __formatter_integer::__format"); + static_assert(!is_void<_Type>::value, "unsupported integral type used in __formatter_integer::__format"); // Reduce the number of instantiation of the integer formatter return __formatter::__format_integer(static_cast<_Type>(__value), __ctx, __specs); @@ -60,47 +60,47 @@ public: // Signed integral types. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<signed char, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<signed char, _CharT> : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<short, _CharT> : public __formatter_integer<_CharT> { +struct _LIBCPP_TEMPLATE_VIS formatter<short, _CharT> : public __formatter_integer<_CharT> { }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<int, _CharT> : public __formatter_integer<_CharT> {}; +struct _LIBCPP_TEMPLATE_VIS formatter<int, _CharT> : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<long, _CharT> : public __formatter_integer<_CharT> {}; +struct _LIBCPP_TEMPLATE_VIS formatter<long, _CharT> : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<long long, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<long long, _CharT> : public __formatter_integer<_CharT> {}; # ifndef _LIBCPP_HAS_NO_INT128 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<__int128_t, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<__int128_t, _CharT> : public __formatter_integer<_CharT> {}; # endif // Unsigned integral types. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<unsigned char, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<unsigned char, _CharT> : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<unsigned short, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<unsigned short, _CharT> : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<unsigned, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<unsigned, _CharT> : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<unsigned long, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<unsigned long, _CharT> : public __formatter_integer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<unsigned long long, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<unsigned long long, _CharT> : public __formatter_integer<_CharT> {}; # ifndef _LIBCPP_HAS_NO_INT128 template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<__uint128_t, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<__uint128_t, _CharT> : public __formatter_integer<_CharT> {}; # endif -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/formatter_integral.h b/libcxx/include/__format/formatter_integral.h index fe3a06311be2..54246aa02718 100644 --- a/libcxx/include/__format/formatter_integral.h +++ b/libcxx/include/__format/formatter_integral.h @@ -10,6 +10,9 @@ #ifndef _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H #define _LIBCPP___FORMAT_FORMATTER_INTEGRAL_H +#include <__charconv/to_chars_integral.h> +#include <__charconv/to_chars_result.h> +#include <__charconv/traits.h> #include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> @@ -17,11 +20,13 @@ #include <__format/format_error.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> +#include <__system_error/errc.h> +#include <__type_traits/make_unsigned.h> #include <__utility/unreachable.h> #include <array> -#include <charconv> #include <limits> #include <string> +#include <string_view> #ifndef _LIBCPP_HAS_NO_LOCALIZATION # include <locale> @@ -36,7 +41,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __formatter { @@ -80,9 +85,9 @@ _LIBCPP_HIDE_FROM_ABI inline char* __insert_sign(char* __buf, bool __negative, _ * regardless whether the @c std::numpunct's type is @c char or @c wchar_t. */ _LIBCPP_HIDE_FROM_ABI inline string __determine_grouping(ptrdiff_t __size, const string& __grouping) { - _LIBCPP_ASSERT(!__grouping.empty() && __size > __grouping[0], - "The slow grouping formatting is used while there will be no " - "separators written"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__grouping.empty() && __size > __grouping[0], + "The slow grouping formatting is used while there will be no " + "separators written"); string __r; auto __end = __grouping.end() - 1; auto __ptr = __grouping.begin(); @@ -149,7 +154,7 @@ _LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value // TODO FMT Evaluate code overhead due to not calling the internal function // directly. (Should be zero overhead.) to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __base); - _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); + _LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small"); return __r.ptr; } @@ -198,16 +203,82 @@ consteval size_t __buffer_size() noexcept + 1; // Reserve space for the sign. } -template <unsigned_integral _Tp, class _CharT> -_LIBCPP_HIDE_FROM_ABI auto __format_integer( +template <class _OutIt, class _CharT> +_LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, const char* __begin, const char* __first, + const char* __last, string&& __grouping, _CharT __sep, + __format_spec::__parsed_specifications<_CharT> __specs) { + int __size = (__first - __begin) + // [sign][prefix] + (__last - __first) + // data + (__grouping.size() - 1); // number of separator characters + + __padding_size_result __padding = {0, 0}; + if (__specs.__alignment_ == __format_spec::__alignment::__zero_padding) { + // Write [sign][prefix]. + __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); + + if (__specs.__width_ > __size) { + // Write zero padding. + __padding.__before_ = __specs.__width_ - __size; + __out_it = __formatter::__fill(_VSTD::move(__out_it), __specs.__width_ - __size, _CharT('0')); + } + } else { + if (__specs.__width_ > __size) { + // Determine padding and write padding. + __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); + + __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); + } + // Write [sign][prefix]. + __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); + } + + auto __r = __grouping.rbegin(); + auto __e = __grouping.rend() - 1; + _LIBCPP_ASSERT_UNCATEGORIZED(__r != __e, "The slow grouping formatting is used while " + "there will be no separators written."); + // The output is divided in small groups of numbers to write: + // - A group before the first separator. + // - A separator and a group, repeated for the number of separators. + // - A group after the last separator. + // This loop achieves that process by testing the termination condition + // midway in the loop. + // + // TODO FMT This loop evaluates the loop invariant `__parser.__type != + // _Flags::_Type::__hexadecimal_upper_case` for every iteration. (This test + // happens in the __write call.) Benchmark whether making two loops and + // hoisting the invariant is worth the effort. + while (true) { + if (__specs.__std_.__type_ == __format_spec::__type::__hexadecimal_upper_case) { + __last = __first + *__r; + __out_it = __formatter::__transform(__first, __last, _VSTD::move(__out_it), __hex_to_upper); + __first = __last; + } else { + __out_it = __formatter::__copy(__first, *__r, _VSTD::move(__out_it)); + __first += *__r; + } + + if (__r == __e) + break; + + ++__r; + *__out_it++ = __sep; + } + + return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); +} + + + +template <unsigned_integral _Tp, class _CharT, class _FormatContext> +_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator __format_integer( _Tp __value, - auto& __ctx, + _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs, bool __negative, char* __begin, char* __end, const char* __prefix, - int __base) -> decltype(__ctx.out()) { + int __base) { char* __first = __formatter::__insert_sign(__begin, __negative, __specs.__std_.__sign_); if (__specs.__std_.__alternate_form_ && __prefix) while (*__prefix) @@ -246,7 +317,7 @@ _LIBCPP_HIDE_FROM_ABI auto __format_integer( // - Write data right aligned with '0' as fill character. __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); __specs.__alignment_ = __format_spec::__alignment::__right; - __specs.__fill_ = _CharT('0'); + __specs.__fill_.__data[0] = _CharT('0'); int32_t __size = __first - __begin; __specs.__width_ -= _VSTD::min(__size, __specs.__width_); @@ -258,10 +329,12 @@ _LIBCPP_HIDE_FROM_ABI auto __format_integer( return __formatter::__write_transformed(__first, __last, __ctx.out(), __specs, __formatter::__hex_to_upper); } -template <unsigned_integral _Tp, class _CharT> -_LIBCPP_HIDE_FROM_ABI auto __format_integer( - _Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs, bool __negative = false) - -> decltype(__ctx.out()) { +template <unsigned_integral _Tp, class _CharT, class _FormatContext> +_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator +__format_integer(_Tp __value, + _FormatContext& __ctx, + __format_spec::__parsed_specifications<_CharT> __specs, + bool __negative = false) { switch (__specs.__std_.__type_) { case __format_spec::__type::__binary_lower_case: { array<char, __formatter::__buffer_size<decltype(__value), 2>()> __array; @@ -292,15 +365,14 @@ _LIBCPP_HIDE_FROM_ABI auto __format_integer( return __formatter::__format_integer(__value, __ctx, __specs, __negative, __array.begin(), __array.end(), "0X", 16); } default: - _LIBCPP_ASSERT(false, "The parse function should have validated the type"); + _LIBCPP_ASSERT_UNCATEGORIZED(false, "The parse function should have validated the type"); __libcpp_unreachable(); } } -template <signed_integral _Tp, class _CharT> -_LIBCPP_HIDE_FROM_ABI auto -__format_integer(_Tp __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) - -> decltype(__ctx.out()) { +template <signed_integral _Tp, class _CharT, class _FormatContext> +_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator +__format_integer(_Tp __value, _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) { // Depending on the std-format-spec string the sign and the value // might not be outputted together: // - alternate form may insert a prefix string. @@ -336,10 +408,9 @@ struct _LIBCPP_TEMPLATE_VIS __bool_strings<wchar_t> { }; # endif -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI auto -__format_bool(bool __value, auto& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) - -> decltype(__ctx.out()) { +template <class _CharT, class _FormatContext> +_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator +__format_bool(bool __value, _FormatContext& __ctx, __format_spec::__parsed_specifications<_CharT> __specs) { # ifndef _LIBCPP_HAS_NO_LOCALIZATION if (__specs.__std_.__locale_specific_form_) { const auto& __np = std::use_facet<numpunct<_CharT>>(__ctx.locale()); @@ -354,7 +425,7 @@ __format_bool(bool __value, auto& __ctx, __format_spec::__parsed_specifications< } // namespace __formatter -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/formatter_output.h b/libcxx/include/__format/formatter_output.h index 467692559ce9..072305b6dbca 100644 --- a/libcxx/include/__format/formatter_output.h +++ b/libcxx/include/__format/formatter_output.h @@ -13,22 +13,21 @@ #include <__algorithm/ranges_copy.h> #include <__algorithm/ranges_fill_n.h> #include <__algorithm/ranges_transform.h> -#include <__chrono/statically_widen.h> +#include <__bit/countl.h> #include <__concepts/same_as.h> #include <__config> #include <__format/buffer.h> #include <__format/concepts.h> -#include <__format/escaped_output_table.h> #include <__format/formatter.h> #include <__format/parser_std_format_spec.h> #include <__format/unicode.h> #include <__iterator/back_insert_iterator.h> -#include <__type_traits/make_unsigned.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> // iter_value_t +#include <__memory/addressof.h> #include <__utility/move.h> #include <__utility/unreachable.h> -#include <charconv> #include <cstddef> -#include <string> #include <string_view> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -37,7 +36,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __formatter { @@ -59,15 +58,15 @@ _LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char __c) { return __c; } -struct _LIBCPP_TYPE_VIS __padding_size_result { +struct _LIBCPP_EXPORTED_FROM_ABI __padding_size_result { size_t __before_; size_t __after_; }; _LIBCPP_HIDE_FROM_ABI constexpr __padding_size_result __padding_size(size_t __size, size_t __width, __format_spec::__alignment __align) { - _LIBCPP_ASSERT(__width > __size, "don't call this function when no padding is required"); - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_UNCATEGORIZED(__width > __size, "don't call this function when no padding is required"); + _LIBCPP_ASSERT_UNCATEGORIZED( __align != __format_spec::__alignment::__zero_padding, "the caller should have handled the zero-padding"); size_t __fill = __width - __size; @@ -161,69 +160,45 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, _CharT __value) } } -template <class _OutIt, class _CharT> -_LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, const char* __begin, const char* __first, - const char* __last, string&& __grouping, _CharT __sep, - __format_spec::__parsed_specifications<_CharT> __specs) { - int __size = (__first - __begin) + // [sign][prefix] - (__last - __first) + // data - (__grouping.size() - 1); // number of separator characters - - __padding_size_result __padding = {0, 0}; - if (__specs.__alignment_ == __format_spec::__alignment::__zero_padding) { - // Write [sign][prefix]. - __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); - - if (__specs.__width_ > __size) { - // Write zero padding. - __padding.__before_ = __specs.__width_ - __size; - __out_it = __formatter::__fill(_VSTD::move(__out_it), __specs.__width_ - __size, _CharT('0')); - } - } else { - if (__specs.__width_ > __size) { - // Determine padding and write padding. - __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_); - - __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); - } - // Write [sign][prefix]. - __out_it = __formatter::__copy(__begin, __first, _VSTD::move(__out_it)); - } +# ifndef _LIBCPP_HAS_NO_UNICODE +template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt> + requires(same_as<_CharT, char>) +_LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { + std::size_t __bytes = std::countl_one(static_cast<unsigned char>(__value.__data[0])); + if (__bytes == 0) + return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]); + + for (size_t __i = 0; __i < __n; ++__i) + __out_it = __formatter::__copy( + std::addressof(__value.__data[0]), std::addressof(__value.__data[0]) + __bytes, std::move(__out_it)); + return __out_it; +} - auto __r = __grouping.rbegin(); - auto __e = __grouping.rend() - 1; - _LIBCPP_ASSERT(__r != __e, "The slow grouping formatting is used while " - "there will be no separators written."); - // The output is divided in small groups of numbers to write: - // - A group before the first separator. - // - A separator and a group, repeated for the number of separators. - // - A group after the last separator. - // This loop achieves that process by testing the termination condition - // midway in the loop. - // - // TODO FMT This loop evaluates the loop invariant `__parser.__type != - // _Flags::_Type::__hexadecimal_upper_case` for every iteration. (This test - // happens in the __write call.) Benchmark whether making two loops and - // hoisting the invariant is worth the effort. - while (true) { - if (__specs.__std_.__type_ == __format_spec::__type::__hexadecimal_upper_case) { - __last = __first + *__r; - __out_it = __formatter::__transform(__first, __last, _VSTD::move(__out_it), __hex_to_upper); - __first = __last; - } else { - __out_it = __formatter::__copy(__first, *__r, _VSTD::move(__out_it)); - __first += *__r; - } - - if (__r == __e) - break; - - ++__r; - *__out_it++ = __sep; - } +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt> + requires(same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) +_LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { + if (!__unicode::__is_high_surrogate(__value.__data[0])) + return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]); + + for (size_t __i = 0; __i < __n; ++__i) + __out_it = __formatter::__copy( + std::addressof(__value.__data[0]), std::addressof(__value.__data[0]) + 2, std::move(__out_it)); + return __out_it; +} - return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); +template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt> + requires(same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4) +_LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { + return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]); } +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS +# else // _LIBCPP_HAS_NO_UNICODE +template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt> +_LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) { + return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]); +} +# endif // _LIBCPP_HAS_NO_UNICODE /// Writes the input to the output with the required padding. /// @@ -261,27 +236,27 @@ __write(basic_string_view<_CharT> __str, return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); } -template <class _CharT, class _ParserCharT> +template <contiguous_iterator _Iterator, class _ParserCharT> _LIBCPP_HIDE_FROM_ABI auto -__write(const _CharT* __first, - const _CharT* __last, - output_iterator<const _CharT&> auto __out_it, +__write(_Iterator __first, + _Iterator __last, + output_iterator<const iter_value_t<_Iterator>&> auto __out_it, __format_spec::__parsed_specifications<_ParserCharT> __specs, ptrdiff_t __size) -> decltype(__out_it) { - _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "Not a valid range"); return __formatter::__write(basic_string_view{__first, __last}, _VSTD::move(__out_it), __specs, __size); } /// \overload /// /// Calls the function above where \a __size = \a __last - \a __first. -template <class _CharT, class _ParserCharT> +template <contiguous_iterator _Iterator, class _ParserCharT> _LIBCPP_HIDE_FROM_ABI auto -__write(const _CharT* __first, - const _CharT* __last, - output_iterator<const _CharT&> auto __out_it, +__write(_Iterator __first, + _Iterator __last, + output_iterator<const iter_value_t<_Iterator>&> auto __out_it, __format_spec::__parsed_specifications<_ParserCharT> __specs) -> decltype(__out_it) { - _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "Not a valid range"); return __formatter::__write(__first, __last, _VSTD::move(__out_it), __specs, __last - __first); } @@ -290,7 +265,7 @@ _LIBCPP_HIDE_FROM_ABI auto __write_transformed(const _CharT* __first, const _Cha output_iterator<const _CharT&> auto __out_it, __format_spec::__parsed_specifications<_ParserCharT> __specs, _UnaryOperation __op) -> decltype(__out_it) { - _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); + _LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "Not a valid range"); ptrdiff_t __size = __last - __first; if (__size >= __specs.__width_) @@ -302,35 +277,6 @@ _LIBCPP_HIDE_FROM_ABI auto __write_transformed(const _CharT* __first, const _Cha return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); } -/// Writes additional zero's for the precision before the exponent. -/// This is used when the precision requested in the format string is larger -/// than the maximum precision of the floating-point type. These precision -/// digits are always 0. -/// -/// \param __exponent The location of the exponent character. -/// \param __num_trailing_zeros The number of 0's to write before the exponent -/// character. -template <class _CharT, class _ParserCharT> -_LIBCPP_HIDE_FROM_ABI auto __write_using_trailing_zeros( - const _CharT* __first, - const _CharT* __last, - output_iterator<const _CharT&> auto __out_it, - __format_spec::__parsed_specifications<_ParserCharT> __specs, - size_t __size, - const _CharT* __exponent, - size_t __num_trailing_zeros) -> decltype(__out_it) { - _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); - _LIBCPP_ASSERT(__num_trailing_zeros > 0, "The overload not writing trailing zeros should have been used"); - - __padding_size_result __padding = - __formatter::__padding_size(__size + __num_trailing_zeros, __specs.__width_, __specs.__alignment_); - __out_it = __formatter::__fill(_VSTD::move(__out_it), __padding.__before_, __specs.__fill_); - __out_it = __formatter::__copy(__first, __exponent, _VSTD::move(__out_it)); - __out_it = __formatter::__fill(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0')); - __out_it = __formatter::__copy(__exponent, __last, _VSTD::move(__out_it)); - return __formatter::__fill(_VSTD::move(__out_it), __padding.__after_, __specs.__fill_); -} - /// Writes a string using format's width estimation algorithm. /// /// \pre !__specs.__has_precision() @@ -342,7 +288,7 @@ _LIBCPP_HIDE_FROM_ABI auto __write_string_no_precision( basic_string_view<_CharT> __str, output_iterator<const _CharT&> auto __out_it, __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { - _LIBCPP_ASSERT(!__specs.__has_precision(), "use __write_string"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__specs.__has_precision(), "use __write_string"); // No padding -> copy the string if (!__specs.__has_width()) @@ -359,211 +305,15 @@ _LIBCPP_HIDE_FROM_ABI auto __write_string_no_precision( template <class _CharT> _LIBCPP_HIDE_FROM_ABI int __truncate(basic_string_view<_CharT>& __str, int __precision) { - __format_spec::__column_width_result<_CharT> __result = + __format_spec::__column_width_result __result = __format_spec::__estimate_column_width(__str, __precision, __format_spec::__column_width_rounding::__down); __str = basic_string_view<_CharT>{__str.begin(), __result.__last_}; return __result.__width_; } -/// Writes a string using format's width estimation algorithm. -/// -/// \note When \c _LIBCPP_HAS_NO_UNICODE is defined the function assumes the -/// input is ASCII. -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI auto __write_string( - basic_string_view<_CharT> __str, - output_iterator<const _CharT&> auto __out_it, - __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { - if (!__specs.__has_precision()) - return __formatter::__write_string_no_precision(__str, _VSTD::move(__out_it), __specs); - - int __size = __formatter::__truncate(__str, __specs.__precision_); - - return __formatter::__write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __size); -} - -# if _LIBCPP_STD_VER > 20 - -struct __nul_terminator {}; - -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI bool operator==(const _CharT* __cstr, __nul_terminator) { - return *__cstr == _CharT('\0'); -} - -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI void -__write_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value, const _CharT* __prefix) { - back_insert_iterator __out_it{__str}; - std::ranges::copy(__prefix, __nul_terminator{}, __out_it); - - char __buffer[8]; - to_chars_result __r = std::to_chars(std::begin(__buffer), std::end(__buffer), __value, 16); - _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small"); - std::ranges::copy(std::begin(__buffer), __r.ptr, __out_it); - - __str += _CharT('}'); -} - -// [format.string.escaped]/2.2.1.2 -// ... -// then the sequence \u{hex-digit-sequence} is appended to E, where -// hex-digit-sequence is the shortest hexadecimal representation of C using -// lower-case hexadecimal digits. -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI void __write_well_formed_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value) { - __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\u{")); -} - -// [format.string.escaped]/2.2.3 -// Otherwise (X is a sequence of ill-formed code units), each code unit U is -// appended to E in order as the sequence \x{hex-digit-sequence}, where -// hex-digit-sequence is the shortest hexadecimal representation of U using -// lower-case hexadecimal digits. -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI void __write_escape_ill_formed_code_unit(basic_string<_CharT>& __str, char32_t __value) { - __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\x{")); -} - -template <class _CharT> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value) { -# ifdef _LIBCPP_HAS_NO_UNICODE - // For ASCII assume everything above 127 is printable. - if (__value > 127) - return false; -# endif - - if (!__escaped_output_table::__needs_escape(__value)) - return false; - - __formatter::__write_well_formed_escaped_code_unit(__str, __value); - return true; -} - -template <class _CharT> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr char32_t __to_char32(_CharT __value) { - return static_cast<make_unsigned_t<_CharT>>(__value); -} - -enum class _LIBCPP_ENUM_VIS __escape_quotation_mark { __apostrophe, __double_quote }; - -// [format.string.escaped]/2 -template <class _CharT> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool -__is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value, __escape_quotation_mark __mark) { - // 2.2.1.1 - Mapped character in [tab:format.escape.sequences] - switch (__value) { - case _CharT('\t'): - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\t"); - return true; - case _CharT('\n'): - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\n"); - return true; - case _CharT('\r'): - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\r"); - return true; - case _CharT('\''): - if (__mark == __escape_quotation_mark::__apostrophe) - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\')"); - else - __str += __value; - return true; - case _CharT('"'): - if (__mark == __escape_quotation_mark::__double_quote) - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\")"); - else - __str += __value; - return true; - case _CharT('\\'): - __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\\)"); - return true; - - // 2.2.1.2 - Space - case _CharT(' '): - __str += __value; - return true; - } - - // 2.2.2 - // Otherwise, if X is a shift sequence, the effect on E and further - // decoding of S is unspecified. - // For now shift sequences are ignored and treated as Unicode. Other parts - // of the format library do the same. It's unknown how ostream treats them. - // TODO FMT determine what to do with shift sequences. - - // 2.2.1.2.1 and 2.2.1.2.2 - Escape - return __formatter::__is_escaped_sequence_written(__str, __formatter::__to_char32(__value)); -} - -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI void -__escape(basic_string<_CharT>& __str, basic_string_view<_CharT> __values, __escape_quotation_mark __mark) { - __unicode::__code_point_view<_CharT> __view{__values.begin(), __values.end()}; - - while (!__view.__at_end()) { - const _CharT* __first = __view.__position(); - typename __unicode::__consume_p2286_result __result = __view.__consume_p2286(); - if (__result.__ill_formed_size == 0) { - if (!__formatter::__is_escaped_sequence_written(__str, __result.__value, __mark)) - // 2.2.1.3 - Add the character - ranges::copy(__first, __view.__position(), std::back_insert_iterator(__str)); - - } else { - // 2.2.3 sequence of ill-formed code units - // The number of code-units in __result.__value depends on the character type being used. - if constexpr (sizeof(_CharT) == 1) { - _LIBCPP_ASSERT(__result.__ill_formed_size == 1 || __result.__ill_formed_size == 4, - "illegal number of invalid code units."); - if (__result.__ill_formed_size == 1) // ill-formed, one code unit - __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value & 0xff); - else { // out of valid range, four code units - // The code point was properly encoded, decode the value. - __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value >> 18 | 0xf0); - __formatter::__write_escape_ill_formed_code_unit(__str, (__result.__value >> 12 & 0x3f) | 0x80); - __formatter::__write_escape_ill_formed_code_unit(__str, (__result.__value >> 6 & 0x3f) | 0x80); - __formatter::__write_escape_ill_formed_code_unit(__str, (__result.__value & 0x3f) | 0x80); - } - } else if constexpr (sizeof(_CharT) == 2) { - _LIBCPP_ASSERT(__result.__ill_formed_size == 1, "for UTF-16 at most one invalid code unit"); - __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value & 0xffff); - } else { - static_assert(sizeof(_CharT) == 4, "unsupported character width"); - _LIBCPP_ASSERT(__result.__ill_formed_size == 1, "for UTF-32 one code unit is one code point"); - __formatter::__write_escape_ill_formed_code_unit(__str, __result.__value); - } - } - } -} - -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI auto -__format_escaped_char(_CharT __value, - output_iterator<const _CharT&> auto __out_it, - __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { - basic_string<_CharT> __str; - __str += _CharT('\''); - __formatter::__escape(__str, basic_string_view{std::addressof(__value), 1}, __escape_quotation_mark::__apostrophe); - __str += _CharT('\''); - return __formatter::__write(__str.data(), __str.data() + __str.size(), _VSTD::move(__out_it), __specs, __str.size()); -} - -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI auto -__format_escaped_string(basic_string_view<_CharT> __values, - output_iterator<const _CharT&> auto __out_it, - __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { - basic_string<_CharT> __str; - __str += _CharT('"'); - __formatter::__escape(__str, __values, __escape_quotation_mark::__double_quote); - __str += _CharT('"'); - return __formatter::__write_string(basic_string_view{__str}, _VSTD::move(__out_it), __specs); -} - -# endif // _LIBCPP_STD_VER > 20 - } // namespace __formatter -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/formatter_pointer.h b/libcxx/include/__format/formatter_pointer.h index 31b49e17ab47..a2212611df48 100644 --- a/libcxx/include/__format/formatter_pointer.h +++ b/libcxx/include/__format/formatter_pointer.h @@ -27,24 +27,27 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS __formatter_pointer { public: - constexpr __formatter_pointer() { __parser_.__alignment_ = __format_spec::__alignment::__right; } - - _LIBCPP_HIDE_FROM_ABI constexpr auto - parse(basic_format_parse_context<_CharT>& __parse_ctx) -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_pointer); - __format_spec::__process_display_type_pointer(__parser_.__type_); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_pointer); + __format_spec::__process_display_type_pointer(__parser_.__type_, "a pointer"); return __result; } - _LIBCPP_HIDE_FROM_ABI auto format(const void* __ptr, auto& __ctx) const -> decltype(__ctx.out()) { + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const void* __ptr, _FormatContext& __ctx) const { __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); __specs.__std_.__alternate_form_ = true; - __specs.__std_.__type_ = __format_spec::__type::__hexadecimal_lower_case; + __specs.__std_.__type_ = + __specs.__std_.__type_ == __format_spec::__type::__pointer_upper_case + ? __format_spec::__type::__hexadecimal_upper_case + : __format_spec::__type::__hexadecimal_lower_case; + return __formatter::__format_integer(reinterpret_cast<uintptr_t>(__ptr), __ctx, __specs); } @@ -57,16 +60,16 @@ public: // - template<> struct formatter<void*, charT>; // - template<> struct formatter<const void*, charT>; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<nullptr_t, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<nullptr_t, _CharT> : public __formatter_pointer<_CharT> {}; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<void*, _CharT> : public __formatter_pointer<_CharT> { +struct _LIBCPP_TEMPLATE_VIS formatter<void*, _CharT> : public __formatter_pointer<_CharT> { }; template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<const void*, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<const void*, _CharT> : public __formatter_pointer<_CharT> {}; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/formatter_string.h b/libcxx/include/__format/formatter_string.h index 606fb792499c..ba64a64af80a 100644 --- a/libcxx/include/__format/formatter_string.h +++ b/libcxx/include/__format/formatter_string.h @@ -17,7 +17,7 @@ #include <__format/formatter.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> -#include <__utility/move.h> +#include <__format/write_escaped.h> #include <string> #include <string_view> @@ -27,20 +27,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS __formatter_string { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto parse(basic_format_parse_context<_CharT>& __parse_ctx) - -> decltype(__parse_ctx.begin()) { - auto __result = __parser_.__parse(__parse_ctx, __format_spec::__fields_string); + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_string); __format_spec::__process_display_type_string(__parser_.__type_); return __result; } - _LIBCPP_HIDE_FROM_ABI auto format(basic_string_view<_CharT> __str, auto& __ctx) const -> decltype(__ctx.out()) { -# if _LIBCPP_STD_VER > 20 + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(basic_string_view<_CharT> __str, _FormatContext& __ctx) const { +# if _LIBCPP_STD_VER >= 23 if (__parser_.__type_ == __format_spec::__type::__debug) return __formatter::__format_escaped_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); # endif @@ -48,7 +50,7 @@ public: return __formatter::__write_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); } -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr void set_debug_format() { __parser_.__type_ = __format_spec::__type::__debug; } # endif @@ -57,16 +59,17 @@ public: // Formatter const char*. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<const _CharT*, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<const _CharT*, _CharT> : public __formatter_string<_CharT> { using _Base = __formatter_string<_CharT>; - _LIBCPP_HIDE_FROM_ABI auto format(const _CharT* __str, auto& __ctx) const -> decltype(__ctx.out()) { - _LIBCPP_ASSERT(__str, "The basic_format_arg constructor should have " - "prevented an invalid pointer."); + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _CharT* __str, _FormatContext& __ctx) const { + _LIBCPP_ASSERT_UNCATEGORIZED(__str, "The basic_format_arg constructor should have " + "prevented an invalid pointer."); __format_spec::__parsed_specifications<_CharT> __specs = _Base::__parser_.__get_parsed_std_specifications(__ctx); -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 if (_Base::__parser_.__type_ == __format_spec::__type::__debug) return __formatter::__format_escaped_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); # endif @@ -95,45 +98,38 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<const _CharT*, // Formatter char*. template <__fmt_char_type _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_CharT*, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter<const _CharT*, _CharT> { using _Base = formatter<const _CharT*, _CharT>; - _LIBCPP_HIDE_FROM_ABI auto format(_CharT* __str, auto& __ctx) const -> decltype(__ctx.out()) { + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_CharT* __str, _FormatContext& __ctx) const { return _Base::format(__str, __ctx); } }; // Formatter char[]. template <__fmt_char_type _CharT, size_t _Size> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_CharT[_Size], _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatter_string<_CharT> { using _Base = __formatter_string<_CharT>; - _LIBCPP_HIDE_FROM_ABI auto format(_CharT __str[_Size], auto& __ctx) const -> decltype(__ctx.out()) { - return _Base::format(basic_string_view<_CharT>(__str, _Size), __ctx); - } -}; - -// Formatter const char[]. -template <__fmt_char_type _CharT, size_t _Size> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<const _CharT[_Size], _CharT> - : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; - - _LIBCPP_HIDE_FROM_ABI auto format(const _CharT __str[_Size], auto& __ctx) const -> decltype(__ctx.out()) { + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(const _CharT (&__str)[_Size], _FormatContext& __ctx) const { return _Base::format(basic_string_view<_CharT>(__str, _Size), __ctx); } }; // Formatter std::string. template <__fmt_char_type _CharT, class _Traits, class _Allocator> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT> : public __formatter_string<_CharT> { using _Base = __formatter_string<_CharT>; - _LIBCPP_HIDE_FROM_ABI auto format(const basic_string<_CharT, _Traits, _Allocator>& __str, auto& __ctx) const - -> decltype(__ctx.out()) { + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(const basic_string<_CharT, _Traits, _Allocator>& __str, _FormatContext& __ctx) const { // Drop _Traits and _Allocator to have one std::basic_string formatter. return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx); } @@ -141,18 +137,19 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<basic_string<_ // Formatter std::string_view. template <__fmt_char_type _CharT, class _Traits> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<basic_string_view<_CharT, _Traits>, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<basic_string_view<_CharT, _Traits>, _CharT> : public __formatter_string<_CharT> { using _Base = __formatter_string<_CharT>; - _LIBCPP_HIDE_FROM_ABI auto format(basic_string_view<_CharT, _Traits> __str, auto& __ctx) const - -> decltype(__ctx.out()) { + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(basic_string_view<_CharT, _Traits> __str, _FormatContext& __ctx) const { // Drop _Traits to have one std::basic_string_view formatter. return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx); } }; -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/formatter_tuple.h b/libcxx/include/__format/formatter_tuple.h index 82f5ada6e012..030097a8797d 100644 --- a/libcxx/include/__format/formatter_tuple.h +++ b/libcxx/include/__format/formatter_tuple.h @@ -11,18 +11,16 @@ #define _LIBCPP___FORMAT_FORMATTER_TUPLE_H #include <__algorithm/ranges_copy.h> -#include <__availability> #include <__chrono/statically_widen.h> #include <__config> +#include <__format/buffer.h> #include <__format/concepts.h> -#include <__format/format_args.h> #include <__format/format_context.h> #include <__format/format_error.h> #include <__format/format_parse_context.h> #include <__format/formatter.h> #include <__format/formatter_output.h> #include <__format/parser_std_format_spec.h> -#include <__iterator/back_insert_iterator.h> #include <__type_traits/remove_cvref.h> #include <__utility/integer_sequence.h> #include <__utility/pair.h> @@ -35,49 +33,52 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <__fmt_char_type _CharT, class _Tuple, formattable<_CharT>... _Args> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_tuple { - _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { +struct _LIBCPP_TEMPLATE_VIS __formatter_tuple { + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept { __separator_ = __separator; } _LIBCPP_HIDE_FROM_ABI constexpr void - set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) noexcept { __opening_bracket_ = __opening_bracket; __closing_bracket_ = __closing_bracket; } template <class _ParseContext> - _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __parse_ctx) { - const _CharT* __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_tuple); + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + auto __begin = __parser_.__parse(__ctx, __format_spec::__fields_tuple); - // [format.tuple]/7 - // ... For each element e in underlying_, if e.set_debug_format() - // is a valid expression, calls e.set_debug_format(). - // TODO FMT this can be removed when P2733 is accepted. - std::__for_each_index_sequence(make_index_sequence<sizeof...(_Args)>(), [&]<size_t _Index> { - std::__set_debug_format(std::get<_Index>(__underlying_)); - }); - - const _CharT* __end = __parse_ctx.end(); - if (__begin == __end) - return __begin; - - if (*__begin == _CharT('m')) { + auto __end = __ctx.end(); + // Note 'n' is part of the type here + if (__parser_.__clear_brackets_) + set_brackets({}, {}); + else if (__begin != __end && *__begin == _CharT('m')) { if constexpr (sizeof...(_Args) == 2) { set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ": ")); set_brackets({}, {}); ++__begin; } else - std::__throw_format_error("The format specifier m requires a pair or a two-element tuple"); - } else if (*__begin == _CharT('n')) { - set_brackets({}, {}); - ++__begin; + std::__throw_format_error("Type m requires a pair or a tuple with two elements"); } if (__begin != __end && *__begin != _CharT('}')) - std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + std::__throw_format_error("The format specifier should consume the input or end with a '}'"); + + __ctx.advance_to(__begin); + + // [format.tuple]/7 + // ... For each element e in underlying_, if e.set_debug_format() + // is a valid expression, calls e.set_debug_format(). + std::__for_each_index_sequence(make_index_sequence<sizeof...(_Args)>(), [&]<size_t _Index> { + auto& __formatter = std::get<_Index>(__underlying_); + __formatter.parse(__ctx); + // Unlike the range_formatter we don't guard against evil parsers. Since + // this format-spec never has a format-spec for the underlying type + // adding the test would give additional overhead. + std::__set_debug_format(__formatter); + }); return __begin; } @@ -91,26 +92,25 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_tuple { if (!__specs.__has_width()) return __format_tuple(__tuple, __ctx); - basic_string<_CharT> __str; - - // Since the output is written to a different iterator a new context is - // created. Since the underlying formatter uses the default formatting it - // doesn't need a locale or the formatting arguments. So creating a new - // context works. - // - // This solution works for this formatter, but it will not work for the - // range_formatter. In that patch a generic solution is work in progress. - // Once that is finished it can be used here. (The range_formatter will use - // these features so it's easier to add it there and then port it.) - // - // TODO FMT Use formatting wrapping used in the range_formatter. - basic_format_context __c = std::__format_context_create( - back_insert_iterator{__str}, - basic_format_args<basic_format_context<back_insert_iterator<basic_string<_CharT>>, _CharT>>{}); + // The size of the buffer needed is: + // - open bracket characters + // - close bracket character + // - n elements where every element may have a different size + // - (n -1) separators + // The size of the element is hard to predict, knowing the type helps but + // it depends on the format-spec. As an initial estimate we guess 6 + // characters. + // Typically both brackets are 1 character and the separator is 2 + // characters. Which means there will be + // (n - 1) * 2 + 1 + 1 = n * 2 character + // So estimate 8 times the range size as buffer. + __format::__retarget_buffer<_CharT> __buffer{8 * tuple_size_v<_Tuple>}; + basic_format_context<typename __format::__retarget_buffer<_CharT>::__iterator, _CharT> __c{ + __buffer.__make_output_iterator(), __ctx}; __format_tuple(__tuple, __c); - return __formatter::__write_string_no_precision(basic_string_view{__str}, __ctx.out(), __specs); + return __formatter::__write_string_no_precision(basic_string_view{__buffer.__view()}, __ctx.out(), __specs); } template <class _FormatContext> @@ -120,35 +120,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_tuple { std::__for_each_index_sequence(make_index_sequence<sizeof...(_Args)>(), [&]<size_t _Index> { if constexpr (_Index) __ctx.advance_to(std::ranges::copy(__separator_, __ctx.out()).out); - - // During review Victor suggested to make the exposition only - // __underlying_ member a local variable. Currently the Standard - // requires nested debug-enabled formatter specializations not to - // output escaped output. P2733 fixes that bug, once accepted the - // code below can be used. - // (Note when a paper allows parsing a tuple-underlying-spec the - // exposition only member needs to be a class member. Earlier - // revisions of P2286 proposed that, but this was not pursued, - // due to time constrains and complexity of the matter.) - // TODO FMT This can be updated after P2733 is accepted. -# if 0 - // P2286 uses an exposition only member in the formatter - // tuple<formatter<remove_cvref_t<_Args>, _CharT>...> __underlying_; - // This was used in earlier versions of the paper since - // __underlying_.parse(...) was called. This is no longer the case - // so we can reduce the scope of the formatter. - // - // It does require the underlying's parse effect to be moved here too. - using _Arg = tuple_element<_Index, decltype(__tuple)>; - formatter<remove_cvref_t<_Args>, _CharT> __underlying; - - // [format.tuple]/7 - // ... For each element e in underlying_, if e.set_debug_format() - // is a valid expression, calls e.set_debug_format(). - std::__set_debug_format(__underlying); -# else __ctx.advance_to(std::get<_Index>(__underlying_).format(std::get<_Index>(__tuple), __ctx)); -# endif }); return std::ranges::copy(__closing_bracket_, __ctx.out()).out; @@ -164,14 +136,14 @@ private: }; template <__fmt_char_type _CharT, formattable<_CharT>... _Args> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<pair<_Args...>, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<pair<_Args...>, _CharT> : public __formatter_tuple<_CharT, pair<_Args...>, _Args...> {}; template <__fmt_char_type _CharT, formattable<_CharT>... _Args> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<tuple<_Args...>, _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<tuple<_Args...>, _CharT> : public __formatter_tuple<_CharT, tuple<_Args...>, _Args...> {}; -#endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h index c03cec979636..c01e5866a431 100644 --- a/libcxx/include/__format/parser_std_format_spec.h +++ b/libcxx/include/__format/parser_std_format_spec.h @@ -16,23 +16,28 @@ /// This header has some support for the chrono-format-spec since it doesn't /// affect the std-format-spec. -#include <__algorithm/find_if.h> +#include <__algorithm/copy_n.h> #include <__algorithm/min.h> #include <__assert> #include <__concepts/arithmetic.h> #include <__concepts/same_as.h> #include <__config> -#include <__debug> #include <__format/format_arg.h> #include <__format/format_error.h> #include <__format/format_parse_context.h> #include <__format/format_string.h> #include <__format/unicode.h> +#include <__format/width_estimation_table.h> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> // iter_value_t +#include <__memory/addressof.h> +#include <__type_traits/common_type.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_trivially_copyable.h> #include <__variant/monostate.h> -#include <bit> #include <cstdint> +#include <string> #include <string_view> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -43,24 +48,36 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __format_spec { -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result< _CharT> -__parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { +_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void +__throw_invalid_option_format_error(const char* __id, const char* __option) { + std::__throw_format_error( + (string("The format specifier for ") + __id + " does not allow the " + __option + " option").c_str()); +} + +_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void __throw_invalid_type_format_error(const char* __id) { + std::__throw_format_error( + (string("The type option contains an invalid value for ") + __id + " formatting argument").c_str()); +} + +template <contiguous_iterator _Iterator, class _ParseContext> +_LIBCPP_HIDE_FROM_ABI constexpr __format::__parse_number_result<_Iterator> +__parse_arg_id(_Iterator __begin, _Iterator __end, _ParseContext& __ctx) { + using _CharT = iter_value_t<_Iterator>; // This function is a wrapper to call the real parser. But it does the // validation for the pre-conditions and post-conditions. if (__begin == __end) - std::__throw_format_error("End of input while parsing format-spec arg-id"); + std::__throw_format_error("End of input while parsing an argument index"); - __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx); + __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __ctx); - if (__r.__ptr == __end || *__r.__ptr != _CharT('}')) - std::__throw_format_error("Invalid arg-id"); + if (__r.__last == __end || *__r.__last != _CharT('}')) + std::__throw_format_error("The argument index is invalid"); - ++__r.__ptr; + ++__r.__last; return __r; } @@ -78,22 +95,33 @@ __substitute_arg_id(basic_format_arg<_Context> __format_arg) { return _VSTD::__visit_format_arg( [](auto __arg) -> uint32_t { using _Type = decltype(__arg); - if constexpr (integral<_Type>) { + if constexpr (same_as<_Type, monostate>) + std::__throw_format_error("The argument index value is too large for the number of arguments supplied"); + + // [format.string.std]/8 + // If { arg-idopt } is used in a width or precision, the value of the + // corresponding formatting argument is used in its place. If the + // corresponding formatting argument is not of standard signed or unsigned + // integer type, or its value is negative for precision or non-positive for + // width, an exception of type format_error is thrown. + // + // When an integral is used in a format function, it is stored as one of + // the types checked below. Other integral types are promoted. For example, + // a signed char is stored as an int. + if constexpr (same_as<_Type, int> || same_as<_Type, unsigned int> || // + same_as<_Type, long long> || same_as<_Type, unsigned long long>) { if constexpr (signed_integral<_Type>) { if (__arg < 0) - std::__throw_format_error("A format-spec arg-id replacement shouldn't have a negative value"); + std::__throw_format_error("An argument index may not have a negative value"); } using _CT = common_type_t<_Type, decltype(__format::__number_max)>; - if (static_cast<_CT>(__arg) > - static_cast<_CT>(__format::__number_max)) - std::__throw_format_error("A format-spec arg-id replacement exceeds the maximum supported value"); + if (static_cast<_CT>(__arg) > static_cast<_CT>(__format::__number_max)) + std::__throw_format_error("The value of the argument index exceeds its maximum value"); return __arg; - } else if constexpr (same_as<_Type, monostate>) - std::__throw_format_error("Argument index out of bounds"); - else - std::__throw_format_error("A format-spec arg-id replacement argument isn't an integral type"); + } else + std::__throw_format_error("Replacement argument isn't a standard signed or unsigned integer type"); }, __format_arg); } @@ -104,42 +132,48 @@ __substitute_arg_id(basic_format_arg<_Context> __format_arg) { /// explicitly. // TODO FMT Use an ABI tag for this struct. struct __fields { - uint8_t __sign_ : 1 {false}; - uint8_t __alternate_form_ : 1 {false}; - uint8_t __zero_padding_ : 1 {false}; - uint8_t __precision_ : 1 {false}; - uint8_t __locale_specific_form_ : 1 {false}; - uint8_t __type_ : 1 {false}; + uint16_t __sign_ : 1 {false}; + uint16_t __alternate_form_ : 1 {false}; + uint16_t __zero_padding_ : 1 {false}; + uint16_t __precision_ : 1 {false}; + uint16_t __locale_specific_form_ : 1 {false}; + uint16_t __type_ : 1 {false}; // Determines the valid values for fill. // // Originally the fill could be any character except { and }. Range-based // formatters use the colon to mark the beginning of the // underlying-format-spec. To avoid parsing ambiguities these formatter // specializations prohibit the use of the colon as a fill character. - uint8_t __allow_colon_in_fill_ : 1 {false}; + uint16_t __use_range_fill_ : 1 {false}; + uint16_t __clear_brackets_ : 1 {false}; + uint16_t __consume_all_ : 1 {false}; }; // By not placing this constant in the formatter class it's not duplicated for // char and wchar_t. +inline constexpr __fields __fields_bool{.__locale_specific_form_ = true, .__type_ = true, .__consume_all_ = true}; inline constexpr __fields __fields_integral{ .__sign_ = true, .__alternate_form_ = true, .__zero_padding_ = true, .__locale_specific_form_ = true, - .__type_ = true}; + .__type_ = true, + .__consume_all_ = true}; inline constexpr __fields __fields_floating_point{ .__sign_ = true, .__alternate_form_ = true, .__zero_padding_ = true, .__precision_ = true, .__locale_specific_form_ = true, - .__type_ = true}; -inline constexpr __fields __fields_string{.__precision_ = true, .__type_ = true}; -inline constexpr __fields __fields_pointer{.__type_ = true}; - -# if _LIBCPP_STD_VER > 20 -inline constexpr __fields __fields_tuple{.__type_ = false, .__allow_colon_in_fill_ = true}; -inline constexpr __fields __fields_range{.__type_ = false, .__allow_colon_in_fill_ = true}; + .__type_ = true, + .__consume_all_ = true}; +inline constexpr __fields __fields_string{.__precision_ = true, .__type_ = true, .__consume_all_ = true}; +inline constexpr __fields __fields_pointer{.__zero_padding_ = true, .__type_ = true, .__consume_all_ = true}; + +# if _LIBCPP_STD_VER >= 23 +inline constexpr __fields __fields_tuple{.__use_range_fill_ = true, .__clear_brackets_ = true}; +inline constexpr __fields __fields_range{.__use_range_fill_ = true, .__clear_brackets_ = true}; +inline constexpr __fields __fields_fill_align_width{}; # endif enum class _LIBCPP_ENUM_VIS __alignment : uint8_t { @@ -164,7 +198,7 @@ enum class _LIBCPP_ENUM_VIS __sign : uint8_t { }; enum class _LIBCPP_ENUM_VIS __type : uint8_t { - __default, + __default = 0, __string, __binary_lower_case, __binary_upper_case, @@ -172,7 +206,8 @@ enum class _LIBCPP_ENUM_VIS __type : uint8_t { __decimal, __hexadecimal_lower_case, __hexadecimal_upper_case, - __pointer, + __pointer_lower_case, + __pointer_upper_case, __char, __hexfloat_lower_case, __hexfloat_upper_case, @@ -185,6 +220,25 @@ enum class _LIBCPP_ENUM_VIS __type : uint8_t { __debug }; +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __create_type_mask(__type __t) { + uint32_t __shift = static_cast<uint32_t>(__t); + if (__shift == 0) + return 1; + + if (__shift > 31) + std::__throw_format_error("The type does not fit in the mask"); + + return 1 << __shift; +} + +inline constexpr uint32_t __type_mask_integer = + __create_type_mask(__type::__binary_lower_case) | // + __create_type_mask(__type::__binary_upper_case) | // + __create_type_mask(__type::__decimal) | // + __create_type_mask(__type::__octal) | // + __create_type_mask(__type::__hexadecimal_lower_case) | // + __create_type_mask(__type::__hexadecimal_upper_case); + struct __std { __alignment __alignment_ : 3; __sign __sign_ : 2; @@ -196,6 +250,7 @@ struct __std { struct __chrono { __alignment __alignment_ : 3; bool __locale_specific_form_ : 1; + bool __hour_ : 1; bool __weekday_name_ : 1; bool __weekday_ : 1; bool __day_of_year_ : 1; @@ -203,6 +258,25 @@ struct __chrono { bool __month_name_ : 1; }; +// The fill UCS scalar value. +// +// This is always an array, with 1, 2, or 4 elements. +// The size of the data structure is always 32-bits. +template <class _CharT> +struct __code_point; + +template <> +struct __code_point<char> { + char __data[4] = {' '}; +}; + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +struct __code_point<wchar_t> { + wchar_t __data[4 / sizeof(wchar_t)] = {L' '}; +}; +# endif + /// Contains the parsed formatting specifications. /// /// This contains information for both the std-format-spec and the @@ -238,7 +312,7 @@ struct __parsed_specifications { /// replaced with the value of that arg-id. int32_t __precision_; - _CharT __fill_; + __code_point<_CharT> __fill_; _LIBCPP_HIDE_FROM_ABI constexpr bool __has_width() const { return __width_ > 0; } @@ -265,48 +339,161 @@ static_assert(is_trivially_copyable_v<__parsed_specifications<wchar_t>>); template <class _CharT> class _LIBCPP_TEMPLATE_VIS __parser { public: - _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields) - -> decltype(__parse_ctx.begin()) { - - const _CharT* __begin = __parse_ctx.begin(); - const _CharT* __end = __parse_ctx.end(); + // Parses the format specification. + // + // Depending on whether the parsing is done compile-time or run-time + // the method slightly differs. + // - Only parses a field when it is in the __fields. Accepting all + // fields and then validating the valid ones has a performance impact. + // This is faster but gives slighly worse error messages. + // - At compile-time when a field is not accepted the parser will still + // parse it and give an error when it's present. This gives a more + // accurate error. + // The idea is that most times the format instead of the vformat + // functions are used. In that case the error will be detected during + // compilation and there is no need to pay for the run-time overhead. + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator __parse(_ParseContext& __ctx, __fields __fields) { + auto __begin = __ctx.begin(); + auto __end = __ctx.end(); if (__begin == __end) return __begin; - if (__parse_fill_align(__begin, __end, __fields.__allow_colon_in_fill_) && __begin == __end) + if (__parse_fill_align(__begin, __end, __fields.__use_range_fill_) && __begin == __end) return __begin; - if (__fields.__sign_ && __parse_sign(__begin) && __begin == __end) - return __begin; + if (__fields.__sign_) { + if (__parse_sign(__begin) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_sign(__begin)) { + std::__throw_format_error("The format specification does not allow the sign option"); + } - if (__fields.__alternate_form_ && __parse_alternate_form(__begin) && __begin == __end) - return __begin; + if (__fields.__alternate_form_) { + if (__parse_alternate_form(__begin) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_alternate_form(__begin)) { + std::__throw_format_error("The format specifier does not allow the alternate form option"); + } - if (__fields.__zero_padding_ && __parse_zero_padding(__begin) && __begin == __end) - return __begin; + if (__fields.__zero_padding_) { + if (__parse_zero_padding(__begin) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_zero_padding(__begin)) { + std::__throw_format_error("The format specifier does not allow the zero-padding option"); + } - if (__parse_width(__begin, __end, __parse_ctx) && __begin == __end) + if (__parse_width(__begin, __end, __ctx) && __begin == __end) return __begin; - if (__fields.__precision_ && __parse_precision(__begin, __end, __parse_ctx) && __begin == __end) - return __begin; + if (__fields.__precision_) { + if (__parse_precision(__begin, __end, __ctx) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_precision(__begin, __end, __ctx)) { + std::__throw_format_error("The format specifier does not allow the precision option"); + } - if (__fields.__locale_specific_form_ && __parse_locale_specific_form(__begin) && __begin == __end) - return __begin; + if (__fields.__locale_specific_form_) { + if (__parse_locale_specific_form(__begin) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_locale_specific_form(__begin)) { + std::__throw_format_error("The format specifier does not allow the locale-specific form option"); + } + + if (__fields.__clear_brackets_) { + if (__parse_clear_brackets(__begin) && __begin == __end) + return __begin; + } else if (std::is_constant_evaluated() && __parse_clear_brackets(__begin)) { + std::__throw_format_error("The format specifier does not allow the n option"); + } - if (__fields.__type_) { + if (__fields.__type_) __parse_type(__begin); - // When __type_ is false the calling parser is expected to do additional - // parsing. In that case that parser should do the end of format string - // validation. - if (__begin != __end && *__begin != _CharT('}')) - std::__throw_format_error("The format-spec should consume the input or end with a '}'"); - } + if (!__fields.__consume_all_) + return __begin; + + if (__begin != __end && *__begin != _CharT('}')) + std::__throw_format_error("The format specifier should consume the input or end with a '}'"); return __begin; } + // Validates the selected the parsed data. + // + // The valid fields in the parser may depend on the display type + // selected. But the type is the last optional field, so by the time + // it's known an option can't be used, it already has been parsed. + // This does the validation again. + // + // For example an integral may have a sign, zero-padding, or alternate + // form when the type option is not 'c'. So the generic approach is: + // + // typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_integral); + // if (__parser.__type_ == __format_spec::__type::__char) { + // __parser.__validate((__format_spec::__fields_bool, "an integer"); + // ... // more char adjustments + // } else { + // ... // validate an integral type. + // } + // + // For some types all valid options need a second validation run, like + // boolean types. + // + // Depending on whether the validation is done at compile-time or + // run-time the error differs + // - run-time the exception is thrown and contains the type of field + // being validated. + // - at compile-time the line with `std::__throw_format_error` is shown + // in the output. In that case it's important for the error to be on one + // line. + // Note future versions of C++ may allow better compile-time error + // reporting. + _LIBCPP_HIDE_FROM_ABI constexpr void + __validate(__fields __fields, const char* __id, uint32_t __type_mask = -1) const { + if (!__fields.__sign_ && __sign_ != __sign::__default) { + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier does not allow the sign option"); + else + __format_spec::__throw_invalid_option_format_error(__id, "sign"); + } + + if (!__fields.__alternate_form_ && __alternate_form_) { + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier does not allow the alternate form option"); + else + __format_spec::__throw_invalid_option_format_error(__id, "alternate form"); + } + + if (!__fields.__zero_padding_ && __alignment_ == __alignment::__zero_padding) { + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier does not allow the zero-padding option"); + else + __format_spec::__throw_invalid_option_format_error(__id, "zero-padding"); + } + + if (!__fields.__precision_ && __precision_ != -1) { // Works both when the precision has a value or an arg-id. + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier does not allow the precision option"); + else + __format_spec::__throw_invalid_option_format_error(__id, "precision"); + } + + if (!__fields.__locale_specific_form_ && __locale_specific_form_) { + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier does not allow the locale-specific form option"); + else + __format_spec::__throw_invalid_option_format_error(__id, "locale-specific form"); + } + + if ((__create_type_mask(__type_) & __type_mask) == 0) { + if (std::is_constant_evaluated()) + std::__throw_format_error("The format specifier uses an invalid value for the type option"); + else + __format_spec::__throw_invalid_type_format_error(__id); + } + } + /// \returns the `__parsed_specifications` with the resolved dynamic sizes.. _LIBCPP_HIDE_FROM_ABI __parsed_specifications<_CharT> __get_parsed_std_specifications(auto& __ctx) const { @@ -326,6 +513,7 @@ public: .__chrono_ = __chrono{.__alignment_ = __alignment_, .__locale_specific_form_ = __locale_specific_form_, + .__hour_ = __hour_, .__weekday_name_ = __weekday_name_, .__weekday_ = __weekday_, .__day_of_year_ = __day_of_year_, @@ -340,11 +528,13 @@ public: __sign __sign_ : 2 {__sign::__default}; bool __alternate_form_ : 1 {false}; bool __locale_specific_form_ : 1 {false}; - bool __reserved_0_ : 1 {false}; + bool __clear_brackets_ : 1 {false}; __type __type_{__type::__default}; // These flags are only used for formatting chrono. Since the struct has // padding space left it's added to this structure. + bool __hour_ : 1 {false}; + bool __weekday_name_ : 1 {false}; bool __weekday_ : 1 {false}; @@ -353,8 +543,8 @@ public: bool __month_name_ : 1 {false}; - uint8_t __reserved_1_ : 3 {0}; - uint8_t __reserved_2_ : 6 {0}; + uint8_t __reserved_0_ : 2 {0}; + uint8_t __reserved_1_ : 6 {0}; // These two flags are only used internally and not part of the // __parsed_specifications. Therefore put them at the end. bool __width_as_arg_ : 1 {false}; @@ -366,11 +556,7 @@ public: /// The requested precision, either the value or the arg-id. int32_t __precision_{-1}; - // LWG 3576 will probably change this to always accept a Unicode code point - // To avoid changing the size with that change align the field so when it - // becomes 32-bit its alignment will remain the same. That also means the - // size will remain the same. (D2572 addresses the solution for LWG 3576.) - _CharT __fill_{_CharT(' ')}; + __code_point<_CharT> __fill_{}; private: _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alignment(_CharT __c) { @@ -390,19 +576,90 @@ private: return false; } + _LIBCPP_HIDE_FROM_ABI constexpr void __validate_fill_character(_CharT __fill, bool __use_range_fill) { + // The forbidden fill characters all code points formed from a single code unit, thus the + // check can be omitted when more code units are used. + if (__use_range_fill && (__fill == _CharT('{') || __fill == _CharT('}') || __fill == _CharT(':'))) + std::__throw_format_error("The fill option contains an invalid value"); + else if (__fill == _CharT('{') || __fill == _CharT('}')) + std::__throw_format_error("The fill option contains an invalid value"); + } + +# ifndef _LIBCPP_HAS_NO_UNICODE + // range-fill and tuple-fill are identical + template <contiguous_iterator _Iterator> + requires same_as<_CharT, char> +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + || (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) +# endif + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end, bool __use_range_fill) { + _LIBCPP_ASSERT_UNCATEGORIZED(__begin != __end, + "when called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); + __unicode::__code_point_view<_CharT> __view{__begin, __end}; + __unicode::__consume_result __consumed = __view.__consume(); + if (__consumed.__status != __unicode::__consume_result::__ok) + std::__throw_format_error("The format specifier contains malformed Unicode characters"); + + if (__view.__position() < __end && __parse_alignment(*__view.__position())) { + ptrdiff_t __code_units = __view.__position() - __begin; + if (__code_units == 1) + // The forbidden fill characters all are code points encoded + // in one code unit, thus the check can be omitted when more + // code units are used. + __validate_fill_character(*__begin, __use_range_fill); + + std::copy_n(__begin, __code_units, std::addressof(__fill_.__data[0])); + __begin += __code_units + 1; + return true; + } + + if (!__parse_alignment(*__begin)) + return false; + + ++__begin; + return true; + } + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + template <contiguous_iterator _Iterator> + requires(same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4) + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end, bool __use_range_fill) { + _LIBCPP_ASSERT_UNCATEGORIZED(__begin != __end, + "when called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); + if (__begin + 1 != __end && __parse_alignment(*(__begin + 1))) { + if (!__unicode::__is_scalar_value(*__begin)) + std::__throw_format_error("The fill option contains an invalid value"); + + __validate_fill_character(*__begin, __use_range_fill); + + __fill_.__data[0] = *__begin; + __begin += 2; + return true; + } + + if (!__parse_alignment(*__begin)) + return false; + + ++__begin; + return true; + } + +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +# else // _LIBCPP_HAS_NO_UNICODE // range-fill and tuple-fill are identical - _LIBCPP_HIDE_FROM_ABI constexpr bool - __parse_fill_align(const _CharT*& __begin, const _CharT* __end, bool __use_range_fill) { - _LIBCPP_ASSERT(__begin != __end, "when called with an empty input the function will cause " - "undefined behavior by evaluating data not in the input"); + template <contiguous_iterator _Iterator> + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_fill_align(_Iterator& __begin, _Iterator __end, bool __use_range_fill) { + _LIBCPP_ASSERT_UNCATEGORIZED(__begin != __end, + "when called with an empty input the function will cause " + "undefined behavior by evaluating data not in the input"); if (__begin + 1 != __end) { if (__parse_alignment(*(__begin + 1))) { - if (__use_range_fill && (*__begin == _CharT('{') || *__begin == _CharT('}') || *__begin == _CharT(':'))) - std::__throw_format_error("The format-spec range-fill field contains an invalid character"); - else if (*__begin == _CharT('{') || *__begin == _CharT('}')) - std::__throw_format_error("The format-spec fill field contains an invalid character"); + __validate_fill_character(*__begin, __use_range_fill); - __fill_ = *__begin; + __fill_.__data[0] = *__begin; __begin += 2; return true; } @@ -415,7 +672,10 @@ private: return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_sign(const _CharT*& __begin) { +# endif // _LIBCPP_HAS_NO_UNICODE + + template <contiguous_iterator _Iterator> + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_sign(_Iterator& __begin) { switch (*__begin) { case _CharT('-'): __sign_ = __sign::__minus; @@ -433,7 +693,8 @@ private: return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alternate_form(const _CharT*& __begin) { + template <contiguous_iterator _Iterator> + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_alternate_form(_Iterator& __begin) { if (*__begin != _CharT('#')) return false; @@ -442,7 +703,8 @@ private: return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_zero_padding(const _CharT*& __begin) { + template <contiguous_iterator _Iterator> + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_zero_padding(_Iterator& __begin) { if (*__begin != _CharT('0')) return false; @@ -452,15 +714,16 @@ private: return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_width(const _CharT*& __begin, const _CharT* __end, auto& __parse_ctx) { + template <contiguous_iterator _Iterator> + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_width(_Iterator& __begin, _Iterator __end, auto& __ctx) { if (*__begin == _CharT('0')) - std::__throw_format_error("A format-spec width field shouldn't have a leading zero"); + std::__throw_format_error("The width option should not have a leading zero"); if (*__begin == _CharT('{')) { - __format::__parse_number_result __r = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx); + __format::__parse_number_result __r = __format_spec::__parse_arg_id(++__begin, __end, __ctx); __width_as_arg_ = true; __width_ = __r.__value; - __begin = __r.__ptr; + __begin = __r.__last; return true; } @@ -469,40 +732,41 @@ private: __format::__parse_number_result __r = __format::__parse_number(__begin, __end); __width_ = __r.__value; - _LIBCPP_ASSERT(__width_ != 0, "A zero value isn't allowed and should be impossible, " - "due to validations in this function"); - __begin = __r.__ptr; + _LIBCPP_ASSERT_UNCATEGORIZED(__width_ != 0, "A zero value isn't allowed and should be impossible, " + "due to validations in this function"); + __begin = __r.__last; return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_precision(const _CharT*& __begin, const _CharT* __end, - auto& __parse_ctx) { + template <contiguous_iterator _Iterator> + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_precision(_Iterator& __begin, _Iterator __end, auto& __ctx) { if (*__begin != _CharT('.')) return false; ++__begin; if (__begin == __end) - std::__throw_format_error("End of input while parsing format-spec precision"); + std::__throw_format_error("End of input while parsing format specifier precision"); if (*__begin == _CharT('{')) { - __format::__parse_number_result __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx); + __format::__parse_number_result __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __ctx); __precision_as_arg_ = true; __precision_ = __arg_id.__value; - __begin = __arg_id.__ptr; + __begin = __arg_id.__last; return true; } if (*__begin < _CharT('0') || *__begin > _CharT('9')) - std::__throw_format_error("The format-spec precision field doesn't contain a value or arg-id"); + std::__throw_format_error("The precision option does not contain a value or an argument index"); __format::__parse_number_result __r = __format::__parse_number(__begin, __end); __precision_ = __r.__value; __precision_as_arg_ = false; - __begin = __r.__ptr; + __begin = __r.__last; return true; } - _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_locale_specific_form(const _CharT*& __begin) { + template <contiguous_iterator _Iterator> + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_locale_specific_form(_Iterator& __begin) { if (*__begin != _CharT('L')) return false; @@ -511,7 +775,18 @@ private: return true; } - _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(const _CharT*& __begin) { + template <contiguous_iterator _Iterator> + _LIBCPP_HIDE_FROM_ABI constexpr bool __parse_clear_brackets(_Iterator& __begin) { + if (*__begin != _CharT('n')) + return false; + + __clear_brackets_ = true; + ++__begin; + return true; + } + + template <contiguous_iterator _Iterator> + _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(_Iterator& __begin) { // Determines the type. It does not validate whether the selected type is // valid. Most formatters have optional fields that are only allowed for // certain types. These parsers need to do validation after the type has @@ -561,7 +836,10 @@ private: __type_ = __type::__octal; break; case 'p': - __type_ = __type::__pointer; + __type_ = __type::__pointer_lower_case; + break; + case 'P': + __type_ = __type::__pointer_upper_case; break; case 's': __type_ = __type::__string; @@ -569,7 +847,7 @@ private: case 'x': __type_ = __type::__hexadecimal_lower_case; break; -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 case '?': __type_ = __type::__debug; break; @@ -611,36 +889,28 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_string(__format_spec break; default: - std::__throw_format_error("The format-spec type has a type not supported for a string argument"); + std::__throw_format_error("The type option contains an invalid value for a string formatting argument"); } } template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_bool_string(__parser<_CharT>& __parser) { - if (__parser.__sign_ != __sign::__default) - std::__throw_format_error("A sign field isn't allowed in this format-spec"); - - if (__parser.__alternate_form_) - std::__throw_format_error("An alternate form field isn't allowed in this format-spec"); - - if (__parser.__alignment_ == __alignment::__zero_padding) - std::__throw_format_error("A zero-padding field isn't allowed in this format-spec"); - +_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_bool_string(__parser<_CharT>& __parser, const char* __id) { + __parser.__validate(__format_spec::__fields_bool, __id); if (__parser.__alignment_ == __alignment::__default) __parser.__alignment_ = __alignment::__left; } template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_char(__parser<_CharT>& __parser) { - __format_spec::__process_display_type_bool_string(__parser); +_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_char(__parser<_CharT>& __parser, const char* __id) { + __format_spec::__process_display_type_bool_string(__parser, __id); } template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_bool(__parser<_CharT>& __parser) { +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_bool(__parser<_CharT>& __parser, const char* __id) { switch (__parser.__type_) { case __format_spec::__type::__default: case __format_spec::__type::__string: - __format_spec::__process_display_type_bool_string(__parser); + __format_spec::__process_display_type_bool_string(__parser, __id); break; case __format_spec::__type::__binary_lower_case: @@ -652,17 +922,17 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_bool(__parser<_CharT>& __p break; default: - std::__throw_format_error("The format-spec type has a type not supported for a bool argument"); + __format_spec::__throw_invalid_type_format_error(__id); } } template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_char(__parser<_CharT>& __parser) { +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_char(__parser<_CharT>& __parser, const char* __id) { switch (__parser.__type_) { case __format_spec::__type::__default: case __format_spec::__type::__char: case __format_spec::__type::__debug: - __format_spec::__process_display_type_char(__parser); + __format_spec::__process_display_type_char(__parser, __id); break; case __format_spec::__type::__binary_lower_case: @@ -674,12 +944,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_char(__parser<_CharT>& __p break; default: - std::__throw_format_error("The format-spec type has a type not supported for a char argument"); + __format_spec::__throw_invalid_type_format_error(__id); } } template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_integer(__parser<_CharT>& __parser) { +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_integer(__parser<_CharT>& __parser, const char* __id) { switch (__parser.__type_) { case __format_spec::__type::__default: case __format_spec::__type::__binary_lower_case: @@ -691,16 +961,16 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_integer(__parser<_CharT>& break; case __format_spec::__type::__char: - __format_spec::__process_display_type_char(__parser); + __format_spec::__process_display_type_char(__parser, __id); break; default: - std::__throw_format_error("The format-spec type has a type not supported for an integer argument"); + __format_spec::__throw_invalid_type_format_error(__id); } } template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_floating_point(__parser<_CharT>& __parser) { +_LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_floating_point(__parser<_CharT>& __parser, const char* __id) { switch (__parser.__type_) { case __format_spec::__type::__default: case __format_spec::__type::__hexfloat_lower_case: @@ -719,33 +989,34 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __process_parsed_floating_point(__parser<_C break; default: - std::__throw_format_error("The format-spec type has a type not supported for a floating-point argument"); + __format_spec::__throw_invalid_type_format_error(__id); } } -_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_pointer(__format_spec::__type __type) { +_LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type_pointer(__format_spec::__type __type, const char* __id) { switch (__type) { case __format_spec::__type::__default: - case __format_spec::__type::__pointer: + case __format_spec::__type::__pointer_lower_case: + case __format_spec::__type::__pointer_upper_case: break; default: - std::__throw_format_error("The format-spec type has a type not supported for a pointer argument"); + __format_spec::__throw_invalid_type_format_error(__id); } } -template <class _CharT> +template <contiguous_iterator _Iterator> struct __column_width_result { /// The number of output columns. size_t __width_; /// One beyond the last code unit used in the estimation. /// /// This limits the original output to fit in the wanted number of columns. - const _CharT* __last_; + _Iterator __last_; }; -template <class _CharT> -__column_width_result(size_t, const _CharT*) -> __column_width_result<_CharT>; +template <contiguous_iterator _Iterator> +__column_width_result(size_t, _Iterator) -> __column_width_result<_Iterator>; /// Since a column width can be two it's possible that the requested column /// width can't be achieved. Depending on the intended usage the policy can be @@ -761,66 +1032,16 @@ enum class __column_width_rounding { __down, __up }; # ifndef _LIBCPP_HAS_NO_UNICODE namespace __detail { - -/// Converts a code point to the column width. -/// -/// The estimations are conforming to [format.string.general]/11 -/// -/// This version expects a value less than 0x1'0000, which is a 3-byte UTF-8 -/// character. -_LIBCPP_HIDE_FROM_ABI constexpr int __column_width_3(uint32_t __c) noexcept { - _LIBCPP_ASSERT(__c < 0x10000, "Use __column_width_4 or __column_width for larger values"); - - // clang-format off - return 1 + (__c >= 0x1100 && (__c <= 0x115f || - (__c >= 0x2329 && (__c <= 0x232a || - (__c >= 0x2e80 && (__c <= 0x303e || - (__c >= 0x3040 && (__c <= 0xa4cf || - (__c >= 0xac00 && (__c <= 0xd7a3 || - (__c >= 0xf900 && (__c <= 0xfaff || - (__c >= 0xfe10 && (__c <= 0xfe19 || - (__c >= 0xfe30 && (__c <= 0xfe6f || - (__c >= 0xff00 && (__c <= 0xff60 || - (__c >= 0xffe0 && (__c <= 0xffe6 - )))))))))))))))))))); - // clang-format on -} - -/// @overload -/// -/// This version expects a value greater than or equal to 0x1'0000, which is a -/// 4-byte UTF-8 character. -_LIBCPP_HIDE_FROM_ABI constexpr int __column_width_4(uint32_t __c) noexcept { - _LIBCPP_ASSERT(__c >= 0x10000, "Use __column_width_3 or __column_width for smaller values"); - - // clang-format off - return 1 + (__c >= 0x1'f300 && (__c <= 0x1'f64f || - (__c >= 0x1'f900 && (__c <= 0x1'f9ff || - (__c >= 0x2'0000 && (__c <= 0x2'fffd || - (__c >= 0x3'0000 && (__c <= 0x3'fffd - )))))))); - // clang-format on -} - -/// @overload -/// -/// The general case, accepting all values. -_LIBCPP_HIDE_FROM_ABI constexpr int __column_width(uint32_t __c) noexcept { - if (__c < 0x10000) - return __detail::__column_width_3(__c); - - return __detail::__column_width_4(__c); -} - -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width_grapheme_clustering( - const _CharT* __first, const _CharT* __last, size_t __maximum, __column_width_rounding __rounding) noexcept { +template <contiguous_iterator _Iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_Iterator> __estimate_column_width_grapheme_clustering( + _Iterator __first, _Iterator __last, size_t __maximum, __column_width_rounding __rounding) noexcept { + using _CharT = iter_value_t<_Iterator>; __unicode::__extended_grapheme_cluster_view<_CharT> __view{__first, __last}; - __column_width_result<_CharT> __result{0, __first}; + __column_width_result<_Iterator> __result{0, __first}; while (__result.__last_ != __last && __result.__width_ <= __maximum) { typename __unicode::__extended_grapheme_cluster_view<_CharT>::__cluster __cluster = __view.__consume(); - int __width = __detail::__column_width(__cluster.__code_point_); + int __width = __width_estimation_table::__estimated_width(__cluster.__code_point_); // When the next entry would exceed the maximum width the previous width // might be returned. For example when a width of 100 is requested the @@ -884,8 +1105,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __is_ascii(char32_t __c) { return __c < 0x8 /// \param __rounding Selects the rounding method. /// \c __down result.__width_ <= __maximum /// \c __up result.__width_ <= __maximum + 1 -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_width( +template <class _CharT, class _Iterator = typename basic_string_view<_CharT>::const_iterator> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_Iterator> __estimate_column_width( basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding __rounding) noexcept { // The width estimation is done in two steps: // - Quickly process for the ASCII part. ASCII has the following properties @@ -904,7 +1125,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_ // need to scan one code unit beyond the requested precision. When this code // unit is non-ASCII we omit the current code unit and let the Grapheme // clustering algorithm do its work. - const _CharT* __it = __str.begin(); + auto __it = __str.begin(); if (__format_spec::__is_ascii(*__it)) { do { --__maximum; @@ -932,7 +1153,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_ } # else // !defined(_LIBCPP_HAS_NO_UNICODE) template <class _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> +_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<typename basic_string_view<_CharT>::const_iterator> __estimate_column_width(basic_string_view<_CharT> __str, size_t __maximum, __column_width_rounding) noexcept { // When Unicode isn't supported assume ASCII and every code unit is one code // point. In ASCII the estimated column width is always one. Thus there's no @@ -945,7 +1166,7 @@ __estimate_column_width(basic_string_view<_CharT> __str, size_t __maximum, __col } // namespace __format_spec -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/range_default_formatter.h b/libcxx/include/__format/range_default_formatter.h index 774887b05305..bcab5d6afdd3 100644 --- a/libcxx/include/__format/range_default_formatter.h +++ b/libcxx/include/__format/range_default_formatter.h @@ -14,22 +14,25 @@ # pragma GCC system_header #endif -#include <__availability> +#include <__algorithm/ranges_copy.h> #include <__chrono/statically_widen.h> #include <__concepts/same_as.h> #include <__config> #include <__format/concepts.h> #include <__format/formatter.h> #include <__format/range_formatter.h> +#include <__iterator/back_insert_iterator.h> #include <__ranges/concepts.h> +#include <__ranges/data.h> +#include <__ranges/size.h> +#include <__type_traits/conditional.h> #include <__type_traits/remove_cvref.h> #include <__utility/pair.h> #include <string_view> -#include <tuple> _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _Rp, class _CharT> concept __const_formattable_range = @@ -83,40 +86,23 @@ inline constexpr range_format format_kind<_Rp> = [] { return range_format::sequence; }(); -// This is a non-standard work-around to fix instantiation of -// formatter<const _CharT[N], _CharT> -// const _CharT[N] satisfies the ranges::input_range concept. -// remove_cvref_t<const _CharT[N]> is _CharT[N] so it does not satisfy the -// requirement of the above specialization. Instead it will instantiate the -// primary template, which is ill-formed. -// -// An alternative solution is to remove the offending formatter. -// -// https://godbolt.org/z/bqjhhaexx -// -// The removal is proposed in LWG3833, but use the work-around until the issue -// has been adopted. -// TODO FMT Implement LWG3833. -template <class _CharT, size_t N> -inline constexpr range_format format_kind<const _CharT[N]> = range_format::disabled; - template <range_format _Kp, ranges::input_range _Rp, class _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter; +struct _LIBCPP_TEMPLATE_VIS __range_default_formatter; // Required specializations template <ranges::input_range _Rp, class _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<range_format::sequence, _Rp, _CharT> { +struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::sequence, _Rp, _CharT> { private: using __maybe_const_r = __fmt_maybe_const<_Rp, _CharT>; range_formatter<remove_cvref_t<ranges::range_reference_t<__maybe_const_r>>, _CharT> __underlying_; public: - _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept { __underlying_.set_separator(__separator); } _LIBCPP_HIDE_FROM_ABI constexpr void - set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) noexcept { __underlying_.set_brackets(__opening_bracket, __closing_bracket); } @@ -125,14 +111,15 @@ public: return __underlying_.parse(__ctx); } - template <class FormatContext> - _LIBCPP_HIDE_FROM_ABI typename FormatContext::iterator format(__maybe_const_r& __range, FormatContext& __ctx) const { + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(__maybe_const_r& __range, _FormatContext& __ctx) const { return __underlying_.format(__range, __ctx); } }; template <ranges::input_range _Rp, class _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<range_format::map, _Rp, _CharT> { +struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::map, _Rp, _CharT> { private: using __maybe_const_map = __fmt_maybe_const<_Rp, _CharT>; using __element_type = remove_cvref_t<ranges::range_reference_t<__maybe_const_map>>; @@ -160,7 +147,7 @@ public: }; template <ranges::input_range _Rp, class _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<range_format::set, _Rp, _CharT> { +struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::set, _Rp, _CharT> { private: using __maybe_const_set = __fmt_maybe_const<_Rp, _CharT>; using __element_type = remove_cvref_t<ranges::range_reference_t<__maybe_const_set>>; @@ -185,16 +172,48 @@ public: template <range_format _Kp, ranges::input_range _Rp, class _CharT> requires(_Kp == range_format::string || _Kp == range_format::debug_string) -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __range_default_formatter<_Kp, _Rp, _CharT> { - __range_default_formatter() = delete; // TODO FMT Implement +struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<_Kp, _Rp, _CharT> { +private: + // This deviates from the Standard, there the exposition only type is + // formatter<basic_string<charT>, charT> underlying_; + // Using a string_view allows the format function to avoid a copy of the + // input range when it is a contigious range. + formatter<basic_string_view<_CharT>, _CharT> __underlying_; + +public: + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + typename _ParseContext::iterator __i = __underlying_.parse(__ctx); + if constexpr (_Kp == range_format::debug_string) + __underlying_.set_debug_format(); + return __i; + } + + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator + format(conditional_t<ranges::input_range<const _Rp>, const _Rp&, _Rp&> __range, _FormatContext& __ctx) const { + // When the range is contiguous use a basic_string_view instead to avoid a + // copy of the underlying data. The basic_string_view formatter + // specialization is the "basic" string formatter in libc++. + if constexpr (ranges::contiguous_range<_Rp> && std::ranges::sized_range<_Rp>) + return __underlying_.format(basic_string_view<_CharT>{ranges::data(__range), ranges::size(__range)}, __ctx); + else { + // P2106's from_range has not been implemented yet. Instead use a simple + // copy operation. + // TODO FMT use basic_string's "from_range" constructor. + // return __underlying_.format(basic_string<_CharT>{from_range, __range}, __ctx); + basic_string<_CharT> __str; + std::ranges::copy(__range, back_insert_iterator{__str}); + return __underlying_.format(static_cast<basic_string_view<_CharT>>(__str), __ctx); + } + } }; template <ranges::input_range _Rp, class _CharT> requires(format_kind<_Rp> != range_format::disabled && formattable<ranges::range_reference_t<_Rp>, _CharT>) -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_Rp, _CharT> - : __range_default_formatter<format_kind<_Rp>, _Rp, _CharT> {}; +struct _LIBCPP_TEMPLATE_VIS formatter<_Rp, _CharT> : __range_default_formatter<format_kind<_Rp>, _Rp, _CharT> {}; -#endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/range_formatter.h b/libcxx/include/__format/range_formatter.h index 9ea61a70350a..27870972c9d5 100644 --- a/libcxx/include/__format/range_formatter.h +++ b/libcxx/include/__format/range_formatter.h @@ -15,13 +15,11 @@ #endif #include <__algorithm/ranges_copy.h> -#include <__availability> #include <__chrono/statically_widen.h> #include <__concepts/same_as.h> #include <__config> #include <__format/buffer.h> #include <__format/concepts.h> -#include <__format/format_args.h> #include <__format/format_context.h> #include <__format/format_error.h> #include <__format/formatter.h> @@ -36,54 +34,73 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _Tp, class _CharT = char> requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter { - _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) { +struct _LIBCPP_TEMPLATE_VIS range_formatter { + _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept { __separator_ = __separator; } _LIBCPP_HIDE_FROM_ABI constexpr void - set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) { + set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) noexcept { __opening_bracket_ = __opening_bracket; __closing_bracket_ = __closing_bracket; } - _LIBCPP_HIDE_FROM_ABI constexpr formatter<_Tp, _CharT>& underlying() { return __underlying_; } - _LIBCPP_HIDE_FROM_ABI constexpr const formatter<_Tp, _CharT>& underlying() const { return __underlying_; } + _LIBCPP_HIDE_FROM_ABI constexpr formatter<_Tp, _CharT>& underlying() noexcept { return __underlying_; } + _LIBCPP_HIDE_FROM_ABI constexpr const formatter<_Tp, _CharT>& underlying() const noexcept { return __underlying_; } template <class _ParseContext> - _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __parse_ctx) { - const _CharT* __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_range); - const _CharT* __end = __parse_ctx.end(); - if (__begin == __end) - return __begin; + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + auto __begin = __parser_.__parse(__ctx, __format_spec::__fields_range); + auto __end = __ctx.end(); + // Note the cases where __begin == __end in this code only happens when the + // replacement-field has no terminating }, or when the parse is manually + // called with a format-spec. The former is an error and the latter means + // using a formatter without the format functions or print. + if (__begin == __end) [[unlikely]] + return __parse_empty_range_underlying_spec(__ctx, __begin); // The n field overrides a possible m type, therefore delay applying the // effect of n until the type has been procesed. - bool __clear_brackets = (*__begin == _CharT('n')); - if (__clear_brackets) { - ++__begin; - if (__begin == __end) { - // Since there is no more data, clear the brackets before returning. - set_brackets({}, {}); - return __begin; - } - } - __parse_type(__begin, __end); - if (__clear_brackets) + if (__parser_.__clear_brackets_) set_brackets({}, {}); - if (__begin == __end) - return __begin; + if (__begin == __end) [[unlikely]] + return __parse_empty_range_underlying_spec(__ctx, __begin); bool __has_range_underlying_spec = *__begin == _CharT(':'); + if (__has_range_underlying_spec) { + // range-underlying-spec: + // : format-spec + ++__begin; + } else if (__begin != __end && *__begin != _CharT('}')) + // When there is no underlaying range the current parse should have + // consumed the format-spec. If not, the not consumed input will be + // processed by the underlying. For example {:-} for a range in invalid, + // the sign field is not present. Without this check the underlying_ will + // get -} as input which my be valid. + std::__throw_format_error("The format specifier should consume the input or end with a '}'"); + + __ctx.advance_to(__begin); + __begin = __underlying_.parse(__ctx); + + // This test should not be required if __has_range_underlying_spec is false. + // However this test makes sure the underlying formatter left the parser in + // a valid state. (Note this is not a full protection against evil parsers. + // For example + // } this is test for the next argument {} + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ + // could consume more than it should. + if (__begin != __end && *__begin != _CharT('}')) + std::__throw_format_error("The format specifier should consume the input or end with a '}'"); + if (__parser_.__type_ != __format_spec::__type::__default) { // [format.range.formatter]/6 // If the range-type is s or ?s, then there shall be no n option and no // range-underlying-spec. - if (__clear_brackets) { + if (__parser_.__clear_brackets_) { if (__parser_.__type_ == __format_spec::__type::__string) std::__throw_format_error("The n option and type s can't be used together"); std::__throw_format_error("The n option and type ?s can't be used together"); @@ -96,20 +113,6 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter { } else if (!__has_range_underlying_spec) std::__set_debug_format(__underlying_); - if (__has_range_underlying_spec) { - // range-underlying-spec: - // : format-spec - ++__begin; - if (__begin == __end) - return __begin; - - __parse_ctx.advance_to(__begin); - __begin = __underlying_.parse(__parse_ctx); - } - - if (__begin != __end && *__begin != _CharT('}')) - std::__throw_format_error("The format-spec should consume the input or end with a '}'"); - return __begin; } @@ -211,7 +214,8 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter { __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__left}; private: - _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(const _CharT*& __begin, const _CharT* __end) { + template <contiguous_iterator _Iterator> + _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(_Iterator& __begin, _Iterator __end) { switch (*__begin) { case _CharT('m'): if constexpr (__fmt_pair_like<_Tp>) { @@ -219,7 +223,7 @@ private: set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ", ")); ++__begin; } else - std::__throw_format_error("The range-format-spec type m requires two elements for a pair or tuple"); + std::__throw_format_error("Type m requires a pair or a tuple with two elements"); break; case _CharT('s'): @@ -227,28 +231,39 @@ private: __parser_.__type_ = __format_spec::__type::__string; ++__begin; } else - std::__throw_format_error("The range-format-spec type s requires formatting a character type"); + std::__throw_format_error("Type s requires character type as formatting argument"); break; case _CharT('?'): ++__begin; if (__begin == __end || *__begin != _CharT('s')) - std::__throw_format_error("The format-spec should consume the input or end with a '}'"); + std::__throw_format_error("The format specifier should consume the input or end with a '}'"); if constexpr (same_as<_Tp, _CharT>) { __parser_.__type_ = __format_spec::__type::__debug; ++__begin; } else - std::__throw_format_error("The range-format-spec type ?s requires formatting a character type"); + std::__throw_format_error("Type ?s requires character type as formatting argument"); } } + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator + __parse_empty_range_underlying_spec(_ParseContext& __ctx, typename _ParseContext::iterator __begin) { + __ctx.advance_to(__begin); + [[maybe_unused]] typename _ParseContext::iterator __result = __underlying_.parse(__ctx); + _LIBCPP_ASSERT_UNCATEGORIZED( + __result == __begin, + "the underlying's parse function should not advance the input beyond the end of the input"); + return __begin; + } + formatter<_Tp, _CharT> __underlying_; basic_string_view<_CharT> __separator_ = _LIBCPP_STATICALLY_WIDEN(_CharT, ", "); basic_string_view<_CharT> __opening_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "["); basic_string_view<_CharT> __closing_bracket_ = _LIBCPP_STATICALLY_WIDEN(_CharT, "]"); }; -#endif //_LIBCPP_STD_VER > 20 +#endif //_LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/unicode.h b/libcxx/include/__format/unicode.h index 432725876082..8666f80c78a2 100644 --- a/libcxx/include/__format/unicode.h +++ b/libcxx/include/__format/unicode.h @@ -11,11 +11,13 @@ #define _LIBCPP___FORMAT_UNICODE_H #include <__assert> +#include <__bit/countl.h> +#include <__concepts/same_as.h> #include <__config> #include <__format/extended_grapheme_cluster_table.h> -#include <__type_traits/make_unsigned.h> -#include <__utility/unreachable.h> -#include <bit> +#include <__iterator/concepts.h> +#include <__iterator/readable_traits.h> // iter_value_t +#include <string_view> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -23,27 +25,32 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace __unicode { -# if _LIBCPP_STD_VER > 20 - -/// The result of consuming a code point using P2286' semantics -/// -/// TODO FMT Combine __consume and __consume_p2286 in one function. -struct __consume_p2286_result { - // A size of 0 means well formed. This to differenciate between - // a valid code point and a code unit that's invalid like 0b11111xxx. - int __ill_formed_size; - - // If well formed the consumed code point. - // Otherwise the ill-formed code units as unsigned 8-bit values. They are - // stored in reverse order, to make it easier to extract the values. - char32_t __value; +// Helper struct for the result of a consume operation. +// +// The status value for a correct code point is 0. This allows a valid value to +// be used without masking. +// When the decoding fails it know the number of code units affected. For the +// current use-cases that value is not needed, therefore it is not stored. +// The escape routine needs the number of code units for both a valid and +// invalid character and keeps track of it itself. Doing it in this result +// unconditionally would give some overhead when the value is unneeded. +struct __consume_result { + // When __status == __ok it contains the decoded code point. + // Else it contains the replacement character U+FFFD + char32_t __code_point : 31; + + enum : char32_t { + // Consumed a well-formed code point. + __ok = 0, + // Encountered invalid UTF-8 + __error = 1 + } __status : 1 {__ok}; }; - -# endif // _LIBCPP_STD_VER > 20 +static_assert(sizeof(__consume_result) == sizeof(char32_t)); # ifndef _LIBCPP_HAS_NO_UNICODE @@ -62,9 +69,41 @@ struct __consume_p2286_result { inline constexpr char32_t __replacement_character = U'\ufffd'; -_LIBCPP_HIDE_FROM_ABI constexpr bool __is_continuation(const char* __char, int __count) { +// The error of a consume operation. +// +// This sets the code point to the replacement character. This code point does +// not participate in the grapheme clustering, so grapheme clustering code can +// ignore the error status and always use the code point. +inline constexpr __consume_result __consume_result_error{__replacement_character, __consume_result::__error}; + +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool __is_high_surrogate(char32_t __value) { + return __value >= 0xd800 && __value <= 0xdbff; +} + +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool __is_low_surrogate(char32_t __value) { + return __value >= 0xdc00 && __value <= 0xdfff; +} + +// https://www.unicode.org/glossary/#surrogate_code_point +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool __is_surrogate(char32_t __value) { + return __value >= 0xd800 && __value <= 0xdfff; +} + +// https://www.unicode.org/glossary/#code_point +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool __is_code_point(char32_t __value) { + return __value <= 0x10ffff; +} + +// https://www.unicode.org/glossary/#unicode_scalar_value +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool __is_scalar_value(char32_t __value) { + return __unicode::__is_code_point(__value) && !__unicode::__is_surrogate(__value); +} + +template <contiguous_iterator _Iterator> + requires same_as<iter_value_t<_Iterator>, char> +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_continuation(_Iterator __char, int __count) { do { - if ((*__char & 0b1000'0000) != 0b1000'0000) + if ((*__char & 0b1100'0000) != 0b1000'0000) return false; --__count; ++__char; @@ -82,133 +121,116 @@ class __code_point_view; /// UTF-8 specialization. template <> class __code_point_view<char> { + using _Iterator = basic_string_view<char>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const char* __first, const char* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } - _LIBCPP_HIDE_FROM_ABI constexpr const char* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } - _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + // https://www.unicode.org/versions/latest/ch03.pdf#G7404 + // Based on Table 3-7, Well-Formed UTF-8 Byte Sequences + // + // Code Points First Byte Second Byte Third Byte Fourth Byte Remarks + // U+0000..U+007F 00..7F U+0000..U+007F 1 code unit range + // C0..C1 80..BF invalid overlong encoding + // U+0080..U+07FF C2..DF 80..BF U+0080..U+07FF 2 code unit range + // E0 80..9F 80..BF invalid overlong encoding + // U+0800..U+0FFF E0 A0..BF 80..BF U+0800..U+FFFF 3 code unit range + // U+1000..U+CFFF E1..EC 80..BF 80..BF + // U+D000..U+D7FF ED 80..9F 80..BF + // U+D800..U+DFFF ED A0..BF 80..BF invalid encoding of surrogate code point + // U+E000..U+FFFF EE..EF 80..BF 80..BF + // F0 80..8F 80..BF 80..BF invalid overlong encoding + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF U+10000..U+10FFFF 4 code unit range + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + // F4 90..BF 80..BF 80..BF U+110000.. invalid code point range + // + // Unlike other parsers, these invalid entries are tested after decoding. + // - The parser always needs to consume these code units + // - The code is optimized for well-formed UTF-8 + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __consume_result __consume() noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED(__first_ != __last_, "can't move beyond the end of input"); // Based on the number of leading 1 bits the number of code units in the // code point can be determined. See // https://en.wikipedia.org/wiki/UTF-8#Encoding - switch (_VSTD::countl_one(static_cast<unsigned char>(*__first_))) { + switch (std::countl_one(static_cast<unsigned char>(*__first_))) { case 0: - return *__first_++; + return {static_cast<unsigned char>(*__first_++)}; - case 2: + case 2: { if (__last_ - __first_ < 2 || !__unicode::__is_continuation(__first_ + 1, 1)) [[unlikely]] break; - else { - char32_t __value = static_cast<unsigned char>(*__first_++) & 0x1f; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - return __value; - } - case 3: - if (__last_ - __first_ < 3 || !__unicode::__is_continuation(__first_ + 1, 2)) [[unlikely]] - break; - else { - char32_t __value = static_cast<unsigned char>(*__first_++) & 0x0f; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - return __value; - } + char32_t __value = static_cast<unsigned char>(*__first_++) & 0x1f; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - case 4: - if (__last_ - __first_ < 4 || !__unicode::__is_continuation(__first_ + 1, 3)) [[unlikely]] - break; - else { - char32_t __value = static_cast<unsigned char>(*__first_++) & 0x07; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - return __value; - } - } - // An invalid number of leading ones can be garbage or a code unit in the - // middle of a code point. By consuming one code unit the parser may get - // "in sync" after a few code units. - ++__first_; - return __replacement_character; - } - -# if _LIBCPP_STD_VER > 20 - _LIBCPP_HIDE_FROM_ABI constexpr __consume_p2286_result __consume_p2286() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + // These values should be encoded in 1 UTF-8 code unit. + if (__value < 0x0080) [[unlikely]] + return __consume_result_error; - // Based on the number of leading 1 bits the number of code units in the - // code point can be determined. See - // https://en.wikipedia.org/wiki/UTF-8#Encoding - switch (std::countl_one(static_cast<unsigned char>(*__first_))) { - case 0: - return {0, static_cast<unsigned char>(*__first_++)}; + return {__value}; + } - case 2: - if (__last_ - __first_ < 2) [[unlikely]] + case 3: { + if (__last_ - __first_ < 3 || !__unicode::__is_continuation(__first_ + 1, 2)) [[unlikely]] break; - if (__unicode::__is_continuation(__first_ + 1, 1)) { - char32_t __value = static_cast<unsigned char>(*__first_++) & 0x1f; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - return {0, __value}; - } - break; + char32_t __value = static_cast<unsigned char>(*__first_++) & 0x0f; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - case 3: - if (__last_ - __first_ < 3) [[unlikely]] - break; + // These values should be encoded in 1 or 2 UTF-8 code units. + if (__value < 0x0800) [[unlikely]] + return __consume_result_error; - if (__unicode::__is_continuation(__first_ + 1, 2)) { - char32_t __value = static_cast<unsigned char>(*__first_++) & 0x0f; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - return {0, __value}; - } - break; + // A surrogate value is always encoded in 3 UTF-8 code units. + if (__unicode::__is_surrogate(__value)) [[unlikely]] + return __consume_result_error; + + return {__value}; + } - case 4: - if (__last_ - __first_ < 4) [[unlikely]] + case 4: { + if (__last_ - __first_ < 4 || !__unicode::__is_continuation(__first_ + 1, 3)) [[unlikely]] break; - if (__unicode::__is_continuation(__first_ + 1, 3)) { - char32_t __value = static_cast<unsigned char>(*__first_++) & 0x07; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - __value <<= 6; - __value |= static_cast<unsigned char>(*__first_++) & 0x3f; + char32_t __value = static_cast<unsigned char>(*__first_++) & 0x07; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; + __value <<= 6; + __value |= static_cast<unsigned char>(*__first_++) & 0x3f; - if (__value > 0x10FFFF) // Outside the valid Unicode range? - return {4, __value}; + // These values should be encoded in 1, 2, or 3 UTF-8 code units. + if (__value < 0x10000) [[unlikely]] + return __consume_result_error; - return {0, __value}; - } - break; + // A value too large is always encoded in 4 UTF-8 code units. + if (!__unicode::__is_code_point(__value)) [[unlikely]] + return __consume_result_error; + + return {__value}; + } } // An invalid number of leading ones can be garbage or a code unit in the // middle of a code point. By consuming one code unit the parser may get // "in sync" after a few code units. - return {1, static_cast<unsigned char>(*__first_++)}; + ++__first_; + return __consume_result_error; } -# endif // _LIBCPP_STD_VER > 20 private: - const char* __first_; - const char* __last_; + _Iterator __first_; + _Iterator __last_; }; # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -225,75 +247,48 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __is_surrogate_pair_low(wchar_t __value) { /// - 4 UTF-32 (for example Linux) template <> class __code_point_view<wchar_t> { + using _Iterator = typename basic_string_view<wchar_t>::const_iterator; + public: static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "sizeof(wchar_t) has a not implemented value"); - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const wchar_t* __first, const wchar_t* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} - _LIBCPP_HIDE_FROM_ABI constexpr const wchar_t* __position() const noexcept { return __first_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } - _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __consume_result __consume() noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED(__first_ != __last_, "can't move beyond the end of input"); + char32_t __value = static_cast<char32_t>(*__first_++); if constexpr (sizeof(wchar_t) == 2) { - char32_t __result = *__first_++; - // Is the code unit part of a surrogate pair? See - // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF - if (__result >= 0xd800 && __result <= 0xDfff) { - // Malformed Unicode. - if (__first_ == __last_) [[unlikely]] - return __replacement_character; - - __result -= 0xd800; - __result <<= 10; - __result += *__first_++ - 0xdc00; - __result += 0x10000; - } - return __result; + if (__unicode::__is_low_surrogate(__value)) [[unlikely]] + return __consume_result_error; - } else if constexpr (sizeof(wchar_t) == 4) { - char32_t __result = *__first_++; - if (__result > 0x10FFFF) [[unlikely]] - return __replacement_character; - return __result; - } else { - __libcpp_unreachable(); - } - } + if (__unicode::__is_high_surrogate(__value)) { + if (__first_ == __last_ || !__unicode::__is_low_surrogate(static_cast<char32_t>(*__first_))) [[unlikely]] + return __consume_result_error; -# if _LIBCPP_STD_VER > 20 - _LIBCPP_HIDE_FROM_ABI constexpr __consume_p2286_result __consume_p2286() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + __value -= 0xd800; + __value <<= 10; + __value += static_cast<char32_t>(*__first_++) - 0xdc00; + __value += 0x10000; - char32_t __result = *__first_++; - if constexpr (sizeof(wchar_t) == 2) { - // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF - if (__is_surrogate_pair_high(__result)) { - // Malformed Unicode. - if (__first_ == __last_ || !__is_surrogate_pair_low(*(__first_ + 1))) [[unlikely]] - return {1, __result}; - - __result -= 0xd800; - __result <<= 10; - __result += *__first_++ - 0xdc00; - __result += 0x10000; - } else if (__is_surrogate_pair_low(__result)) - // A code point shouldn't start with the low surrogate pair - return {1, __result}; + if (!__unicode::__is_code_point(__value)) [[unlikely]] + return __consume_result_error; + } } else { - if (__result > 0x10FFFF) [[unlikely]] - return {1, __result}; + if (!__unicode::__is_scalar_value(__value)) [[unlikely]] + return __consume_result_error; } - return {0, __result}; + return {__value}; } -# endif // _LIBCPP_STD_VER > 20 private: - const wchar_t* __first_; - const wchar_t* __last_; + _Iterator __first_; + _Iterator __last_; }; # endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -310,8 +305,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __at_extended_grapheme_cluster_break( // *** Break at the start and end of text, unless the text is empty. *** - _LIBCPP_ASSERT(__prev != __property::__sot, "should be handled in the constructor"); // GB1 - _LIBCPP_ASSERT(__prev != __property::__eot, "should be handled by our caller"); // GB2 + _LIBCPP_ASSERT_UNCATEGORIZED(__prev != __property::__sot, "should be handled in the constructor"); // GB1 + _LIBCPP_ASSERT_UNCATEGORIZED(__prev != __property::__eot, "should be handled by our caller"); // GB2 // *** Do not break between a CR and LF. Otherwise, break before and after controls. *** if (__prev == __property::__CR && __next == __property::__LF) // GB3 @@ -384,10 +379,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __at_extended_grapheme_cluster_break( /// Therefore only this code point is extracted. template <class _CharT> class __extended_grapheme_cluster_view { + using _Iterator = typename basic_string_view<_CharT>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(const _CharT* __first, const _CharT* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(_Iterator __first, _Iterator __last) : __code_point_view_(__first, __last), - __next_code_point_(__code_point_view_.__consume()), + __next_code_point_(__code_point_view_.__consume().__code_point), __next_prop_(__extended_grapheme_custer_property_boundary::__get_property(__next_code_point_)) {} struct __cluster { @@ -401,13 +398,14 @@ public: /// /// It's expected the caller has the start position and thus can determine /// the code unit range of the extended grapheme cluster. - const _CharT* __last_; + _Iterator __last_; }; _LIBCPP_HIDE_FROM_ABI constexpr __cluster __consume() { - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_UNCATEGORIZED( __next_prop_ != __extended_grapheme_custer_property_boundary::__property::__eot, "can't move beyond the end of input"); + char32_t __code_point = __next_code_point_; if (!__code_point_view_.__at_end()) return {__code_point, __get_break()}; @@ -422,17 +420,17 @@ private: char32_t __next_code_point_; __extended_grapheme_custer_property_boundary::__property __next_prop_; - _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __get_break() { + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __get_break() { bool __ri_break_allowed = true; bool __has_extened_pictographic = false; while (true) { - const _CharT* __result = __code_point_view_.__position(); + _Iterator __result = __code_point_view_.__position(); __extended_grapheme_custer_property_boundary::__property __prev = __next_prop_; if (__code_point_view_.__at_end()) { __next_prop_ = __extended_grapheme_custer_property_boundary::__property::__eot; return __result; } - __next_code_point_ = __code_point_view_.__consume(); + __next_code_point_ = __code_point_view_.__consume().__code_point; __next_prop_ = __extended_grapheme_custer_property_boundary::__get_property(__next_code_point_); __has_extened_pictographic |= @@ -444,8 +442,8 @@ private: } }; -template <class _CharT> -__extended_grapheme_cluster_view(const _CharT*, const _CharT*) -> __extended_grapheme_cluster_view<_CharT>; +template <contiguous_iterator _Iterator> +__extended_grapheme_cluster_view(_Iterator, _Iterator) -> __extended_grapheme_cluster_view<iter_value_t<_Iterator>>; # else // _LIBCPP_HAS_NO_UNICODE @@ -453,36 +451,30 @@ __extended_grapheme_cluster_view(const _CharT*, const _CharT*) -> __extended_gra // This makes it easier to write code agnostic of the _LIBCPP_HAS_NO_UNICODE define. template <class _CharT> class __code_point_view { + using _Iterator = typename basic_string_view<_CharT>::const_iterator; + public: - _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(const _CharT* __first, const _CharT* __last) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) : __first_(__first), __last_(__last) {} _LIBCPP_HIDE_FROM_ABI constexpr bool __at_end() const noexcept { return __first_ == __last_; } - _LIBCPP_HIDE_FROM_ABI constexpr const _CharT* __position() const noexcept { return __first_; } - - _LIBCPP_HIDE_FROM_ABI constexpr char32_t __consume() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); - return *__first_++; - } - -# if _LIBCPP_STD_VER > 20 - _LIBCPP_HIDE_FROM_ABI constexpr __consume_p2286_result __consume_p2286() noexcept { - _LIBCPP_ASSERT(__first_ != __last_, "can't move beyond the end of input"); + _LIBCPP_HIDE_FROM_ABI constexpr _Iterator __position() const noexcept { return __first_; } - return {0, std::make_unsigned_t<_CharT>(*__first_++)}; + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __consume_result __consume() noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED(__first_ != __last_, "can't move beyond the end of input"); + return {static_cast<char32_t>(*__first_++)}; } -# endif // _LIBCPP_STD_VER > 20 private: - const _CharT* __first_; - const _CharT* __last_; + _Iterator __first_; + _Iterator __last_; }; # endif // _LIBCPP_HAS_NO_UNICODE } // namespace __unicode -#endif //_LIBCPP_STD_VER > 17 +#endif //_LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__format/width_estimation_table.h b/libcxx/include/__format/width_estimation_table.h new file mode 100644 index 000000000000..cfb488975d57 --- /dev/null +++ b/libcxx/include/__format/width_estimation_table.h @@ -0,0 +1,271 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// WARNING, this entire header is generated by +// utils/generate_width_estimation_table.py +// DO NOT MODIFY! + +// UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE +// +// See Terms of Use <https://www.unicode.org/copyright.html> +// for definitions of Unicode Inc.'s Data Files and Software. +// +// NOTICE TO USER: Carefully read the following legal agreement. +// BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +// DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +// YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +// TERMS AND CONDITIONS OF THIS AGREEMENT. +// IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +// THE DATA FILES OR SOFTWARE. +// +// COPYRIGHT AND PERMISSION NOTICE +// +// Copyright (c) 1991-2022 Unicode, Inc. All rights reserved. +// Distributed under the Terms of Use in https://www.unicode.org/copyright.html. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of the Unicode data files and any associated documentation +// (the "Data Files") or Unicode software and any associated documentation +// (the "Software") to deal in the Data Files or Software +// without restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, and/or sell copies of +// the Data Files or Software, and to permit persons to whom the Data Files +// or Software are furnished to do so, provided that either +// (a) this copyright and permission notice appear with all copies +// of the Data Files or Software, or +// (b) this copyright and permission notice appear in associated +// Documentation. +// +// THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT OF THIRD PARTY RIGHTS. +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +// NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +// DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THE DATA FILES OR SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder +// shall not be used in advertising or otherwise to promote the sale, +// use or other dealings in these Data Files or Software without prior +// written authorization of the copyright holder. + +#ifndef _LIBCPP___FORMAT_WIDTH_ESTIMATION_TABLE_H +#define _LIBCPP___FORMAT_WIDTH_ESTIMATION_TABLE_H + +#include <__algorithm/ranges_upper_bound.h> +#include <__config> +#include <cstddef> +#include <cstdint> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +namespace __width_estimation_table { + +/// The entries of the characters with an estimated width of 2. +/// +/// Contains the entries for [format.string.std]/12 +/// - Any code point with the East_Asian_Width="W" or East_Asian_Width="F" +/// Derived Extracted Property as described by UAX #44 +/// - U+4DC0 - U+4DFF (Yijing Hexagram Symbols) +/// - U+1F300 - U+1F5FF (Miscellaneous Symbols and Pictographs) +/// - U+1F900 - U+1F9FF (Supplemental Symbols and Pictographs) +/// +/// The data is generated from +/// - https://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt +/// - The "overrides" in [format.string.std]/12 +/// +/// The format of EastAsianWidth.txt is two fields separated by a semicolon. +/// Field 0: Unicode code point value or range of code point values +/// Field 1: East_Asian_Width property, consisting of one of the following values: +/// "A", "F", "H", "N", "Na", "W" +/// - All code points, assigned or unassigned, that are not listed +/// explicitly are given the value "N". +/// - The unassigned code points in the following blocks default to "W": +/// CJK Unified Ideographs Extension A: U+3400..U+4DBF +/// CJK Unified Ideographs: U+4E00..U+9FFF +/// CJK Compatibility Ideographs: U+F900..U+FAFF +/// - All undesignated code points in Planes 2 and 3, whether inside or +/// outside of allocated blocks, default to "W": +/// Plane 2: U+20000..U+2FFFD +/// Plane 3: U+30000..U+3FFFD +/// +/// The table is similar to the table +/// __extended_grapheme_custer_property_boundary::__entries +/// which explains the details of these classes. The only difference is this +/// table lacks a property, thus having more bits available for the size. +/// +/// The maximum code point that has an estimated width of 2 is U+3FFFD. This +/// value can be encoded in 18 bits. Thus the upper 3 bits of the code point +/// are always 0. These 3 bits are used to enlarge the offset range. This +/// optimization reduces the table in Unicode 15 from 184 to 104 entries, +/// saving 320 bytes. +/// +/// The data has 2 values: +/// - bits [0, 13] The size of the range, allowing 16384 elements. +/// - bits [14, 31] The lower bound code point of the range. The upper bound of +/// the range is lower bound + size. +inline constexpr uint32_t __entries[108] = { + 0x0440005f /* 00001100 - 0000115f [ 96] */, // + 0x08c68001 /* 0000231a - 0000231b [ 2] */, // + 0x08ca4001 /* 00002329 - 0000232a [ 2] */, // + 0x08fa4003 /* 000023e9 - 000023ec [ 4] */, // + 0x08fc0000 /* 000023f0 - 000023f0 [ 1] */, // + 0x08fcc000 /* 000023f3 - 000023f3 [ 1] */, // + 0x097f4001 /* 000025fd - 000025fe [ 2] */, // + 0x09850001 /* 00002614 - 00002615 [ 2] */, // + 0x0992000b /* 00002648 - 00002653 [ 12] */, // + 0x099fc000 /* 0000267f - 0000267f [ 1] */, // + 0x09a4c000 /* 00002693 - 00002693 [ 1] */, // + 0x09a84000 /* 000026a1 - 000026a1 [ 1] */, // + 0x09aa8001 /* 000026aa - 000026ab [ 2] */, // + 0x09af4001 /* 000026bd - 000026be [ 2] */, // + 0x09b10001 /* 000026c4 - 000026c5 [ 2] */, // + 0x09b38000 /* 000026ce - 000026ce [ 1] */, // + 0x09b50000 /* 000026d4 - 000026d4 [ 1] */, // + 0x09ba8000 /* 000026ea - 000026ea [ 1] */, // + 0x09bc8001 /* 000026f2 - 000026f3 [ 2] */, // + 0x09bd4000 /* 000026f5 - 000026f5 [ 1] */, // + 0x09be8000 /* 000026fa - 000026fa [ 1] */, // + 0x09bf4000 /* 000026fd - 000026fd [ 1] */, // + 0x09c14000 /* 00002705 - 00002705 [ 1] */, // + 0x09c28001 /* 0000270a - 0000270b [ 2] */, // + 0x09ca0000 /* 00002728 - 00002728 [ 1] */, // + 0x09d30000 /* 0000274c - 0000274c [ 1] */, // + 0x09d38000 /* 0000274e - 0000274e [ 1] */, // + 0x09d4c002 /* 00002753 - 00002755 [ 3] */, // + 0x09d5c000 /* 00002757 - 00002757 [ 1] */, // + 0x09e54002 /* 00002795 - 00002797 [ 3] */, // + 0x09ec0000 /* 000027b0 - 000027b0 [ 1] */, // + 0x09efc000 /* 000027bf - 000027bf [ 1] */, // + 0x0ac6c001 /* 00002b1b - 00002b1c [ 2] */, // + 0x0ad40000 /* 00002b50 - 00002b50 [ 1] */, // + 0x0ad54000 /* 00002b55 - 00002b55 [ 1] */, // + 0x0ba00019 /* 00002e80 - 00002e99 [ 26] */, // + 0x0ba6c058 /* 00002e9b - 00002ef3 [ 89] */, // + 0x0bc000d5 /* 00002f00 - 00002fd5 [ 214] */, // + 0x0bfc000b /* 00002ff0 - 00002ffb [ 12] */, // + 0x0c00003e /* 00003000 - 0000303e [ 63] */, // + 0x0c104055 /* 00003041 - 00003096 [ 86] */, // + 0x0c264066 /* 00003099 - 000030ff [ 103] */, // + 0x0c41402a /* 00003105 - 0000312f [ 43] */, // + 0x0c4c405d /* 00003131 - 0000318e [ 94] */, // + 0x0c640053 /* 00003190 - 000031e3 [ 84] */, // + 0x0c7c002e /* 000031f0 - 0000321e [ 47] */, // + 0x0c880027 /* 00003220 - 00003247 [ 40] */, // + 0x0c943fff /* 00003250 - 0000724f [16384] */, // + 0x1c94323c /* 00007250 - 0000a48c [12861] */, // + 0x29240036 /* 0000a490 - 0000a4c6 [ 55] */, // + 0x2a58001c /* 0000a960 - 0000a97c [ 29] */, // + 0x2b002ba3 /* 0000ac00 - 0000d7a3 [11172] */, // + 0x3e4001ff /* 0000f900 - 0000faff [ 512] */, // + 0x3f840009 /* 0000fe10 - 0000fe19 [ 10] */, // + 0x3f8c0022 /* 0000fe30 - 0000fe52 [ 35] */, // + 0x3f950012 /* 0000fe54 - 0000fe66 [ 19] */, // + 0x3f9a0003 /* 0000fe68 - 0000fe6b [ 4] */, // + 0x3fc0405f /* 0000ff01 - 0000ff60 [ 96] */, // + 0x3ff80006 /* 0000ffe0 - 0000ffe6 [ 7] */, // + 0x5bf80004 /* 00016fe0 - 00016fe4 [ 5] */, // + 0x5bfc0001 /* 00016ff0 - 00016ff1 [ 2] */, // + 0x5c0017f7 /* 00017000 - 000187f7 [ 6136] */, // + 0x620004d5 /* 00018800 - 00018cd5 [ 1238] */, // + 0x63400008 /* 00018d00 - 00018d08 [ 9] */, // + 0x6bfc0003 /* 0001aff0 - 0001aff3 [ 4] */, // + 0x6bfd4006 /* 0001aff5 - 0001affb [ 7] */, // + 0x6bff4001 /* 0001affd - 0001affe [ 2] */, // + 0x6c000122 /* 0001b000 - 0001b122 [ 291] */, // + 0x6c4c8000 /* 0001b132 - 0001b132 [ 1] */, // + 0x6c540002 /* 0001b150 - 0001b152 [ 3] */, // + 0x6c554000 /* 0001b155 - 0001b155 [ 1] */, // + 0x6c590003 /* 0001b164 - 0001b167 [ 4] */, // + 0x6c5c018b /* 0001b170 - 0001b2fb [ 396] */, // + 0x7c010000 /* 0001f004 - 0001f004 [ 1] */, // + 0x7c33c000 /* 0001f0cf - 0001f0cf [ 1] */, // + 0x7c638000 /* 0001f18e - 0001f18e [ 1] */, // + 0x7c644009 /* 0001f191 - 0001f19a [ 10] */, // + 0x7c800002 /* 0001f200 - 0001f202 [ 3] */, // + 0x7c84002b /* 0001f210 - 0001f23b [ 44] */, // + 0x7c900008 /* 0001f240 - 0001f248 [ 9] */, // + 0x7c940001 /* 0001f250 - 0001f251 [ 2] */, // + 0x7c980005 /* 0001f260 - 0001f265 [ 6] */, // + 0x7cc0034f /* 0001f300 - 0001f64f [ 848] */, // + 0x7da00045 /* 0001f680 - 0001f6c5 [ 70] */, // + 0x7db30000 /* 0001f6cc - 0001f6cc [ 1] */, // + 0x7db40002 /* 0001f6d0 - 0001f6d2 [ 3] */, // + 0x7db54002 /* 0001f6d5 - 0001f6d7 [ 3] */, // + 0x7db70003 /* 0001f6dc - 0001f6df [ 4] */, // + 0x7dbac001 /* 0001f6eb - 0001f6ec [ 2] */, // + 0x7dbd0008 /* 0001f6f4 - 0001f6fc [ 9] */, // + 0x7df8000b /* 0001f7e0 - 0001f7eb [ 12] */, // + 0x7dfc0000 /* 0001f7f0 - 0001f7f0 [ 1] */, // + 0x7e4000ff /* 0001f900 - 0001f9ff [ 256] */, // + 0x7e9c000c /* 0001fa70 - 0001fa7c [ 13] */, // + 0x7ea00008 /* 0001fa80 - 0001fa88 [ 9] */, // + 0x7ea4002d /* 0001fa90 - 0001fabd [ 46] */, // + 0x7eafc006 /* 0001fabf - 0001fac5 [ 7] */, // + 0x7eb3800d /* 0001face - 0001fadb [ 14] */, // + 0x7eb80008 /* 0001fae0 - 0001fae8 [ 9] */, // + 0x7ebc0008 /* 0001faf0 - 0001faf8 [ 9] */, // + 0x80003fff /* 00020000 - 00023fff [16384] */, // + 0x90003fff /* 00024000 - 00027fff [16384] */, // + 0xa0003fff /* 00028000 - 0002bfff [16384] */, // + 0xb0003ffd /* 0002c000 - 0002fffd [16382] */, // + 0xc0003fff /* 00030000 - 00033fff [16384] */, // + 0xd0003fff /* 00034000 - 00037fff [16384] */, // + 0xe0003fff /* 00038000 - 0003bfff [16384] */, // + 0xf0003ffd /* 0003c000 - 0003fffd [16382] */}; + +/// The upper bound entry of EastAsianWidth.txt. +/// +/// Values greater than this value may have more than 18 significant bits. +/// They always have a width of 1. This property makes it possible to store +/// the table in its compact form. +inline constexpr uint32_t __table_upper_bound = 0x0003fffd; + +/// Returns the estimated width of a Unicode code point. +/// +/// \pre The code point is a valid Unicode code point. +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int __estimated_width(const char32_t __code_point) noexcept { + // Since __table_upper_bound contains the unshifted range do the + // comparison without shifting. + if (__code_point > __table_upper_bound) [[unlikely]] + return 1; + + // When the code-point is less than the first element in the table + // the lookup is quite expensive. Since quite some scripts are in + // that range, it makes sense to validate that first. + // The std_format_spec_string_unicode benchmark gives a measurable + // improvement. + if (__code_point < (__entries[0] >> 14)) + return 1; + + ptrdiff_t __i = std::ranges::upper_bound(__entries, (__code_point << 14) | 0x3fffu) - __entries; + if (__i == 0) + return 1; + + --__i; + uint32_t __upper_bound = (__entries[__i] >> 14) + (__entries[__i] & 0x3fffu); + return 1 + (__code_point <= __upper_bound); +} + +} // namespace __width_estimation_table + +#endif //_LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_WIDTH_ESTIMATION_TABLE_H diff --git a/libcxx/include/__format/write_escaped.h b/libcxx/include/__format/write_escaped.h new file mode 100644 index 000000000000..8c51d0b1f148 --- /dev/null +++ b/libcxx/include/__format/write_escaped.h @@ -0,0 +1,222 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_WRITE_ESCAPED_H +#define _LIBCPP___FORMAT_WRITE_ESCAPED_H + +#include <__algorithm/ranges_copy.h> +#include <__algorithm/ranges_for_each.h> +#include <__charconv/to_chars_integral.h> +#include <__charconv/to_chars_result.h> +#include <__chrono/statically_widen.h> +#include <__format/escaped_output_table.h> +#include <__format/formatter_output.h> +#include <__format/parser_std_format_spec.h> +#include <__format/unicode.h> +#include <__iterator/back_insert_iterator.h> +#include <__memory/addressof.h> +#include <__system_error/errc.h> +#include <__type_traits/make_unsigned.h> +#include <__utility/move.h> +#include <string_view> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + + +namespace __formatter { + +#if _LIBCPP_STD_VER >= 20 + +/// Writes a string using format's width estimation algorithm. +/// +/// \note When \c _LIBCPP_HAS_NO_UNICODE is defined the function assumes the +/// input is ASCII. +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI auto __write_string( + basic_string_view<_CharT> __str, + output_iterator<const _CharT&> auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + if (!__specs.__has_precision()) + return __formatter::__write_string_no_precision(__str, _VSTD::move(__out_it), __specs); + + int __size = __formatter::__truncate(__str, __specs.__precision_); + + return __formatter::__write(__str.begin(), __str.end(), _VSTD::move(__out_it), __specs, __size); +} + +# endif // _LIBCPP_STD_VER >= 20 +# if _LIBCPP_STD_VER >= 23 + +struct __nul_terminator {}; + +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI bool operator==(const _CharT* __cstr, __nul_terminator) { + return *__cstr == _CharT('\0'); +} + +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI void +__write_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value, const _CharT* __prefix) { + back_insert_iterator __out_it{__str}; + std::ranges::copy(__prefix, __nul_terminator{}, __out_it); + + char __buffer[8]; + to_chars_result __r = std::to_chars(std::begin(__buffer), std::end(__buffer), __value, 16); + _LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small"); + std::ranges::copy(std::begin(__buffer), __r.ptr, __out_it); + + __str += _CharT('}'); +} + +// [format.string.escaped]/2.2.1.2 +// ... +// then the sequence \u{hex-digit-sequence} is appended to E, where +// hex-digit-sequence is the shortest hexadecimal representation of C using +// lower-case hexadecimal digits. +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI void __write_well_formed_escaped_code_unit(basic_string<_CharT>& __str, char32_t __value) { + __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\u{")); +} + +// [format.string.escaped]/2.2.3 +// Otherwise (X is a sequence of ill-formed code units), each code unit U is +// appended to E in order as the sequence \x{hex-digit-sequence}, where +// hex-digit-sequence is the shortest hexadecimal representation of U using +// lower-case hexadecimal digits. +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI void __write_escape_ill_formed_code_unit(basic_string<_CharT>& __str, char32_t __value) { + __formatter::__write_escaped_code_unit(__str, __value, _LIBCPP_STATICALLY_WIDEN(_CharT, "\\x{")); +} + +template <class _CharT> +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool __is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value) { +# ifdef _LIBCPP_HAS_NO_UNICODE + // For ASCII assume everything above 127 is printable. + if (__value > 127) + return false; +# endif + + if (!__escaped_output_table::__needs_escape(__value)) + return false; + + __formatter::__write_well_formed_escaped_code_unit(__str, __value); + return true; +} + +template <class _CharT> +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr char32_t __to_char32(_CharT __value) { + return static_cast<make_unsigned_t<_CharT>>(__value); +} + +enum class _LIBCPP_ENUM_VIS __escape_quotation_mark { __apostrophe, __double_quote }; + +// [format.string.escaped]/2 +template <class _CharT> +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool +__is_escaped_sequence_written(basic_string<_CharT>& __str, char32_t __value, __escape_quotation_mark __mark) { + // 2.2.1.1 - Mapped character in [tab:format.escape.sequences] + switch (__value) { + case _CharT('\t'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\t"); + return true; + case _CharT('\n'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\n"); + return true; + case _CharT('\r'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, "\\r"); + return true; + case _CharT('\''): + if (__mark == __escape_quotation_mark::__apostrophe) + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\')"); + else + __str += __value; + return true; + case _CharT('"'): + if (__mark == __escape_quotation_mark::__double_quote) + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\")"); + else + __str += __value; + return true; + case _CharT('\\'): + __str += _LIBCPP_STATICALLY_WIDEN(_CharT, R"(\\)"); + return true; + + // 2.2.1.2 - Space + case _CharT(' '): + __str += __value; + return true; + } + + // 2.2.2 + // Otherwise, if X is a shift sequence, the effect on E and further + // decoding of S is unspecified. + // For now shift sequences are ignored and treated as Unicode. Other parts + // of the format library do the same. It's unknown how ostream treats them. + // TODO FMT determine what to do with shift sequences. + + // 2.2.1.2.1 and 2.2.1.2.2 - Escape + return __formatter::__is_escaped_sequence_written(__str, __formatter::__to_char32(__value)); +} + +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI void +__escape(basic_string<_CharT>& __str, basic_string_view<_CharT> __values, __escape_quotation_mark __mark) { + __unicode::__code_point_view<_CharT> __view{__values.begin(), __values.end()}; + + while (!__view.__at_end()) { + auto __first = __view.__position(); + typename __unicode::__consume_result __result = __view.__consume(); + if (__result.__status == __unicode::__consume_result::__ok) { + if (!__formatter::__is_escaped_sequence_written(__str, __result.__code_point, __mark)) + // 2.2.1.3 - Add the character + ranges::copy(__first, __view.__position(), std::back_insert_iterator(__str)); + } else { + // 2.2.3 sequence of ill-formed code units + ranges::for_each(__first, __view.__position(), [&](_CharT __value) { + __formatter::__write_escape_ill_formed_code_unit(__str, __formatter::__to_char32(__value)); + }); + } + } +} + +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI auto +__format_escaped_char(_CharT __value, + output_iterator<const _CharT&> auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + basic_string<_CharT> __str; + __str += _CharT('\''); + __formatter::__escape(__str, basic_string_view{std::addressof(__value), 1}, __escape_quotation_mark::__apostrophe); + __str += _CharT('\''); + return __formatter::__write(__str.data(), __str.data() + __str.size(), _VSTD::move(__out_it), __specs, __str.size()); +} + +template <class _CharT> +_LIBCPP_HIDE_FROM_ABI auto +__format_escaped_string(basic_string_view<_CharT> __values, + output_iterator<const _CharT&> auto __out_it, + __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) { + basic_string<_CharT> __str; + __str += _CharT('"'); + __formatter::__escape(__str, __values, __escape_quotation_mark::__double_quote); + __str += _CharT('"'); + return __formatter::__write_string(basic_string_view{__str}, _VSTD::move(__out_it), __specs); +} + +# endif // _LIBCPP_STD_VER >= 23 + +} // namespace __formatter + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_WRITE_ESCAPED_H diff --git a/libcxx/include/__functional/bind.h b/libcxx/include/__functional/bind.h index 297e4e5103a3..398cb3dc3480 100644 --- a/libcxx/include/__functional/bind.h +++ b/libcxx/include/__functional/bind.h @@ -13,9 +13,11 @@ #include <__config> #include <__functional/invoke.h> #include <__functional/weak_result_type.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_reference_wrapper.h> +#include <__type_traits/is_void.h> #include <cstddef> #include <tuple> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -30,9 +32,9 @@ struct is_bind_expression : _If< is_bind_expression<__remove_cvref_t<_Tp> > > {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> -inline constexpr size_t is_bind_expression_v = is_bind_expression<_Tp>::value; +inline constexpr bool is_bind_expression_v = is_bind_expression<_Tp>::value; #endif template<class _Tp> @@ -42,9 +44,9 @@ struct is_placeholder : _If< is_placeholder<__remove_cvref_t<_Tp> > > {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> -inline constexpr size_t is_placeholder_v = is_placeholder<_Tp>::value; +inline constexpr int is_placeholder_v = is_placeholder<_Tp>::value; #endif namespace placeholders @@ -52,29 +54,24 @@ namespace placeholders template <int _Np> struct __ph {}; -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) -_LIBCPP_FUNC_VIS extern const __ph<1> _1; -_LIBCPP_FUNC_VIS extern const __ph<2> _2; -_LIBCPP_FUNC_VIS extern const __ph<3> _3; -_LIBCPP_FUNC_VIS extern const __ph<4> _4; -_LIBCPP_FUNC_VIS extern const __ph<5> _5; -_LIBCPP_FUNC_VIS extern const __ph<6> _6; -_LIBCPP_FUNC_VIS extern const __ph<7> _7; -_LIBCPP_FUNC_VIS extern const __ph<8> _8; -_LIBCPP_FUNC_VIS extern const __ph<9> _9; -_LIBCPP_FUNC_VIS extern const __ph<10> _10; -#else -/* inline */ constexpr __ph<1> _1{}; -/* inline */ constexpr __ph<2> _2{}; -/* inline */ constexpr __ph<3> _3{}; -/* inline */ constexpr __ph<4> _4{}; -/* inline */ constexpr __ph<5> _5{}; -/* inline */ constexpr __ph<6> _6{}; -/* inline */ constexpr __ph<7> _7{}; -/* inline */ constexpr __ph<8> _8{}; -/* inline */ constexpr __ph<9> _9{}; -/* inline */ constexpr __ph<10> _10{}; -#endif // defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) +// C++17 recommends that we implement placeholders as `inline constexpr`, but allows +// implementing them as `extern <implementation-defined>`. Libc++ implements them as +// `extern const` in all standard modes to avoid an ABI break in C++03: making them +// `inline constexpr` requires removing their definition in the shared library to +// avoid ODR violations, which is an ABI break. +// +// In practice, since placeholders are empty, `extern const` is almost impossible +// to distinguish from `inline constexpr` from a usage stand point. +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<1> _1; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<2> _2; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<3> _3; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<4> _4; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<5> _5; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<6> _6; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<7> _7; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<8> _8; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<9> _9; +_LIBCPP_EXPORTED_FROM_ABI extern const __ph<10> _10; } // namespace placeholders @@ -86,7 +83,7 @@ struct is_placeholder<placeholders::__ph<_Np> > #ifndef _LIBCPP_CXX03_LANG template <class _Tp, class _Uj> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __mu(reference_wrapper<_Tp> __t, _Uj&) { @@ -94,7 +91,7 @@ __mu(reference_wrapper<_Tp> __t, _Uj&) } template <class _Ti, class ..._Uj, size_t ..._Indx> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<_Ti&, _Uj...>::type __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) { @@ -102,7 +99,7 @@ __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) } template <class _Ti, class ..._Uj> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __enable_if_t < is_bind_expression<_Ti>::value, @@ -124,7 +121,7 @@ struct __mu_return2<true, _Ti, _Uj> }; template <class _Ti, class _Uj> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < 0 < is_placeholder<_Ti>::value, @@ -132,12 +129,12 @@ typename enable_if >::type __mu(_Ti&, _Uj& __uj) { - const size_t _Indx = is_placeholder<_Ti>::value - 1; - return _VSTD::forward<typename tuple_element<_Indx, _Uj>::type>(_VSTD::get<_Indx>(__uj)); + const size_t __indx = is_placeholder<_Ti>::value - 1; + return _VSTD::forward<typename tuple_element<__indx, _Uj>::type>(_VSTD::get<__indx>(__uj)); } template <class _Ti, class _Uj> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < !is_bind_expression<_Ti>::value && @@ -255,7 +252,7 @@ struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> }; template <class _Fp, class _BoundArgs, size_t ..._Indx, class _Args> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __bind_return<_Fp, _BoundArgs, _Args>::type __apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, _Args&& __args) @@ -264,11 +261,11 @@ __apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, } template<class _Fp, class ..._BoundArgs> -class __bind : public __weak_result_type<typename decay<_Fp>::type> +class __bind : public __weak_result_type<__decay_t<_Fp> > { protected: - typedef typename decay<_Fp>::type _Fd; - typedef tuple<typename decay<_BoundArgs>::type...> _Td; + using _Fd = __decay_t<_Fp>; + typedef tuple<__decay_t<_BoundArgs>...> _Td; private: _Fd __f_; _Td __bound_args_; diff --git a/libcxx/include/__functional/bind_back.h b/libcxx/include/__functional/bind_back.h index f0a6e49875a3..71dc63c86bdb 100644 --- a/libcxx/include/__functional/bind_back.h +++ b/libcxx/include/__functional/bind_back.h @@ -13,10 +13,10 @@ #include <__config> #include <__functional/invoke.h> #include <__functional/perfect_forward.h> +#include <__type_traits/decay.h> #include <__utility/forward.h> #include <__utility/integer_sequence.h> #include <tuple> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <size_t _NBound, class = make_index_sequence<_NBound>> struct __bind_back_op; @@ -57,7 +57,7 @@ constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) -> decltype( __bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(_VSTD::forward<_Fn>(__f), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...))) { return __bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(_VSTD::forward<_Fn>(__f), _VSTD::forward_as_tuple(_VSTD::forward<_Args>(__args)...)); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/bind_front.h b/libcxx/include/__functional/bind_front.h index 22fb3a69dc75..72bb66480959 100644 --- a/libcxx/include/__functional/bind_front.h +++ b/libcxx/include/__functional/bind_front.h @@ -13,8 +13,12 @@ #include <__config> #include <__functional/invoke.h> #include <__functional/perfect_forward.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_move_constructible.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct __bind_front_op { template <class ..._Args> @@ -51,7 +55,7 @@ constexpr auto bind_front(_Fn&& __f, _Args&&... __args) { return __bind_front_t<decay_t<_Fn>, decay_t<_Args>...>(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/binder1st.h b/libcxx/include/__functional/binder1st.h index dea22c70e1f2..78049d13f922 100644 --- a/libcxx/include/__functional/binder1st.h +++ b/libcxx/include/__functional/binder1st.h @@ -21,30 +21,30 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) -template <class __Operation> +template <class _Operation> class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder1st - : public __unary_function<typename __Operation::second_argument_type, typename __Operation::result_type> + : public __unary_function<typename _Operation::second_argument_type, typename _Operation::result_type> { protected: - __Operation op; - typename __Operation::first_argument_type value; + _Operation op; + typename _Operation::first_argument_type value; public: - _LIBCPP_INLINE_VISIBILITY binder1st(const __Operation& __x, - const typename __Operation::first_argument_type __y) + _LIBCPP_INLINE_VISIBILITY binder1st(const _Operation& __x, + const typename _Operation::first_argument_type __y) : op(__x), value(__y) {} - _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() - (typename __Operation::second_argument_type& __x) const + _LIBCPP_INLINE_VISIBILITY typename _Operation::result_type operator() + (typename _Operation::second_argument_type& __x) const {return op(value, __x);} - _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() - (const typename __Operation::second_argument_type& __x) const + _LIBCPP_INLINE_VISIBILITY typename _Operation::result_type operator() + (const typename _Operation::second_argument_type& __x) const {return op(value, __x);} }; -template <class __Operation, class _Tp> +template <class _Operation, class _Tp> _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY -binder1st<__Operation> -bind1st(const __Operation& __op, const _Tp& __x) - {return binder1st<__Operation>(__op, __x);} +binder1st<_Operation> +bind1st(const _Operation& __op, const _Tp& __x) + {return binder1st<_Operation>(__op, __x);} #endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) diff --git a/libcxx/include/__functional/binder2nd.h b/libcxx/include/__functional/binder2nd.h index c98a146b6a66..a3227745bcb9 100644 --- a/libcxx/include/__functional/binder2nd.h +++ b/libcxx/include/__functional/binder2nd.h @@ -21,30 +21,30 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) -template <class __Operation> +template <class _Operation> class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 binder2nd - : public __unary_function<typename __Operation::first_argument_type, typename __Operation::result_type> + : public __unary_function<typename _Operation::first_argument_type, typename _Operation::result_type> { protected: - __Operation op; - typename __Operation::second_argument_type value; + _Operation op; + typename _Operation::second_argument_type value; public: _LIBCPP_INLINE_VISIBILITY - binder2nd(const __Operation& __x, const typename __Operation::second_argument_type __y) + binder2nd(const _Operation& __x, const typename _Operation::second_argument_type __y) : op(__x), value(__y) {} - _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() - ( typename __Operation::first_argument_type& __x) const + _LIBCPP_INLINE_VISIBILITY typename _Operation::result_type operator() + ( typename _Operation::first_argument_type& __x) const {return op(__x, value);} - _LIBCPP_INLINE_VISIBILITY typename __Operation::result_type operator() - (const typename __Operation::first_argument_type& __x) const + _LIBCPP_INLINE_VISIBILITY typename _Operation::result_type operator() + (const typename _Operation::first_argument_type& __x) const {return op(__x, value);} }; -template <class __Operation, class _Tp> +template <class _Operation, class _Tp> _LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY -binder2nd<__Operation> -bind2nd(const __Operation& __op, const _Tp& __x) - {return binder2nd<__Operation>(__op, __x);} +binder2nd<_Operation> +bind2nd(const _Operation& __op, const _Tp& __x) + {return binder2nd<_Operation>(__op, __x);} #endif // _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_BINDERS) diff --git a/libcxx/include/__functional/boyer_moore_searcher.h b/libcxx/include/__functional/boyer_moore_searcher.h index a6750893ee57..0165e062810f 100644 --- a/libcxx/include/__functional/boyer_moore_searcher.h +++ b/libcxx/include/__functional/boyer_moore_searcher.h @@ -20,12 +20,13 @@ #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__memory/shared_ptr.h> +#include <__type_traits/make_unsigned.h> #include <__utility/pair.h> #include <array> #include <unordered_map> #include <vector> -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_PUSH_MACROS #include <__undef_macros> @@ -113,6 +114,7 @@ private: && is_same_v<_BinaryPredicate, equal_to<>>>; public: + _LIBCPP_HIDE_FROM_ABI boyer_moore_searcher(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _Hash __hash = _Hash(), @@ -134,7 +136,7 @@ public: } template <class _RandomAccessIterator2> - pair<_RandomAccessIterator2, _RandomAccessIterator2> + _LIBCPP_HIDE_FROM_ABI pair<_RandomAccessIterator2, _RandomAccessIterator2> operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const { static_assert(__is_same_uncvref<typename iterator_traits<_RandomAccessIterator1>::value_type, typename iterator_traits<_RandomAccessIterator2>::value_type>::value, @@ -158,7 +160,7 @@ private: shared_ptr<difference_type[]> __suffix_; template <class _RandomAccessIterator2> - pair<_RandomAccessIterator2, _RandomAccessIterator2> + _LIBCPP_HIDE_FROM_ABI pair<_RandomAccessIterator2, _RandomAccessIterator2> __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const { _RandomAccessIterator2 __current = __f; const _RandomAccessIterator2 __last = __l - __pattern_length_; @@ -183,7 +185,8 @@ private: } template <class _Iterator, class _Container> - void __compute_bm_prefix(_Iterator __first, _Iterator __last, _BinaryPredicate __pred, _Container& __prefix) { + _LIBCPP_HIDE_FROM_ABI void + __compute_bm_prefix(_Iterator __first, _Iterator __last, _BinaryPredicate __pred, _Container& __prefix) { const size_t __count = __last - __first; __prefix[0] = 0; @@ -199,7 +202,8 @@ private: } } - void __build_suffix_table(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _BinaryPredicate __pred) { + _LIBCPP_HIDE_FROM_ABI void + __build_suffix_table(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _BinaryPredicate __pred) { const size_t __count = __last - __first; if (__count == 0) @@ -241,6 +245,7 @@ private: && is_same_v<_Hash, hash<value_type>> && is_same_v<_BinaryPredicate, equal_to<>>>; public: + _LIBCPP_HIDE_FROM_ABI boyer_moore_horspool_searcher(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _Hash __hash = _Hash(), @@ -262,7 +267,7 @@ public: } template <class _RandomAccessIterator2> - pair<_RandomAccessIterator2, _RandomAccessIterator2> + _LIBCPP_HIDE_FROM_ABI pair<_RandomAccessIterator2, _RandomAccessIterator2> operator()(_RandomAccessIterator2 __first, _RandomAccessIterator2 __last) const { static_assert(__is_same_uncvref<typename std::iterator_traits<_RandomAccessIterator1>::value_type, typename std::iterator_traits<_RandomAccessIterator2>::value_type>::value, @@ -286,7 +291,7 @@ private: shared_ptr<__skip_table_type> __skip_table_; template <class _RandomAccessIterator2> - pair<_RandomAccessIterator2, _RandomAccessIterator2> + _LIBCPP_HIDE_FROM_ABI pair<_RandomAccessIterator2, _RandomAccessIterator2> __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const { _RandomAccessIterator2 __current = __f; const _RandomAccessIterator2 __last = __l - __pattern_length_; @@ -310,6 +315,6 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___FUNCTIONAL_BOYER_MOORE_SEARCHER_H diff --git a/libcxx/include/__functional/compose.h b/libcxx/include/__functional/compose.h index 25213f28b1f2..80fcd7076c83 100644 --- a/libcxx/include/__functional/compose.h +++ b/libcxx/include/__functional/compose.h @@ -13,8 +13,8 @@ #include <__config> #include <__functional/invoke.h> #include <__functional/perfect_forward.h> +#include <__type_traits/decay.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct __compose_op { template<class _Fn1, class _Fn2, class ..._Args> @@ -45,7 +45,7 @@ constexpr auto __compose(_Fn1&& __f1, _Fn2&& __f2) -> decltype( __compose_t<decay_t<_Fn1>, decay_t<_Fn2>>(_VSTD::forward<_Fn1>(__f1), _VSTD::forward<_Fn2>(__f2))) { return __compose_t<decay_t<_Fn1>, decay_t<_Fn2>>(_VSTD::forward<_Fn1>(__f1), _VSTD::forward<_Fn2>(__f2)); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/default_searcher.h b/libcxx/include/__functional/default_searcher.h index e4151e589f78..222b4c66e6c6 100644 --- a/libcxx/include/__functional/default_searcher.h +++ b/libcxx/include/__functional/default_searcher.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 // default searcher template<class _ForwardIterator, class _BinaryPredicate = equal_to<>> @@ -50,7 +50,7 @@ private: }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(default_searcher); -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h index ca79d334a028..3c6e3f450d8b 100644 --- a/libcxx/include/__functional/function.h +++ b/libcxx/include/__functional/function.h @@ -12,6 +12,7 @@ #include <__assert> #include <__config> +#include <__exception/exception.h> #include <__functional/binary_function.h> #include <__functional/invoke.h> #include <__functional/unary_function.h> @@ -23,15 +24,21 @@ #include <__memory/builtin_new_allocator.h> #include <__memory/compressed_pair.h> #include <__memory/unique_ptr.h> +#include <__type_traits/aligned_storage.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_core_convertible.h> +#include <__type_traits/is_scalar.h> +#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_trivially_destructible.h> +#include <__type_traits/is_void.h> #include <__type_traits/strip_signature.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/piecewise_construct.h> #include <__utility/swap.h> -#include <exception> +#include <__verbose_abort> #include <new> #include <tuple> -#include <type_traits> #include <typeinfo> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -46,7 +53,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables") -class _LIBCPP_EXCEPTION_ABI bad_function_call +class _LIBCPP_EXPORTED_FROM_ABI bad_function_call : public exception { public: @@ -56,7 +63,7 @@ public: #ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION ~bad_function_call() _NOEXCEPT override; #else - ~bad_function_call() _NOEXCEPT override {} + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_function_call() _NOEXCEPT override {} #endif #ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE @@ -68,10 +75,10 @@ _LIBCPP_DIAGNOSTIC_POP _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_function_call() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_function_call(); #else - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("bad_function_call was thrown in -fno-exceptions mode"); #endif } @@ -201,7 +208,7 @@ class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> _LIBCPP_INLINE_VISIBILITY void destroy() _NOEXCEPT { __f_.~__compressed_pair<_Target, _Alloc>(); } - static void __destroy_and_delete(__alloc_func* __f) { + _LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__alloc_func* __f) { typedef allocator_traits<_Alloc> __alloc_traits; typedef __rebind_alloc<__alloc_traits, __alloc_func> _FunAlloc; _FunAlloc __a(__f->__get_allocator()); @@ -245,7 +252,7 @@ public: _LIBCPP_INLINE_VISIBILITY void destroy() _NOEXCEPT { __f_.~_Target(); } - static void __destroy_and_delete(__default_alloc_func* __f) { + _LIBCPP_HIDE_FROM_ABI static void __destroy_and_delete(__default_alloc_func* __f) { __f->destroy(); __builtin_new_allocator::__deallocate_type<__default_alloc_func>(__f, 1); } @@ -268,10 +275,10 @@ public: virtual void destroy() _NOEXCEPT = 0; virtual void destroy_deallocate() _NOEXCEPT = 0; virtual _Rp operator()(_ArgTypes&& ...) = 0; -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI virtual const void* target(const type_info&) const _NOEXCEPT = 0; virtual const std::type_info& target_type() const _NOEXCEPT = 0; -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; // __func implements __base for a given functor type. @@ -300,15 +307,15 @@ public: explicit __func(_Fp&& __f, _Alloc&& __a) : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} - virtual __base<_Rp(_ArgTypes...)>* __clone() const; - virtual void __clone(__base<_Rp(_ArgTypes...)>*) const; - virtual void destroy() _NOEXCEPT; - virtual void destroy_deallocate() _NOEXCEPT; - virtual _Rp operator()(_ArgTypes&&... __arg); -#ifndef _LIBCPP_NO_RTTI - virtual const void* target(const type_info&) const _NOEXCEPT; - virtual const std::type_info& target_type() const _NOEXCEPT; -#endif // _LIBCPP_NO_RTTI + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual __base<_Rp(_ArgTypes...)>* __clone() const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __clone(__base<_Rp(_ArgTypes...)>*) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy_deallocate() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual _Rp operator()(_ArgTypes&&... __arg); +#ifndef _LIBCPP_HAS_NO_RTTI + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const void* target(const type_info&) const _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const std::type_info& target_type() const _NOEXCEPT; +#endif // _LIBCPP_HAS_NO_RTTI }; template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> @@ -356,7 +363,7 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg) return __f_(_VSTD::forward<_ArgTypes>(__arg)...); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> const void* @@ -374,7 +381,7 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT return typeid(_Fp); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI // __value_func creates a value-type from a __func. @@ -389,7 +396,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> typedef __base<_Rp(_ArgTypes...)> __func; __func* __f_; - _LIBCPP_NO_CFI static __func* __as_base(void* __p) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI static __func* __as_base(void* __p) { return reinterpret_cast<__func*>(__p); } @@ -427,7 +434,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> } template <class _Fp, - class = typename enable_if<!is_same<typename decay<_Fp>::type, __value_func>::value>::type> + class = typename enable_if<!is_same<__decay_t<_Fp>, __value_func>::value>::type> _LIBCPP_INLINE_VISIBILITY explicit __value_func(_Fp&& __f) : __value_func(_VSTD::forward<_Fp>(__f), allocator<_Fp>()) {} @@ -553,7 +560,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT { return __f_ != nullptr; } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI _LIBCPP_INLINE_VISIBILITY const std::type_info& target_type() const _NOEXCEPT { @@ -569,7 +576,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)> return nullptr; return (const _Tp*)__f_->target(typeid(_Tp)); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; // Storage for a functor object, to be used with __policy to manage copy and @@ -614,56 +621,57 @@ struct __policy _LIBCPP_INLINE_VISIBILITY static const __policy* __create_empty() { - static const _LIBCPP_CONSTEXPR __policy __policy_ = {nullptr, nullptr, - true, -#ifndef _LIBCPP_NO_RTTI - &typeid(void) + static const _LIBCPP_CONSTEXPR __policy __policy = {nullptr, nullptr, + true, +#ifndef _LIBCPP_HAS_NO_RTTI + &typeid(void) #else - nullptr + nullptr #endif }; - return &__policy_; + return &__policy; } private: - template <typename _Fun> static void* __large_clone(const void* __s) + template <typename _Fun> + _LIBCPP_HIDE_FROM_ABI static void* __large_clone(const void* __s) { const _Fun* __f = static_cast<const _Fun*>(__s); return __f->__clone(); } template <typename _Fun> - static void __large_destroy(void* __s) { + _LIBCPP_HIDE_FROM_ABI static void __large_destroy(void* __s) { _Fun::__destroy_and_delete(static_cast<_Fun*>(__s)); } template <typename _Fun> _LIBCPP_INLINE_VISIBILITY static const __policy* __choose_policy(/* is_small = */ false_type) { - static const _LIBCPP_CONSTEXPR __policy __policy_ = { + static const _LIBCPP_CONSTEXPR __policy __policy = { &__large_clone<_Fun>, &__large_destroy<_Fun>, false, -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI &typeid(typename _Fun::_Target) #else nullptr #endif }; - return &__policy_; + return &__policy; } template <typename _Fun> _LIBCPP_INLINE_VISIBILITY static const __policy* __choose_policy(/* is_small = */ true_type) { - static const _LIBCPP_CONSTEXPR __policy __policy_ = { + static const _LIBCPP_CONSTEXPR __policy __policy = { nullptr, nullptr, false, -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI &typeid(typename _Fun::_Target) #else nullptr #endif }; - return &__policy_; + return &__policy; } }; @@ -699,14 +707,14 @@ struct __policy_invoker<_Rp(_ArgTypes...)> _LIBCPP_INLINE_VISIBILITY explicit __policy_invoker(__Call __c) : __call_(__c) {} - static _Rp __call_empty(const __policy_storage*, + _LIBCPP_HIDE_FROM_ABI static _Rp __call_empty(const __policy_storage*, __fast_forward<_ArgTypes>...) { __throw_bad_function_call(); } template <typename _Fun> - static _Rp __call_impl(const __policy_storage* __buf, + _LIBCPP_HIDE_FROM_ABI static _Rp __call_impl(const __policy_storage* __buf, __fast_forward<_ArgTypes>... __args) { _Fun* __f = reinterpret_cast<_Fun*>(__use_small_storage<_Fun>::value @@ -770,7 +778,7 @@ template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)> } } - template <class _Fp, class = typename enable_if<!is_same<typename decay<_Fp>::type, __policy_func>::value>::type> + template <class _Fp, class = typename enable_if<!is_same<__decay_t<_Fp>, __policy_func>::value>::type> _LIBCPP_INLINE_VISIBILITY explicit __policy_func(_Fp&& __f) : __policy_(__policy::__create_empty()) { typedef __default_alloc_func<_Fp, _Rp(_ArgTypes...)> _Fun; @@ -861,7 +869,7 @@ template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)> return !__policy_->__is_null; } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI _LIBCPP_INLINE_VISIBILITY const std::type_info& target_type() const _NOEXCEPT { @@ -878,7 +886,7 @@ template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)> else return reinterpret_cast<const _Tp*>(&__buf_.__small); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; #if defined(_LIBCPP_HAS_BLOCKS_RUNTIME) @@ -915,7 +923,7 @@ public: { } virtual __base<_Rp(_ArgTypes...)>* __clone() const { - _LIBCPP_ASSERT(false, + _LIBCPP_ASSERT_INTERNAL(false, "Block pointers are just pointers, so they should always fit into " "std::function's small buffer optimization. This function should " "never be invoked."); @@ -935,7 +943,7 @@ public: } virtual void destroy_deallocate() _NOEXCEPT { - _LIBCPP_ASSERT(false, + _LIBCPP_ASSERT_INTERNAL(false, "Block pointers are just pointers, so they should always fit into " "std::function's small buffer optimization. This function should " "never be invoked."); @@ -945,7 +953,7 @@ public: return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__arg)...); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI virtual const void* target(type_info const& __ti) const _NOEXCEPT { if (__ti == typeid(__func::__block_type)) return &__f_; @@ -955,7 +963,7 @@ public: virtual const std::type_info& target_type() const _NOEXCEPT { return typeid(__func::__block_type); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI }; #endif // _LIBCPP_HAS_EXTENSION_BLOCKS @@ -1002,11 +1010,11 @@ public: _LIBCPP_INLINE_VISIBILITY function() _NOEXCEPT { } _LIBCPP_INLINE_VISIBILITY - function(nullptr_t) _NOEXCEPT {} - function(const function&); - function(function&&) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI function(nullptr_t) _NOEXCEPT {} + _LIBCPP_HIDE_FROM_ABI function(const function&); + _LIBCPP_HIDE_FROM_ABI function(function&&) _NOEXCEPT; template<class _Fp, class = _EnableIfLValueCallable<_Fp>> - function(_Fp); + _LIBCPP_HIDE_FROM_ABI function(_Fp); #if _LIBCPP_STD_VER <= 14 template<class _Alloc> @@ -1016,23 +1024,23 @@ public: _LIBCPP_INLINE_VISIBILITY function(allocator_arg_t, const _Alloc&, nullptr_t) _NOEXCEPT {} template<class _Alloc> - function(allocator_arg_t, const _Alloc&, const function&); + _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc&, const function&); template<class _Alloc> - function(allocator_arg_t, const _Alloc&, function&&); + _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc&, function&&); template<class _Fp, class _Alloc, class = _EnableIfLValueCallable<_Fp>> - function(allocator_arg_t, const _Alloc& __a, _Fp __f); + _LIBCPP_HIDE_FROM_ABI function(allocator_arg_t, const _Alloc& __a, _Fp __f); #endif - function& operator=(const function&); - function& operator=(function&&) _NOEXCEPT; - function& operator=(nullptr_t) _NOEXCEPT; - template<class _Fp, class = _EnableIfLValueCallable<typename decay<_Fp>::type>> - function& operator=(_Fp&&); + _LIBCPP_HIDE_FROM_ABI function& operator=(const function&); + _LIBCPP_HIDE_FROM_ABI function& operator=(function&&) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI function& operator=(nullptr_t) _NOEXCEPT; + template<class _Fp, class = _EnableIfLValueCallable<__decay_t<_Fp>>> + _LIBCPP_HIDE_FROM_ABI function& operator=(_Fp&&); - ~function(); + _LIBCPP_HIDE_FROM_ABI ~function(); // function modifiers: - void swap(function&) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void swap(function&) _NOEXCEPT; #if _LIBCPP_STD_VER <= 14 template<class _Fp, class _Alloc> @@ -1050,18 +1058,22 @@ public: // deleted overloads close possible hole in the type system template<class _R2, class... _ArgTypes2> bool operator==(const function<_R2(_ArgTypes2...)>&) const = delete; +#if _LIBCPP_STD_VER <= 17 template<class _R2, class... _ArgTypes2> bool operator!=(const function<_R2(_ArgTypes2...)>&) const = delete; +#endif public: // function invocation: - _Rp operator()(_ArgTypes...) const; + _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes...) const; -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI // function target access: - const std::type_info& target_type() const _NOEXCEPT; - template <typename _Tp> _Tp* target() _NOEXCEPT; - template <typename _Tp> const _Tp* target() const _NOEXCEPT; -#endif // _LIBCPP_NO_RTTI + _LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT; + template <typename _Tp> + _LIBCPP_HIDE_FROM_ABI _Tp* target() _NOEXCEPT; + template <typename _Tp> + _LIBCPP_HIDE_FROM_ABI const _Tp* target() const _NOEXCEPT; +#endif // _LIBCPP_HAS_NO_RTTI }; #if _LIBCPP_STD_VER >= 17 @@ -1156,7 +1168,7 @@ function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const return __f_(_VSTD::forward<_ArgTypes>(__arg)...); } -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template<class _Rp, class ..._ArgTypes> const std::type_info& @@ -1181,13 +1193,15 @@ function<_Rp(_ArgTypes...)>::target() const _NOEXCEPT return __f_.template target<_Tp>(); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template <class _Rp, class... _ArgTypes> inline _LIBCPP_INLINE_VISIBILITY bool operator==(const function<_Rp(_ArgTypes...)>& __f, nullptr_t) _NOEXCEPT {return !__f;} +#if _LIBCPP_STD_VER <= 17 + template <class _Rp, class... _ArgTypes> inline _LIBCPP_INLINE_VISIBILITY bool @@ -1203,6 +1217,8 @@ inline _LIBCPP_INLINE_VISIBILITY bool operator!=(nullptr_t, const function<_Rp(_ArgTypes...)>& __f) _NOEXCEPT {return (bool)__f;} +#endif // _LIBCPP_STD_VER <= 17 + template <class _Rp, class... _ArgTypes> inline _LIBCPP_INLINE_VISIBILITY void diff --git a/libcxx/include/__functional/hash.h b/libcxx/include/__functional/hash.h index dfd8ea2553dc..fa09748b145d 100644 --- a/libcxx/include/__functional/hash.h +++ b/libcxx/include/__functional/hash.h @@ -13,7 +13,7 @@ #include <__functional/invoke.h> #include <__functional/unary_function.h> #include <__fwd/hash.h> -#include <__tuple_dir/sfinae_helpers.h> +#include <__tuple/sfinae_helpers.h> #include <__type_traits/is_copy_constructible.h> #include <__type_traits/is_default_constructible.h> #include <__type_traits/is_enum.h> @@ -35,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Size> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI _Size __loadword(const void* __p) { @@ -53,73 +53,113 @@ struct __murmur2_or_cityhash; template <class _Size> struct __murmur2_or_cityhash<_Size, 32> { - inline _Size operator()(const void* __key, _Size __len) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + _Size operator()(const void* __key, _Size __len) const { + // murmur2 + const _Size __m = 0x5bd1e995; + const _Size __r = 24; + _Size __h = __len; + const unsigned char* __data = static_cast<const unsigned char*>(__key); + for (; __len >= 4; __data += 4, __len -= 4) + { + _Size __k = std::__loadword<_Size>(__data); + __k *= __m; + __k ^= __k >> __r; + __k *= __m; + __h *= __m; + __h ^= __k; + } + switch (__len) + { + case 3: + __h ^= static_cast<_Size>(__data[2] << 16); + _LIBCPP_FALLTHROUGH(); + case 2: + __h ^= static_cast<_Size>(__data[1] << 8); + _LIBCPP_FALLTHROUGH(); + case 1: + __h ^= __data[0]; + __h *= __m; + } + __h ^= __h >> 13; + __h *= __m; + __h ^= __h >> 15; + return __h; + } }; -// murmur2 template <class _Size> -_Size -__murmur2_or_cityhash<_Size, 32>::operator()(const void* __key, _Size __len) +struct __murmur2_or_cityhash<_Size, 64> { - const _Size __m = 0x5bd1e995; - const _Size __r = 24; - _Size __h = __len; - const unsigned char* __data = static_cast<const unsigned char*>(__key); - for (; __len >= 4; __data += 4, __len -= 4) - { - _Size __k = std::__loadword<_Size>(__data); - __k *= __m; - __k ^= __k >> __r; - __k *= __m; - __h *= __m; - __h ^= __k; - } - switch (__len) - { - case 3: - __h ^= static_cast<_Size>(__data[2] << 16); - _LIBCPP_FALLTHROUGH(); - case 2: - __h ^= static_cast<_Size>(__data[1] << 8); - _LIBCPP_FALLTHROUGH(); - case 1: - __h ^= __data[0]; - __h *= __m; + // cityhash64 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + _Size operator()(const void* __key, _Size __len) const { + const char* __s = static_cast<const char*>(__key); + if (__len <= 32) { + if (__len <= 16) { + return __hash_len_0_to_16(__s, __len); + } else { + return __hash_len_17_to_32(__s, __len); + } + } else if (__len <= 64) { + return __hash_len_33_to_64(__s, __len); } - __h ^= __h >> 13; - __h *= __m; - __h ^= __h >> 15; - return __h; -} -template <class _Size> -struct __murmur2_or_cityhash<_Size, 64> -{ - inline _Size operator()(const void* __key, _Size __len) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK; + // For strings over 64 bytes we hash the end first, and then as we + // loop we keep 56 bytes of state: v, w, x, y, and z. + _Size __x = std::__loadword<_Size>(__s + __len - 40); + _Size __y = std::__loadword<_Size>(__s + __len - 16) + + std::__loadword<_Size>(__s + __len - 56); + _Size __z = __hash_len_16(std::__loadword<_Size>(__s + __len - 48) + __len, + std::__loadword<_Size>(__s + __len - 24)); + pair<_Size, _Size> __v = __weak_hash_len_32_with_seeds(__s + __len - 64, __len, __z); + pair<_Size, _Size> __w = __weak_hash_len_32_with_seeds(__s + __len - 32, __y + __k1, __x); + __x = __x * __k1 + std::__loadword<_Size>(__s); + + // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. + __len = (__len - 1) & ~static_cast<_Size>(63); + do { + __x = __rotate(__x + __y + __v.first + std::__loadword<_Size>(__s + 8), 37) * __k1; + __y = __rotate(__y + __v.second + std::__loadword<_Size>(__s + 48), 42) * __k1; + __x ^= __w.second; + __y += __v.first + std::__loadword<_Size>(__s + 40); + __z = __rotate(__z + __w.first, 33) * __k1; + __v = __weak_hash_len_32_with_seeds(__s, __v.second * __k1, __x + __w.first); + __w = __weak_hash_len_32_with_seeds(__s + 32, __z + __w.second, + __y + std::__loadword<_Size>(__s + 16)); + _VSTD::swap(__z, __x); + __s += 64; + __len -= 64; + } while (__len != 0); + return __hash_len_16( + __hash_len_16(__v.first, __w.first) + __shift_mix(__y) * __k1 + __z, + __hash_len_16(__v.second, __w.second) + __x); + } - private: - // Some primes between 2^63 and 2^64. - static const _Size __k0 = 0xc3a5c85c97cb3127ULL; - static const _Size __k1 = 0xb492b66fbe98f273ULL; - static const _Size __k2 = 0x9ae16a3b2f90404fULL; - static const _Size __k3 = 0xc949d7c7509e6557ULL; + private: + // Some primes between 2^63 and 2^64. + static const _Size __k0 = 0xc3a5c85c97cb3127ULL; + static const _Size __k1 = 0xb492b66fbe98f273ULL; + static const _Size __k2 = 0x9ae16a3b2f90404fULL; + static const _Size __k3 = 0xc949d7c7509e6557ULL; + _LIBCPP_HIDE_FROM_ABI static _Size __rotate(_Size __val, int __shift) { return __shift == 0 ? __val : ((__val >> __shift) | (__val << (64 - __shift))); } + _LIBCPP_HIDE_FROM_ABI static _Size __rotate_by_at_least_1(_Size __val, int __shift) { return (__val >> __shift) | (__val << (64 - __shift)); } + _LIBCPP_HIDE_FROM_ABI static _Size __shift_mix(_Size __val) { return __val ^ (__val >> 47); } - static _Size __hash_len_16(_Size __u, _Size __v) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK - { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + static _Size __hash_len_16(_Size __u, _Size __v) { const _Size __mul = 0x9ddfea08eb382d69ULL; _Size __a = (__u ^ __v) * __mul; __a ^= (__a >> 47); @@ -129,9 +169,8 @@ struct __murmur2_or_cityhash<_Size, 64> return __b; } - static _Size __hash_len_0_to_16(const char* __s, _Size __len) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK - { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + static _Size __hash_len_0_to_16(const char* __s, _Size __len) { if (__len > 8) { const _Size __a = std::__loadword<_Size>(__s); const _Size __b = std::__loadword<_Size>(__s + __len - 8); @@ -140,7 +179,11 @@ struct __murmur2_or_cityhash<_Size, 64> if (__len >= 4) { const uint32_t __a = std::__loadword<uint32_t>(__s); const uint32_t __b = std::__loadword<uint32_t>(__s + __len - 4); +#ifdef _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION return __hash_len_16(__len + (static_cast<_Size>(__a) << 3), __b); +#else + return __hash_len_16(__len + (__a << 3), __b); +#endif } if (__len > 0) { const unsigned char __a = static_cast<unsigned char>(__s[0]); @@ -154,9 +197,8 @@ struct __murmur2_or_cityhash<_Size, 64> return __k2; } - static _Size __hash_len_17_to_32(const char *__s, _Size __len) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK - { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + static _Size __hash_len_17_to_32(const char *__s, _Size __len) { const _Size __a = std::__loadword<_Size>(__s) * __k1; const _Size __b = std::__loadword<_Size>(__s + 8); const _Size __c = std::__loadword<_Size>(__s + __len - 8) * __k2; @@ -167,9 +209,9 @@ struct __murmur2_or_cityhash<_Size, 64> // Return a 16-byte hash for 48 bytes. Quick and dirty. // Callers do best to use "random-looking" values for a and b. + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK static pair<_Size, _Size> __weak_hash_len_32_with_seeds( _Size __w, _Size __x, _Size __y, _Size __z, _Size __a, _Size __b) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { __a += __w; __b = __rotate(__b + __a + __z, 21); @@ -181,9 +223,9 @@ struct __murmur2_or_cityhash<_Size, 64> } // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK static pair<_Size, _Size> __weak_hash_len_32_with_seeds( const char* __s, _Size __a, _Size __b) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { return __weak_hash_len_32_with_seeds(std::__loadword<_Size>(__s), std::__loadword<_Size>(__s + 8), @@ -194,9 +236,8 @@ struct __murmur2_or_cityhash<_Size, 64> } // Return an 8-byte hash for 33 to 64 bytes. - static _Size __hash_len_33_to_64(const char *__s, size_t __len) - _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK - { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK + static _Size __hash_len_33_to_64(const char *__s, size_t __len) { _Size __z = std::__loadword<_Size>(__s + 24); _Size __a = std::__loadword<_Size>(__s) + (__len + std::__loadword<_Size>(__s + __len - 16)) * __k0; @@ -221,53 +262,6 @@ struct __murmur2_or_cityhash<_Size, 64> } }; -// cityhash64 -template <class _Size> -_Size -__murmur2_or_cityhash<_Size, 64>::operator()(const void* __key, _Size __len) -{ - const char* __s = static_cast<const char*>(__key); - if (__len <= 32) { - if (__len <= 16) { - return __hash_len_0_to_16(__s, __len); - } else { - return __hash_len_17_to_32(__s, __len); - } - } else if (__len <= 64) { - return __hash_len_33_to_64(__s, __len); - } - - // For strings over 64 bytes we hash the end first, and then as we - // loop we keep 56 bytes of state: v, w, x, y, and z. - _Size __x = std::__loadword<_Size>(__s + __len - 40); - _Size __y = std::__loadword<_Size>(__s + __len - 16) + - std::__loadword<_Size>(__s + __len - 56); - _Size __z = __hash_len_16(std::__loadword<_Size>(__s + __len - 48) + __len, - std::__loadword<_Size>(__s + __len - 24)); - pair<_Size, _Size> __v = __weak_hash_len_32_with_seeds(__s + __len - 64, __len, __z); - pair<_Size, _Size> __w = __weak_hash_len_32_with_seeds(__s + __len - 32, __y + __k1, __x); - __x = __x * __k1 + std::__loadword<_Size>(__s); - - // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. - __len = (__len - 1) & ~static_cast<_Size>(63); - do { - __x = __rotate(__x + __y + __v.first + std::__loadword<_Size>(__s + 8), 37) * __k1; - __y = __rotate(__y + __v.second + std::__loadword<_Size>(__s + 48), 42) * __k1; - __x ^= __w.second; - __y += __v.first + std::__loadword<_Size>(__s + 40); - __z = __rotate(__z + __w.first, 33) * __k1; - __v = __weak_hash_len_32_with_seeds(__s, __v.second * __k1, __x + __w.first); - __w = __weak_hash_len_32_with_seeds(__s + 32, __z + __w.second, - __y + std::__loadword<_Size>(__s + 16)); - _VSTD::swap(__z, __x); - __s += 64; - __len -= 64; - } while (__len != 0); - return __hash_len_16( - __hash_len_16(__v.first, __w.first) + __shift_mix(__y) * __k1 + __z, - __hash_len_16(__v.second, __w.second) + __x); -} - template <class _Tp, size_t = sizeof(_Tp) / sizeof(size_t)> struct __scalar_hash; @@ -275,7 +269,7 @@ template <class _Tp> struct __scalar_hash<_Tp, 0> : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { union @@ -293,7 +287,7 @@ template <class _Tp> struct __scalar_hash<_Tp, 1> : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { union @@ -310,7 +304,7 @@ template <class _Tp> struct __scalar_hash<_Tp, 2> : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { union @@ -331,7 +325,7 @@ template <class _Tp> struct __scalar_hash<_Tp, 3> : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { union @@ -353,7 +347,7 @@ template <class _Tp> struct __scalar_hash<_Tp, 4> : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { union @@ -377,7 +371,7 @@ struct _PairT { size_t second; }; -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_HIDE_FROM_ABI inline size_t __hash_combine(size_t __lhs, size_t __rhs) _NOEXCEPT { typedef __scalar_hash<_PairT> _HashT; const _PairT __p = {__lhs, __rhs}; @@ -388,7 +382,7 @@ template<class _Tp> struct _LIBCPP_TEMPLATE_VIS hash<_Tp*> : public __unary_function<_Tp*, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp* __v) const _NOEXCEPT { union @@ -405,7 +399,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<bool> : public __unary_function<bool, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(bool __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -413,7 +407,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<char> : public __unary_function<char, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(char __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -421,7 +415,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<signed char> : public __unary_function<signed char, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(signed char __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -429,7 +423,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<unsigned char> : public __unary_function<unsigned char, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned char __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -438,7 +432,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<char8_t> : public __unary_function<char8_t, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(char8_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; #endif // !_LIBCPP_HAS_NO_CHAR8_T @@ -447,7 +441,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<char16_t> : public __unary_function<char16_t, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(char16_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -455,7 +449,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<char32_t> : public __unary_function<char32_t, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(char32_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -464,7 +458,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<wchar_t> : public __unary_function<wchar_t, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(wchar_t __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -473,7 +467,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<short> : public __unary_function<short, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(short __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -481,7 +475,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<unsigned short> : public __unary_function<unsigned short, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned short __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -489,7 +483,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<int> : public __unary_function<int, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(int __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -497,7 +491,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<unsigned int> : public __unary_function<unsigned int, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned int __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -505,7 +499,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<long> : public __unary_function<long, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(long __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -513,7 +507,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<unsigned long> : public __unary_function<unsigned long, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(unsigned long __v) const _NOEXCEPT {return static_cast<size_t>(__v);} }; @@ -549,7 +543,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<float> : public __scalar_hash<float> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(float __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash @@ -563,7 +557,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<double> : public __scalar_hash<double> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(double __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash @@ -577,7 +571,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS hash<long double> : public __scalar_hash<long double> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(long double __v) const _NOEXCEPT { // -0.0 and 0.0 should return same hash @@ -627,7 +621,7 @@ template <class _Tp, bool = is_enum<_Tp>::value> struct _LIBCPP_TEMPLATE_VIS __enum_hash : public __unary_function<_Tp, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(_Tp __v) const _NOEXCEPT { typedef typename underlying_type<_Tp>::type type; @@ -646,13 +640,13 @@ struct _LIBCPP_TEMPLATE_VIS hash : public __enum_hash<_Tp> { }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <> struct _LIBCPP_TEMPLATE_VIS hash<nullptr_t> : public __unary_function<nullptr_t, size_t> { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI size_t operator()(nullptr_t) const _NOEXCEPT { return 662607004ull; } @@ -673,7 +667,7 @@ using __has_enabled_hash _LIBCPP_NODEBUG = integral_constant<bool, is_default_constructible<_Hash>::value >; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Type, class> using __enable_hash_helper_imp _LIBCPP_NODEBUG = _Type; diff --git a/libcxx/include/__functional/identity.h b/libcxx/include/__functional/identity.h index 2fe3acca0899..5dffedf677f9 100644 --- a/libcxx/include/__functional/identity.h +++ b/libcxx/include/__functional/identity.h @@ -11,6 +11,7 @@ #define _LIBCPP___FUNCTIONAL_IDENTITY_H #include <__config> +#include <__type_traits/integral_constant.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -19,27 +20,37 @@ _LIBCPP_BEGIN_NAMESPACE_STD +template <class _Tp> +struct __is_identity : false_type {}; + struct __identity { template <class _Tp> - _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR _Tp&& operator()(_Tp&& __t) const _NOEXCEPT { + _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp&& operator()(_Tp&& __t) const _NOEXCEPT { return std::forward<_Tp>(__t); } using is_transparent = void; }; -#if _LIBCPP_STD_VER > 17 +template <> +struct __is_identity<__identity> : true_type {}; + +#if _LIBCPP_STD_VER >= 20 struct identity { template<class _Tp> - _LIBCPP_NODISCARD_EXT constexpr _Tp&& operator()(_Tp&& __t) const noexcept + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator()(_Tp&& __t) const noexcept { return _VSTD::forward<_Tp>(__t); } using is_transparent = void; }; -#endif // _LIBCPP_STD_VER > 17 + +template <> +struct __is_identity<identity> : true_type {}; + +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/invoke.h b/libcxx/include/__functional/invoke.h index 48e6eac3ce98..a7dd311074d8 100644 --- a/libcxx/include/__functional/invoke.h +++ b/libcxx/include/__functional/invoke.h @@ -11,525 +11,16 @@ #define _LIBCPP___FUNCTIONAL_INVOKE_H #include <__config> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/apply_cv.h> -#include <__type_traits/conditional.h> -#include <__type_traits/decay.h> -#include <__type_traits/enable_if.h> -#include <__type_traits/integral_constant.h> -#include <__type_traits/is_base_of.h> -#include <__type_traits/is_core_convertible.h> -#include <__type_traits/is_member_function_pointer.h> -#include <__type_traits/is_member_object_pointer.h> -#include <__type_traits/is_reference_wrapper.h> -#include <__type_traits/is_same.h> -#include <__type_traits/is_void.h> -#include <__type_traits/nat.h> -#include <__type_traits/remove_cv.h> -#include <__utility/declval.h> +#include <__type_traits/invoke.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -// TODO: Disentangle the type traits and std::invoke properly - _LIBCPP_BEGIN_NAMESPACE_STD -struct __any -{ - __any(...); -}; - -template <class _MP, bool _IsMemberFunctionPtr, bool _IsMemberObjectPtr> -struct __member_pointer_traits_imp -{ -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...), true, false> -{ - typedef _Class _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...), true, false> -{ - typedef _Class _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const, true, false> -{ - typedef _Class const _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const, true, false> -{ - typedef _Class const _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile, true, false> -{ - typedef _Class volatile _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile, true, false> -{ - typedef _Class volatile _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile, true, false> -{ - typedef _Class const volatile _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile, true, false> -{ - typedef _Class const volatile _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) &, true, false> -{ - typedef _Class& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) &, true, false> -{ - typedef _Class& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&, true, false> -{ - typedef _Class const& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&, true, false> -{ - typedef _Class const& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&, true, false> -{ - typedef _Class volatile& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&, true, false> -{ - typedef _Class volatile& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&, true, false> -{ - typedef _Class const volatile& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&, true, false> -{ - typedef _Class const volatile& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) &&, true, false> -{ - typedef _Class&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) &&, true, false> -{ - typedef _Class&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&&, true, false> -{ - typedef _Class const&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&&, true, false> -{ - typedef _Class const&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&&, true, false> -{ - typedef _Class volatile&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&&, true, false> -{ - typedef _Class volatile&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&&, true, false> -{ - typedef _Class const volatile&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param...); -}; - -template <class _Rp, class _Class, class ..._Param> -struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&&, true, false> -{ - typedef _Class const volatile&& _ClassType; - typedef _Rp _ReturnType; - typedef _Rp (_FnType) (_Param..., ...); -}; - -template <class _Rp, class _Class> -struct __member_pointer_traits_imp<_Rp _Class::*, false, true> -{ - typedef _Class _ClassType; - typedef _Rp _ReturnType; -}; - -template <class _MP> -struct __member_pointer_traits - : public __member_pointer_traits_imp<__remove_cv_t<_MP>, - is_member_function_pointer<_MP>::value, - is_member_object_pointer<_MP>::value> -{ -// typedef ... _ClassType; -// typedef ... _ReturnType; -// typedef ... _FnType; -}; - -template <class _DecayedFp> -struct __member_pointer_class_type {}; - -template <class _Ret, class _ClassType> -struct __member_pointer_class_type<_Ret _ClassType::*> { - typedef _ClassType type; -}; - -template <class _Fp, class _A0, - class _DecayFp = typename decay<_Fp>::type, - class _DecayA0 = typename decay<_A0>::type, - class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> -using __enable_if_bullet1 = typename enable_if - < - is_member_function_pointer<_DecayFp>::value - && is_base_of<_ClassT, _DecayA0>::value - >::type; - -template <class _Fp, class _A0, - class _DecayFp = typename decay<_Fp>::type, - class _DecayA0 = typename decay<_A0>::type> -using __enable_if_bullet2 = typename enable_if - < - is_member_function_pointer<_DecayFp>::value - && __is_reference_wrapper<_DecayA0>::value - >::type; - -template <class _Fp, class _A0, - class _DecayFp = typename decay<_Fp>::type, - class _DecayA0 = typename decay<_A0>::type, - class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> -using __enable_if_bullet3 = typename enable_if - < - is_member_function_pointer<_DecayFp>::value - && !is_base_of<_ClassT, _DecayA0>::value - && !__is_reference_wrapper<_DecayA0>::value - >::type; - -template <class _Fp, class _A0, - class _DecayFp = typename decay<_Fp>::type, - class _DecayA0 = typename decay<_A0>::type, - class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> -using __enable_if_bullet4 = typename enable_if - < - is_member_object_pointer<_DecayFp>::value - && is_base_of<_ClassT, _DecayA0>::value - >::type; - -template <class _Fp, class _A0, - class _DecayFp = typename decay<_Fp>::type, - class _DecayA0 = typename decay<_A0>::type> -using __enable_if_bullet5 = typename enable_if - < - is_member_object_pointer<_DecayFp>::value - && __is_reference_wrapper<_DecayA0>::value - >::type; - -template <class _Fp, class _A0, - class _DecayFp = typename decay<_Fp>::type, - class _DecayA0 = typename decay<_A0>::type, - class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> -using __enable_if_bullet6 = typename enable_if - < - is_member_object_pointer<_DecayFp>::value - && !is_base_of<_ClassT, _DecayA0>::value - && !__is_reference_wrapper<_DecayA0>::value - >::type; - -// __invoke forward declarations - -// fall back - none of the bullets - -template <class ..._Args> -__nat __invoke(__any, _Args&& ...__args); - -// bullets 1, 2 and 3 - -template <class _Fp, class _A0, class ..._Args, - class = __enable_if_bullet1<_Fp, _A0> > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype((std::declval<_A0>().*std::declval<_Fp>())(std::declval<_Args>()...)) -__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) - _NOEXCEPT_(noexcept((static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...))) - { return (static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...); } - -template <class _Fp, class _A0, class ..._Args, - class = __enable_if_bullet2<_Fp, _A0> > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype((std::declval<_A0>().get().*std::declval<_Fp>())(std::declval<_Args>()...)) -__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) - _NOEXCEPT_(noexcept((__a0.get().*__f)(static_cast<_Args&&>(__args)...))) - { return (__a0.get().*__f)(static_cast<_Args&&>(__args)...); } - -template <class _Fp, class _A0, class ..._Args, - class = __enable_if_bullet3<_Fp, _A0> > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype(((*std::declval<_A0>()).*std::declval<_Fp>())(std::declval<_Args>()...)) -__invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) - _NOEXCEPT_(noexcept(((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...))) - { return ((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...); } - -// bullets 4, 5 and 6 - -template <class _Fp, class _A0, - class = __enable_if_bullet4<_Fp, _A0> > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype(std::declval<_A0>().*std::declval<_Fp>()) -__invoke(_Fp&& __f, _A0&& __a0) - _NOEXCEPT_(noexcept(static_cast<_A0&&>(__a0).*__f)) - { return static_cast<_A0&&>(__a0).*__f; } - -template <class _Fp, class _A0, - class = __enable_if_bullet5<_Fp, _A0> > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype(std::declval<_A0>().get().*std::declval<_Fp>()) -__invoke(_Fp&& __f, _A0&& __a0) - _NOEXCEPT_(noexcept(__a0.get().*__f)) - { return __a0.get().*__f; } - -template <class _Fp, class _A0, - class = __enable_if_bullet6<_Fp, _A0> > -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype((*std::declval<_A0>()).*std::declval<_Fp>()) -__invoke(_Fp&& __f, _A0&& __a0) - _NOEXCEPT_(noexcept((*static_cast<_A0&&>(__a0)).*__f)) - { return (*static_cast<_A0&&>(__a0)).*__f; } - -// bullet 7 - -template <class _Fp, class ..._Args> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR decltype(std::declval<_Fp>()(std::declval<_Args>()...)) -__invoke(_Fp&& __f, _Args&& ...__args) - _NOEXCEPT_(noexcept(static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...))) - { return static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...); } - -// __invokable -template <class _Ret, class _Fp, class ..._Args> -struct __invokable_r -{ - template <class _XFp, class ..._XArgs> - static decltype(std::__invoke(std::declval<_XFp>(), std::declval<_XArgs>()...)) __try_call(int); - template <class _XFp, class ..._XArgs> - static __nat __try_call(...); - - // FIXME: Check that _Ret, _Fp, and _Args... are all complete types, cv void, - // or incomplete array types as required by the standard. - using _Result = decltype(__try_call<_Fp, _Args...>(0)); - - using type = __conditional_t< - _IsNotSame<_Result, __nat>::value, - __conditional_t<is_void<_Ret>::value, true_type, __is_core_convertible<_Result, _Ret> >, - false_type>; - static const bool value = type::value; -}; -template <class _Fp, class ..._Args> -using __invokable = __invokable_r<void, _Fp, _Args...>; - -template <bool _IsInvokable, bool _IsCVVoid, class _Ret, class _Fp, class ..._Args> -struct __nothrow_invokable_r_imp { - static const bool value = false; -}; - -template <class _Ret, class _Fp, class ..._Args> -struct __nothrow_invokable_r_imp<true, false, _Ret, _Fp, _Args...> -{ - typedef __nothrow_invokable_r_imp _ThisT; - - template <class _Tp> - static void __test_noexcept(_Tp) _NOEXCEPT; - -#ifdef _LIBCPP_CXX03_LANG - static const bool value = false; -#else - static const bool value = noexcept(_ThisT::__test_noexcept<_Ret>( - _VSTD::__invoke(std::declval<_Fp>(), std::declval<_Args>()...))); -#endif -}; - -template <class _Ret, class _Fp, class ..._Args> -struct __nothrow_invokable_r_imp<true, true, _Ret, _Fp, _Args...> -{ -#ifdef _LIBCPP_CXX03_LANG - static const bool value = false; -#else - static const bool value = noexcept( - _VSTD::__invoke(std::declval<_Fp>(), std::declval<_Args>()...)); -#endif -}; - -template <class _Ret, class _Fp, class ..._Args> -using __nothrow_invokable_r = - __nothrow_invokable_r_imp< - __invokable_r<_Ret, _Fp, _Args...>::value, - is_void<_Ret>::value, - _Ret, _Fp, _Args... - >; - -template <class _Fp, class ..._Args> -using __nothrow_invokable = - __nothrow_invokable_r_imp< - __invokable<_Fp, _Args...>::value, - true, void, _Fp, _Args... - >; - -template <class _Fp, class ..._Args> -struct __invoke_of - : public enable_if< - __invokable<_Fp, _Args...>::value, - typename __invokable_r<void, _Fp, _Args...>::_Result> -{ -}; - -template <class _Ret, bool = is_void<_Ret>::value> -struct __invoke_void_return_wrapper -{ - template <class ..._Args> - static _Ret __call(_Args&&... __args) { - return std::__invoke(std::forward<_Args>(__args)...); - } -}; - -template <class _Ret> -struct __invoke_void_return_wrapper<_Ret, true> -{ - template <class ..._Args> - static void __call(_Args&&... __args) { - std::__invoke(std::forward<_Args>(__args)...); - } -}; - -#if _LIBCPP_STD_VER > 14 - -// is_invocable - -template <class _Fn, class ..._Args> -struct _LIBCPP_TEMPLATE_VIS is_invocable - : integral_constant<bool, __invokable<_Fn, _Args...>::value> {}; - -template <class _Ret, class _Fn, class ..._Args> -struct _LIBCPP_TEMPLATE_VIS is_invocable_r - : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {}; - -template <class _Fn, class ..._Args> -inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; - -template <class _Ret, class _Fn, class ..._Args> -inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value; - -// is_nothrow_invocable - -template <class _Fn, class ..._Args> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable - : integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value> {}; - -template <class _Ret, class _Fn, class ..._Args> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r - : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {}; - -template <class _Fn, class ..._Args> -inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value; - -template <class _Ret, class _Fn, class ..._Args> -inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; - -template <class _Fn, class... _Args> -struct _LIBCPP_TEMPLATE_VIS invoke_result - : __invoke_of<_Fn, _Args...> -{ -}; - -template <class _Fn, class... _Args> -using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; +#if _LIBCPP_STD_VER >= 17 template <class _Fn, class ..._Args> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 invoke_result_t<_Fn, _Args...> @@ -539,7 +30,26 @@ invoke(_Fn&& __f, _Args&&... __args) return _VSTD::__invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 + +#if _LIBCPP_STD_VER >= 23 +template <class _Result, class _Fn, class... _Args> + requires is_invocable_r_v<_Result, _Fn, _Args...> +_LIBCPP_HIDE_FROM_ABI constexpr _Result +invoke_r(_Fn&& __f, _Args&&... __args) noexcept(is_nothrow_invocable_r_v<_Result, _Fn, _Args...>) { + if constexpr (is_void_v<_Result>) { + static_cast<void>(std::invoke(std::forward<_Fn>(__f), std::forward<_Args>(__args)...)); + } else { + // TODO: Use reference_converts_from_temporary_v once implemented + // using _ImplicitInvokeResult = invoke_result_t<_Fn, _Args...>; + // static_assert(!reference_converts_from_temporary_v<_Result, _ImplicitInvokeResult>, + static_assert(true, + "Returning from invoke_r would bind a temporary object to the reference return type, " + "which would result in a dangling reference."); + return std::invoke(std::forward<_Fn>(__f), std::forward<_Args>(__args)...); + } +} +#endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/is_transparent.h b/libcxx/include/__functional/is_transparent.h index c7a0ee9ee7b8..c539a07d696d 100644 --- a/libcxx/include/__functional/is_transparent.h +++ b/libcxx/include/__functional/is_transparent.h @@ -11,7 +11,8 @@ #define _LIBCPP___FUNCTIONAL_IS_TRANSPARENT #include <__config> -#include <type_traits> +#include <__type_traits/integral_constant.h> +#include <__type_traits/void_t.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp, class, class = void> struct __is_transparent : false_type {}; diff --git a/libcxx/include/__functional/mem_fn.h b/libcxx/include/__functional/mem_fn.h index 8b51627079cf..fe221dd128f4 100644 --- a/libcxx/include/__functional/mem_fn.h +++ b/libcxx/include/__functional/mem_fn.h @@ -15,7 +15,6 @@ #include <__functional/invoke.h> #include <__functional/weak_result_type.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__functional/not_fn.h b/libcxx/include/__functional/not_fn.h index 79d9a8710bd0..0cdb1b7e238b 100644 --- a/libcxx/include/__functional/not_fn.h +++ b/libcxx/include/__functional/not_fn.h @@ -13,8 +13,11 @@ #include <__config> #include <__functional/invoke.h> #include <__functional/perfect_forward.h> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_move_constructible.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 struct __not_fn_op { template <class... _Args> @@ -47,7 +50,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 auto not_fn(_Fn&& __f) { return __not_fn_t<decay_t<_Fn>>(_VSTD::forward<_Fn>(__f)); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/operations.h b/libcxx/include/__functional/operations.h index 8a781efbdbbb..6cdb89d6b449 100644 --- a/libcxx/include/__functional/operations.h +++ b/libcxx/include/__functional/operations.h @@ -13,6 +13,9 @@ #include <__config> #include <__functional/binary_function.h> #include <__functional/unary_function.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/operation_traits.h> +#include <__type_traits/predicate_traits.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -23,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Arithmetic operations -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -38,7 +41,15 @@ struct _LIBCPP_TEMPLATE_VIS plus }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(plus); -#if _LIBCPP_STD_VER > 11 +template <class _Tp> +struct __is_trivial_plus_operation<plus<_Tp>, _Tp, _Tp> : true_type {}; + +#if _LIBCPP_STD_VER >= 14 +template <class _Tp, class _Up> +struct __is_trivial_plus_operation<plus<>, _Tp, _Up> : true_type {}; +#endif + +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS plus<void> { @@ -52,7 +63,7 @@ struct _LIBCPP_TEMPLATE_VIS plus<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -67,7 +78,7 @@ struct _LIBCPP_TEMPLATE_VIS minus }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(minus); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS minus<void> { @@ -81,7 +92,7 @@ struct _LIBCPP_TEMPLATE_VIS minus<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -96,7 +107,7 @@ struct _LIBCPP_TEMPLATE_VIS multiplies }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(multiplies); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS multiplies<void> { @@ -110,7 +121,7 @@ struct _LIBCPP_TEMPLATE_VIS multiplies<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -125,7 +136,7 @@ struct _LIBCPP_TEMPLATE_VIS divides }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(divides); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS divides<void> { @@ -139,7 +150,7 @@ struct _LIBCPP_TEMPLATE_VIS divides<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -154,7 +165,7 @@ struct _LIBCPP_TEMPLATE_VIS modulus }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(modulus); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS modulus<void> { @@ -168,7 +179,7 @@ struct _LIBCPP_TEMPLATE_VIS modulus<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -183,7 +194,7 @@ struct _LIBCPP_TEMPLATE_VIS negate }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(negate); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS negate<void> { @@ -199,7 +210,7 @@ struct _LIBCPP_TEMPLATE_VIS negate<void> // Bitwise operations -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -214,7 +225,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_and }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_and); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS bit_and<void> { @@ -228,7 +239,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_and<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> struct _LIBCPP_TEMPLATE_VIS bit_not : __unary_function<_Tp, _Tp> @@ -252,7 +263,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_not<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -267,7 +278,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_or }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_or); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS bit_or<void> { @@ -281,7 +292,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_or<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -296,7 +307,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_xor }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_xor); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS bit_xor<void> { @@ -312,7 +323,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_xor<void> // Comparison operations -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -327,7 +338,7 @@ struct _LIBCPP_TEMPLATE_VIS equal_to }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(equal_to); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS equal_to<void> { @@ -341,7 +352,15 @@ struct _LIBCPP_TEMPLATE_VIS equal_to<void> }; #endif -#if _LIBCPP_STD_VER > 11 +template <class _Tp> +struct __is_trivial_equality_predicate<equal_to<_Tp>, _Tp, _Tp> : true_type {}; + +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +struct __is_trivial_equality_predicate<equal_to<>, _Tp, _Tp> : true_type {}; +#endif + +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -356,7 +375,7 @@ struct _LIBCPP_TEMPLATE_VIS not_equal_to }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(not_equal_to); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS not_equal_to<void> { @@ -370,7 +389,7 @@ struct _LIBCPP_TEMPLATE_VIS not_equal_to<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -385,7 +404,7 @@ struct _LIBCPP_TEMPLATE_VIS less }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(less); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS less<void> { @@ -399,7 +418,7 @@ struct _LIBCPP_TEMPLATE_VIS less<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -414,7 +433,7 @@ struct _LIBCPP_TEMPLATE_VIS less_equal }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(less_equal); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS less_equal<void> { @@ -428,7 +447,7 @@ struct _LIBCPP_TEMPLATE_VIS less_equal<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -443,7 +462,7 @@ struct _LIBCPP_TEMPLATE_VIS greater_equal }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(greater_equal); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS greater_equal<void> { @@ -457,7 +476,7 @@ struct _LIBCPP_TEMPLATE_VIS greater_equal<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -472,7 +491,7 @@ struct _LIBCPP_TEMPLATE_VIS greater }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(greater); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS greater<void> { @@ -488,7 +507,7 @@ struct _LIBCPP_TEMPLATE_VIS greater<void> // Logical operations -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -503,7 +522,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_and }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_and); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS logical_and<void> { @@ -517,7 +536,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_and<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -532,7 +551,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_not }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_not); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS logical_not<void> { @@ -546,7 +565,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_not<void> }; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp = void> #else template <class _Tp> @@ -561,7 +580,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_or }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_or); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <> struct _LIBCPP_TEMPLATE_VIS logical_or<void> { diff --git a/libcxx/include/__functional/perfect_forward.h b/libcxx/include/__functional/perfect_forward.h index 9ffea1a8c75d..b848fbf69631 100644 --- a/libcxx/include/__functional/perfect_forward.h +++ b/libcxx/include/__functional/perfect_forward.h @@ -11,19 +11,25 @@ #define _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H #include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/invoke.h> +#include <__type_traits/is_constructible.h> #include <__utility/declval.h> #include <__utility/forward.h> +#include <__utility/integer_sequence.h> #include <__utility/move.h> #include <tuple> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Op, class _Indices, class... _BoundArgs> struct __perfect_forward_impl; @@ -37,14 +43,14 @@ public: template <class... _Args, class = enable_if_t< is_constructible_v<tuple<_BoundArgs...>, _Args&&...> >> - explicit constexpr __perfect_forward_impl(_Args&&... __bound_args) + _LIBCPP_HIDE_FROM_ABI explicit constexpr __perfect_forward_impl(_Args&&... __bound_args) : __bound_args_(_VSTD::forward<_Args>(__bound_args)...) {} - __perfect_forward_impl(__perfect_forward_impl const&) = default; - __perfect_forward_impl(__perfect_forward_impl&&) = default; + _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl(__perfect_forward_impl const&) = default; + _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl(__perfect_forward_impl&&) = default; - __perfect_forward_impl& operator=(__perfect_forward_impl const&) = default; - __perfect_forward_impl& operator=(__perfect_forward_impl&&) = default; + _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl& operator=(__perfect_forward_impl const&) = default; + _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl& operator=(__perfect_forward_impl&&) = default; template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs&..., _Args...>>> _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) & @@ -87,8 +93,10 @@ public: template <class _Op, class ..._Args> using __perfect_forward = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H diff --git a/libcxx/include/__functional/ranges_operations.h b/libcxx/include/__functional/ranges_operations.h index 87081dd56a05..c344fc38f98d 100644 --- a/libcxx/include/__functional/ranges_operations.h +++ b/libcxx/include/__functional/ranges_operations.h @@ -13,6 +13,8 @@ #include <__concepts/equality_comparable.h> #include <__concepts/totally_ordered.h> #include <__config> +#include <__type_traits/integral_constant.h> +#include <__type_traits/predicate_traits.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -21,14 +23,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { struct equal_to { template <class _Tp, class _Up> requires equality_comparable_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u)))) { return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u); } @@ -39,7 +41,7 @@ struct equal_to { struct not_equal_to { template <class _Tp, class _Up> requires equality_comparable_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(!(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u))))) { return !(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u)); } @@ -50,7 +52,7 @@ struct not_equal_to { struct less { template <class _Tp, class _Up> requires totally_ordered_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u)))) { return _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u); } @@ -61,7 +63,7 @@ struct less { struct less_equal { template <class _Tp, class _Up> requires totally_ordered_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(!(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t))))) { return !(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t)); } @@ -72,7 +74,7 @@ struct less_equal { struct greater { template <class _Tp, class _Up> requires totally_ordered_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t)))) { return _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t); } @@ -83,7 +85,7 @@ struct greater { struct greater_equal { template <class _Tp, class _Up> requires totally_ordered_with<_Tp, _Up> - [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp &&__t, _Up &&__u) const noexcept(noexcept(bool(!(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u))))) { return !(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u)); } @@ -93,7 +95,10 @@ struct greater_equal { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +template <class _Lhs, class _Rhs> +struct __is_trivial_equality_predicate<ranges::equal_to, _Lhs, _Rhs> : true_type {}; + +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/reference_wrapper.h b/libcxx/include/__functional/reference_wrapper.h index c377b6437701..2d382a34f6a4 100644 --- a/libcxx/include/__functional/reference_wrapper.h +++ b/libcxx/include/__functional/reference_wrapper.h @@ -55,12 +55,18 @@ public: template <class... _ArgTypes> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<type&, _ArgTypes...>::type - operator() (_ArgTypes&&... __args) const { + operator() (_ArgTypes&&... __args) const +#if _LIBCPP_STD_VER >= 17 + // Since is_nothrow_invocable requires C++17 LWG3764 is not backported + // to earlier versions. + noexcept(is_nothrow_invocable_v<_Tp&, _ArgTypes...>) +#endif + { return std::__invoke(get(), std::forward<_ArgTypes>(__args)...); } }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; #endif diff --git a/libcxx/include/__fwd/fstream.h b/libcxx/include/__fwd/fstream.h new file mode 100644 index 000000000000..b4a112bfd4de --- /dev/null +++ b/libcxx/include/__fwd/fstream.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_FSTREAM_H +#define _LIBCPP___FWD_FSTREAM_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _CharT, class _Traits = char_traits<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_filebuf; +template <class _CharT, class _Traits = char_traits<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_ifstream; +template <class _CharT, class _Traits = char_traits<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_ofstream; +template <class _CharT, class _Traits = char_traits<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_fstream; + +using filebuf = basic_filebuf<char>; +using ifstream = basic_ifstream<char>; +using ofstream = basic_ofstream<char>; +using fstream = basic_fstream<char>; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wfilebuf = basic_filebuf<wchar_t>; +using wifstream = basic_ifstream<wchar_t>; +using wofstream = basic_ofstream<wchar_t>; +using wfstream = basic_fstream<wchar_t>; +#endif + +template <class _CharT, class _Traits> +class _LIBCPP_PREFERRED_NAME(filebuf) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wfilebuf)) basic_filebuf; +template <class _CharT, class _Traits> +class _LIBCPP_PREFERRED_NAME(ifstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wifstream)) basic_ifstream; +template <class _CharT, class _Traits> +class _LIBCPP_PREFERRED_NAME(ofstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wofstream)) basic_ofstream; +template <class _CharT, class _Traits> +class _LIBCPP_PREFERRED_NAME(fstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wfstream)) basic_fstream; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_FSTREAM_H diff --git a/libcxx/include/__fwd/get.h b/libcxx/include/__fwd/get.h index ec1fab4602d7..d04341496c60 100644 --- a/libcxx/include/__fwd/get.h +++ b/libcxx/include/__fwd/get.h @@ -15,7 +15,7 @@ #include <__fwd/pair.h> #include <__fwd/subrange.h> #include <__fwd/tuple.h> -#include <__tuple_dir/tuple_element.h> +#include <__tuple/tuple_element.h> #include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__fwd/ios.h b/libcxx/include/__fwd/ios.h new file mode 100644 index 000000000000..82c865d58cc7 --- /dev/null +++ b/libcxx/include/__fwd/ios.h @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_IOS_H +#define _LIBCPP___FWD_IOS_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _CharT, class _Traits = char_traits<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_ios; + +using ios = basic_ios<char>; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wios = basic_ios<wchar_t>; +#endif + +template <class _CharT, class _Traits> +class _LIBCPP_PREFERRED_NAME(ios) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wios)) basic_ios; + +#if defined(_NEWLIB_VERSION) +// On newlib, off_t is 'long int' +using streamoff = long int; // for char_traits in <string> +#else +using streamoff = long long; // for char_traits in <string> +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_IOS_H diff --git a/libcxx/include/__fwd/istream.h b/libcxx/include/__fwd/istream.h new file mode 100644 index 000000000000..a06907a6c8ef --- /dev/null +++ b/libcxx/include/__fwd/istream.h @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_ISTREAM_H +#define _LIBCPP___FWD_ISTREAM_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _CharT, class _Traits = char_traits<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_istream; + +template <class _CharT, class _Traits = char_traits<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_iostream; + +using istream = basic_istream<char>; +using iostream = basic_iostream<char>; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wistream = basic_istream<wchar_t>; +using wiostream = basic_iostream<wchar_t>; +#endif + +template <class _CharT, class _Traits> +class _LIBCPP_PREFERRED_NAME(istream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wistream)) basic_istream; + +template <class _CharT, class _Traits> +class _LIBCPP_PREFERRED_NAME(iostream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wiostream)) basic_iostream; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_ISTREAM_H diff --git a/libcxx/include/__fwd/mdspan.h b/libcxx/include/__fwd/mdspan.h new file mode 100644 index 000000000000..a3628c2d60dc --- /dev/null +++ b/libcxx/include/__fwd/mdspan.h @@ -0,0 +1,60 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___MDSPAN_LAYOUTS_H +#define _LIBCPP___MDSPAN_LAYOUTS_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +// Layout policy with a mapping which corresponds to FORTRAN-style array layouts +struct layout_left { + template <class _Extents> + class mapping; +}; + +// Layout policy with a mapping which corresponds to C-style array layouts +struct layout_right { + template <class _Extents> + class mapping; +}; + +/* +// Will be implemented with follow on revision +// Layout policy with a unique mapping where strides are arbitrary +struct layout_stride { + template<class Extents> + class mapping; +}; +*/ + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_LAYOUTS_H diff --git a/libcxx/include/__fwd/memory_resource.h b/libcxx/include/__fwd/memory_resource.h index 718a9078d3cf..03b78ad2bd3c 100644 --- a/libcxx/include/__fwd/memory_resource.h +++ b/libcxx/include/__fwd/memory_resource.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___FWD_MEMORY_RESOURCE_H #define _LIBCPP___FWD_MEMORY_RESOURCE_H +#include <__availability> #include <__config> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -19,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template <class _ValueType> -class _LIBCPP_TEMPLATE_VIS polymorphic_allocator; +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_TEMPLATE_VIS polymorphic_allocator; } // namespace pmr _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__fwd/ostream.h b/libcxx/include/__fwd/ostream.h new file mode 100644 index 000000000000..3347e0f71d7a --- /dev/null +++ b/libcxx/include/__fwd/ostream.h @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_OSTREAM_H +#define _LIBCPP___FWD_OSTREAM_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _CharT, class _Traits = char_traits<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_ostream; + +using ostream = basic_ostream<char>; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wostream = basic_ostream<wchar_t>; +#endif + +template <class _CharT, class _Traits> +class _LIBCPP_PREFERRED_NAME(ostream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wostream)) basic_ostream; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_OSTREAM_H diff --git a/libcxx/include/__fwd/span.h b/libcxx/include/__fwd/span.h index 943cb13fa1bb..e9fa70382f59 100644 --- a/libcxx/include/__fwd/span.h +++ b/libcxx/include/__fwd/span.h @@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max(); template <typename _Tp, size_t _Extent = dynamic_extent> class span; diff --git a/libcxx/include/__fwd/sstream.h b/libcxx/include/__fwd/sstream.h new file mode 100644 index 000000000000..e2d46fbe1d9b --- /dev/null +++ b/libcxx/include/__fwd/sstream.h @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_SSTREAM_H +#define _LIBCPP___FWD_SSTREAM_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _CharT, class _Traits = char_traits<_CharT>, class _Allocator = allocator<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_stringbuf; + +template <class _CharT, class _Traits = char_traits<_CharT>, class _Allocator = allocator<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_istringstream; +template <class _CharT, class _Traits = char_traits<_CharT>, class _Allocator = allocator<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_ostringstream; +template <class _CharT, class _Traits = char_traits<_CharT>, class _Allocator = allocator<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_stringstream; + +using stringbuf = basic_stringbuf<char>; +using istringstream = basic_istringstream<char>; +using ostringstream = basic_ostringstream<char>; +using stringstream = basic_stringstream<char>; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wstringbuf = basic_stringbuf<wchar_t>; +using wistringstream = basic_istringstream<wchar_t>; +using wostringstream = basic_ostringstream<wchar_t>; +using wstringstream = basic_stringstream<wchar_t>; +#endif + +template <class _CharT, class _Traits, class _Allocator> +class _LIBCPP_PREFERRED_NAME(stringbuf) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstringbuf)) basic_stringbuf; +template <class _CharT, class _Traits, class _Allocator> +class _LIBCPP_PREFERRED_NAME(istringstream) + _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wistringstream)) basic_istringstream; +template <class _CharT, class _Traits, class _Allocator> +class _LIBCPP_PREFERRED_NAME(ostringstream) + _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wostringstream)) basic_ostringstream; +template <class _CharT, class _Traits, class _Allocator> +class _LIBCPP_PREFERRED_NAME(stringstream) + _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstringstream)) basic_stringstream; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_SSTREAM_H diff --git a/libcxx/include/__fwd/streambuf.h b/libcxx/include/__fwd/streambuf.h new file mode 100644 index 000000000000..b35afa6afe34 --- /dev/null +++ b/libcxx/include/__fwd/streambuf.h @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_STREAMBUF_H +#define _LIBCPP___FWD_STREAMBUF_H + +#include <__config> +#include <__fwd/string.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _CharT, class _Traits = char_traits<_CharT> > +class _LIBCPP_TEMPLATE_VIS basic_streambuf; + +using streambuf = basic_streambuf<char>; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +using wstreambuf = basic_streambuf<wchar_t>; +#endif + +template <class _CharT, class _Traits> +class _LIBCPP_PREFERRED_NAME(streambuf) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstreambuf)) basic_streambuf; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_STREAMBUF_H diff --git a/libcxx/include/__fwd/string.h b/libcxx/include/__fwd/string.h index 7ab5561b758f..032132374de5 100644 --- a/libcxx/include/__fwd/string.h +++ b/libcxx/include/__fwd/string.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___FWD_STRING_H #define _LIBCPP___FWD_STRING_H +#include <__availability> #include <__config> #include <__fwd/memory_resource.h> @@ -61,21 +62,20 @@ using u32string = basic_string<char32_t>; namespace pmr { template <class _CharT, class _Traits = char_traits<_CharT>> -using basic_string = std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>; +using basic_string _LIBCPP_AVAILABILITY_PMR = std::basic_string<_CharT, _Traits, polymorphic_allocator<_CharT>>; -using string = basic_string<char>; +using string _LIBCPP_AVAILABILITY_PMR = basic_string<char>; # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -using wstring = basic_string<wchar_t>; +using wstring _LIBCPP_AVAILABILITY_PMR = basic_string<wchar_t>; # endif # ifndef _LIBCPP_HAS_NO_CHAR8_T -using u8string = basic_string<char8_t>; +using u8string _LIBCPP_AVAILABILITY_PMR = basic_string<char8_t>; # endif -using u16string = basic_string<char16_t>; -using u32string = basic_string<char32_t>; - +using u16string _LIBCPP_AVAILABILITY_PMR = basic_string<char16_t>; +using u32string _LIBCPP_AVAILABILITY_PMR = basic_string<char32_t>; } // namespace pmr #endif // _LIBCPP_STD_VER >= 17 diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index f8896c8664eb..2ae7afdc10de 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -15,8 +15,8 @@ #include <__assert> #include <__bit/countl.h> #include <__config> -#include <__debug> #include <__functional/hash.h> +#include <__functional/invoke.h> #include <__iterator/iterator_traits.h> #include <__memory/addressof.h> #include <__memory/allocator_traits.h> @@ -25,6 +25,19 @@ #include <__memory/swap_allocator.h> #include <__memory/unique_ptr.h> #include <__type_traits/can_extract_key.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -32,7 +45,6 @@ #include <cmath> #include <cstring> #include <initializer_list> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -59,8 +71,7 @@ struct __is_hash_value_type : false_type {}; template <class _One> struct __is_hash_value_type<_One> : __is_hash_value_type_imp<__remove_cvref_t<_One> > {}; -_LIBCPP_FUNC_VIS -size_t __next_prime(size_t __n); +_LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t __n); template <class _NodePtr> struct __hash_node_base @@ -296,53 +307,20 @@ public: typedef typename _NodeTypes::__node_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT : __node_(nullptr) { - _VSTD::__debug_db_insert_i(this); } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY - __hash_iterator(const __hash_iterator& __i) - : __node_(__i.__node_) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_iterator& operator=(const __hash_iterator& __i) - { - if (this != _VSTD::addressof(__i)) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - __node_ = __i.__node_; - } - return *this; - } -#endif // _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container iterator"); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container iterator"); return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable unordered container iterator"); __node_ = __node_->__next_; return *this; } @@ -366,14 +344,11 @@ public: private: _LIBCPP_INLINE_VISIBILITY - explicit __hash_iterator(__next_pointer __node, const void* __c) _NOEXCEPT + explicit __hash_iterator(__next_pointer __node) _NOEXCEPT : __node_(__node) { - (void)__c; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__insert_ic(this, __c); -#endif } + template <class, class, class, class> friend class __hash_table; template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator; template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; @@ -402,61 +377,25 @@ public: _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT : __node_(nullptr) { - _VSTD::__debug_db_insert_i(this); } _LIBCPP_INLINE_VISIBILITY __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT : __node_(__x.__node_) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); -#endif } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY - __hash_const_iterator(const __hash_const_iterator& __i) - : __node_(__i.__node_) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_const_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_const_iterator& operator=(const __hash_const_iterator& __i) - { - if (this != _VSTD::addressof(__i)) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - __node_ = __i.__node_; - } - return *this; - } -#endif // _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_iterator"); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_iterator"); return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_const_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable unordered container const_iterator"); __node_ = __node_->__next_; return *this; } @@ -480,14 +419,11 @@ public: private: _LIBCPP_INLINE_VISIBILITY - explicit __hash_const_iterator(__next_pointer __node, const void* __c) _NOEXCEPT + explicit __hash_const_iterator(__next_pointer __node) _NOEXCEPT : __node_(__node) { - (void)__c; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__insert_ic(this, __c); -#endif } + template <class, class, class, class> friend class __hash_table; template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_map; @@ -513,57 +449,20 @@ public: typedef typename _NodeTypes::__node_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT : __node_(nullptr) { - _VSTD::__debug_db_insert_i(this); - } - -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY - __hash_local_iterator(const __hash_local_iterator& __i) - : __node_(__i.__node_), - __bucket_(__i.__bucket_), - __bucket_count_(__i.__bucket_count_) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_local_iterator() - { - __get_db()->__erase_i(this); } _LIBCPP_INLINE_VISIBILITY - __hash_local_iterator& operator=(const __hash_local_iterator& __i) - { - if (this != _VSTD::addressof(__i)) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - __node_ = __i.__node_; - __bucket_ = __i.__bucket_; - __bucket_count_ = __i.__bucket_count_; - } - return *this; - } -#endif // _LIBCPP_ENABLE_DEBUG_MODE - - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container local_iterator"); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container local_iterator"); return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_local_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable unordered container local_iterator"); __node_ = __node_->__next_; if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; @@ -590,18 +489,15 @@ public: private: _LIBCPP_INLINE_VISIBILITY explicit __hash_local_iterator(__next_pointer __node, size_t __bucket, - size_t __bucket_count, const void* __c) _NOEXCEPT + size_t __bucket_count) _NOEXCEPT : __node_(__node), __bucket_(__bucket), __bucket_count_(__bucket_count) { - (void)__c; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__insert_ic(this, __c); -#endif if (__node_ != nullptr) __node_ = __node_->__next_; } + template <class, class, class, class> friend class __hash_table; template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator; template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator; @@ -635,7 +531,6 @@ public: _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT : __node_(nullptr) { - _VSTD::__debug_db_insert_i(this); } _LIBCPP_INLINE_VISIBILITY @@ -644,59 +539,20 @@ public: __bucket_(__x.__bucket_), __bucket_count_(__x.__bucket_count_) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); -#endif } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY - __hash_const_local_iterator(const __hash_const_local_iterator& __i) - : __node_(__i.__node_), - __bucket_(__i.__bucket_), - __bucket_count_(__i.__bucket_count_) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - } - - _LIBCPP_INLINE_VISIBILITY - ~__hash_const_local_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i) - { - if (this != _VSTD::addressof(__i)) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__i)); - __node_ = __i.__node_; - __bucket_ = __i.__bucket_; - __bucket_count_ = __i.__bucket_count_; - } - return *this; - } -#endif // _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); return __node_->__upcast()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_); } _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable unordered container const_local_iterator"); __node_ = __node_->__next_; if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; @@ -723,18 +579,15 @@ public: private: _LIBCPP_INLINE_VISIBILITY explicit __hash_const_local_iterator(__next_pointer __node_ptr, size_t __bucket, - size_t __bucket_count, const void* __c) _NOEXCEPT + size_t __bucket_count) _NOEXCEPT : __node_(__node_ptr), __bucket_(__bucket), __bucket_count_(__bucket_count) { - (void)__c; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__insert_ic(this, __c); -#endif if (__node_ != nullptr) __node_ = __node_->__next_; } + template <class, class, class, class> friend class __hash_table; template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator; }; @@ -803,8 +656,8 @@ private: public: bool __value_constructed; - __hash_node_destructor(__hash_node_destructor const&) = default; - __hash_node_destructor& operator=(const __hash_node_destructor&) = delete; + _LIBCPP_HIDE_FROM_ABI __hash_node_destructor(__hash_node_destructor const&) = default; + _LIBCPP_HIDE_FROM_ABI __hash_node_destructor& operator=(const __hash_node_destructor&) = delete; _LIBCPP_INLINE_VISIBILITY @@ -826,7 +679,7 @@ public: template <class> friend class __hash_map_node_destructor; }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _NodeType, class _Alloc> struct __generic_container_node_destructor; @@ -976,22 +829,22 @@ public: is_nothrow_default_constructible<key_equal>::value); _LIBCPP_INLINE_VISIBILITY __hash_table(const hasher& __hf, const key_equal& __eql); - __hash_table(const hasher& __hf, const key_equal& __eql, + _LIBCPP_HIDE_FROM_ABI __hash_table(const hasher& __hf, const key_equal& __eql, const allocator_type& __a); - explicit __hash_table(const allocator_type& __a); - __hash_table(const __hash_table& __u); - __hash_table(const __hash_table& __u, const allocator_type& __a); - __hash_table(__hash_table&& __u) + _LIBCPP_HIDE_FROM_ABI explicit __hash_table(const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI __hash_table(const __hash_table& __u); + _LIBCPP_HIDE_FROM_ABI __hash_table(const __hash_table& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI __hash_table(__hash_table&& __u) _NOEXCEPT_( is_nothrow_move_constructible<__bucket_list>::value && is_nothrow_move_constructible<__first_node>::value && is_nothrow_move_constructible<__node_allocator>::value && is_nothrow_move_constructible<hasher>::value && is_nothrow_move_constructible<key_equal>::value); - __hash_table(__hash_table&& __u, const allocator_type& __a); - ~__hash_table(); + _LIBCPP_HIDE_FROM_ABI __hash_table(__hash_table&& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI ~__hash_table(); - __hash_table& operator=(const __hash_table& __u); + _LIBCPP_HIDE_FROM_ABI __hash_table& operator=(const __hash_table& __u); _LIBCPP_INLINE_VISIBILITY __hash_table& operator=(__hash_table&& __u) _NOEXCEPT_( @@ -1000,9 +853,9 @@ public: is_nothrow_move_assignable<hasher>::value && is_nothrow_move_assignable<key_equal>::value); template <class _InputIterator> - void __assign_unique(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI void __assign_unique(_InputIterator __first, _InputIterator __last); template <class _InputIterator> - void __assign_multi(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI void __assign_multi(_InputIterator __first, _InputIterator __last); _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT @@ -1121,7 +974,7 @@ public: return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _NodeHandle, class _InsertReturnType> _LIBCPP_INLINE_VISIBILITY _InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh); @@ -1151,7 +1004,7 @@ public: _NodeHandle __node_handle_extract(const_iterator __it); #endif - void clear() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY void __rehash_unique(size_type __n) { __rehash<true>(__n); } _LIBCPP_INLINE_VISIBILITY void __rehash_multi(size_type __n) { __rehash<false>(__n); } _LIBCPP_INLINE_VISIBILITY void __reserve_unique(size_type __n) @@ -1182,48 +1035,48 @@ public: _LIBCPP_INLINE_VISIBILITY size_type bucket(const _Key& __k) const { - _LIBCPP_ASSERT(bucket_count() > 0, + _LIBCPP_ASSERT_UNCATEGORIZED(bucket_count() > 0, "unordered container::bucket(key) called when bucket_count() == 0"); return std::__constrain_hash(hash_function()(__k), bucket_count()); } template <class _Key> - iterator find(const _Key& __x); + _LIBCPP_HIDE_FROM_ABI iterator find(const _Key& __x); template <class _Key> - const_iterator find(const _Key& __x) const; + _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Key& __x) const; typedef __hash_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; - iterator erase(const_iterator __p); - iterator erase(const_iterator __first, const_iterator __last); + _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p); + _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last); template <class _Key> - size_type __erase_unique(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI size_type __erase_unique(const _Key& __k); template <class _Key> - size_type __erase_multi(const _Key& __k); - __node_holder remove(const_iterator __p) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI size_type __erase_multi(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI __node_holder remove(const_iterator __p) _NOEXCEPT; template <class _Key> _LIBCPP_INLINE_VISIBILITY size_type __count_unique(const _Key& __k) const; template <class _Key> - size_type __count_multi(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI size_type __count_multi(const _Key& __k) const; template <class _Key> - pair<iterator, iterator> + _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_unique(const _Key& __k); template <class _Key> - pair<const_iterator, const_iterator> + _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> __equal_range_unique(const _Key& __k) const; template <class _Key> - pair<iterator, iterator> + _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_multi(const _Key& __k); template <class _Key> - pair<const_iterator, const_iterator> + _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> __equal_range_multi(const _Key& __k) const; - void swap(__hash_table& __u) + _LIBCPP_HIDE_FROM_ABI void swap(__hash_table& __u) #if _LIBCPP_STD_VER <= 11 _NOEXCEPT_( __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value @@ -1239,7 +1092,7 @@ public: _LIBCPP_INLINE_VISIBILITY size_type max_bucket_count() const _NOEXCEPT {return max_size(); } - size_type bucket_size(size_type __n) const; + _LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const; _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT { size_type __bc = bucket_count(); @@ -1247,7 +1100,7 @@ public: } _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT { - _LIBCPP_ASSERT(__mlf > 0, + _LIBCPP_ASSERT_UNCATEGORIZED(__mlf > 0, "unordered container::max_load_factor(lf) called with lf <= 0"); max_load_factor() = _VSTD::max(__mlf, load_factor()); } @@ -1256,68 +1109,61 @@ public: local_iterator begin(size_type __n) { - _LIBCPP_ASSERT(__n < bucket_count(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(), "unordered container::begin(n) called with n >= bucket_count()"); - return local_iterator(__bucket_list_[__n], __n, bucket_count(), this); + return local_iterator(__bucket_list_[__n], __n, bucket_count()); } _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n) { - _LIBCPP_ASSERT(__n < bucket_count(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(), "unordered container::end(n) called with n >= bucket_count()"); - return local_iterator(nullptr, __n, bucket_count(), this); + return local_iterator(nullptr, __n, bucket_count()); } _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const { - _LIBCPP_ASSERT(__n < bucket_count(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(), "unordered container::cbegin(n) called with n >= bucket_count()"); - return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this); + return const_local_iterator(__bucket_list_[__n], __n, bucket_count()); } _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const { - _LIBCPP_ASSERT(__n < bucket_count(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(), "unordered container::cend(n) called with n >= bucket_count()"); - return const_local_iterator(nullptr, __n, bucket_count(), this); + return const_local_iterator(nullptr, __n, bucket_count()); } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - bool __dereferenceable(const const_iterator* __i) const; - bool __decrementable(const const_iterator* __i) const; - bool __addable(const const_iterator* __i, ptrdiff_t __n) const; - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - private: - template <bool _UniqueKeys> void __rehash(size_type __n); - template <bool _UniqueKeys> void __do_rehash(size_type __n); + template <bool _UniqueKeys> + _LIBCPP_HIDE_FROM_ABI void __rehash(size_type __n); + template <bool _UniqueKeys> + _LIBCPP_HIDE_FROM_ABI void __do_rehash(size_type __n); template <class ..._Args> - __node_holder __construct_node(_Args&& ...__args); + _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&& ...__args); template <class _First, class ..._Rest> - __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest); + _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest); _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __hash_table& __u) {__copy_assign_alloc(__u, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>());} - void __copy_assign_alloc(const __hash_table& __u, true_type); + _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u, true_type); _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __hash_table&, false_type) {} - void __move_assign(__hash_table& __u, false_type); - void __move_assign(__hash_table& __u, true_type) + _LIBCPP_HIDE_FROM_ABI void __move_assign(__hash_table& __u, false_type); + _LIBCPP_HIDE_FROM_ABI void __move_assign(__hash_table& __u, true_type) _NOEXCEPT_( is_nothrow_move_assignable<__node_allocator>::value && is_nothrow_move_assignable<hasher>::value && @@ -1343,8 +1189,8 @@ private: _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {} - void __deallocate_node(__next_pointer __np) _NOEXCEPT; - __next_pointer __detach() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void __deallocate_node(__next_pointer __np) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT; template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_map; template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; @@ -1476,7 +1322,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() #endif __deallocate_node(__p1_.first().__next_); - std::__debug_db_erase_c(this); } template <class _Tp, class _Hash, class _Equal, class _Alloc> @@ -1518,21 +1363,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np) while (__np != nullptr) { __next_pointer __next = __np->__next_; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __p = __c->end_; __p != __c->beg_; ) - { - --__p; - iterator* __i = static_cast<iterator*>((*__p)->__i_); - if (__i->__node_ == __np) - { - (*__p)->__c_ = nullptr; - if (--__c->end_ != __p) - _VSTD::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#endif __node_pointer __real_np = __np->__upcast(); __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__value_)); __node_traits::deallocate(__na, __real_np, 1); @@ -1579,7 +1409,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( __u.__p1_.first().__next_ = nullptr; __u.size() = 0; } - std::__debug_db_swap(this, std::addressof(__u)); } template <class _Tp, class _Hash, class _Equal, class _Alloc> @@ -1597,10 +1426,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( if (bucket_count() != 0) { __next_pointer __cache = __detach(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS const_iterator __i = __u.begin(); while (__cache != nullptr && __u.size() != 0) { @@ -1610,14 +1439,14 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( __node_insert_multi(__cache->__upcast()); __cache = __next; } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __deallocate_node(__cache); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __deallocate_node(__cache); } const_iterator __i = __u.begin(); @@ -1659,10 +1488,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first if (bucket_count() != 0) { __next_pointer __cache = __detach(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { __cache->__upcast()->__value_ = *__first; @@ -1670,14 +1499,14 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first __node_insert_unique(__cache->__upcast()); __cache = __next; } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __deallocate_node(__cache); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __deallocate_node(__cache); } for (; __first != __last; ++__first) @@ -1699,10 +1528,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, if (bucket_count() != 0) { __next_pointer __cache = __detach(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __cache != nullptr && __first != __last; ++__first) { __cache->__upcast()->__value_ = *__first; @@ -1710,14 +1539,14 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, __node_insert_multi(__cache->__upcast()); __cache = __next; } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __deallocate_node(__cache); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __deallocate_node(__cache); } for (; __first != __last; ++__first) @@ -1729,7 +1558,7 @@ inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT { - return iterator(__p1_.first().__next_, this); + return iterator(__p1_.first().__next_); } template <class _Tp, class _Hash, class _Equal, class _Alloc> @@ -1737,7 +1566,7 @@ inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT { - return iterator(nullptr, this); + return iterator(nullptr); } template <class _Tp, class _Hash, class _Equal, class _Alloc> @@ -1745,7 +1574,7 @@ inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT { - return const_iterator(__p1_.first().__next_, this); + return const_iterator(__p1_.first().__next_); } template <class _Tp, class _Hash, class _Equal, class _Alloc> @@ -1753,7 +1582,7 @@ inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT { - return const_iterator(nullptr, this); + return const_iterator(nullptr); } template <class _Tp, class _Hash, class _Equal, class _Alloc> @@ -1794,10 +1623,12 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare( if (__ndptr != nullptr) { for (__ndptr = __ndptr->__next_; __ndptr != nullptr && - std::__constrain_hash(__ndptr->__hash(), __bc) == __chash; + (__ndptr->__hash() == __hash || + std::__constrain_hash(__ndptr->__hash(), __bc) == __chash); __ndptr = __ndptr->__next_) { - if (key_eq()(__ndptr->__upcast()->__value_, __value)) + if ((__ndptr->__hash() == __hash) && + key_eq()(__ndptr->__upcast()->__value_, __value)) return __ndptr; } } @@ -1858,7 +1689,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __ __existing_node = __nd->__ptr(); __inserted = true; } - return pair<iterator, bool>(iterator(__existing_node, this), __inserted); + return pair<iterator, bool>(iterator(__existing_node), __inserted); } // Prepare the container for an insertion of the value __cp_val with the hash @@ -1952,7 +1783,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __c __next_pointer __pn = __node_insert_multi_prepare(__cp->__hash(), __cp->__value_); __node_insert_multi_perform(__cp, __pn); - return iterator(__cp->__ptr(), this); + return iterator(__cp->__ptr()); } template <class _Tp, class _Hash, class _Equal, class _Alloc> @@ -1960,9 +1791,6 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( const_iterator __p, __node_pointer __cp) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" - " referring to this unordered container"); if (__p != end() && key_eq()(*__p, __cp->__value_)) { __next_pointer __np = __p.__node_; @@ -1981,7 +1809,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( __cp->__next_ = __np; __pp->__next_ = static_cast<__next_pointer>(__cp); ++size(); - return iterator(static_cast<__next_pointer>(__cp), this); + return iterator(static_cast<__next_pointer>(__cp)); } return __node_insert_multi(__cp); } @@ -2009,7 +1837,8 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash); __nd = __nd->__next_) { - if (key_eq()(__nd->__upcast()->__value_, __k)) + if ((__nd->__hash() == __hash) && + key_eq()(__nd->__upcast()->__value_, __k)) goto __done; } } @@ -2047,7 +1876,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __inserted = true; } __done: - return pair<iterator, bool>(iterator(__nd, this), __inserted); + return pair<iterator, bool>(iterator(__nd), __inserted); } template <class _Tp, class _Hash, class _Equal, class _Alloc> @@ -2079,16 +1908,13 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi( const_iterator __p, _Args&&... __args) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" - " referring to this unordered container"); __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); iterator __r = __node_insert_multi(__p, __h.get()); __h.release(); return __r; } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp, class _Hash, class _Equal, class _Alloc> template <class _NodeHandle, class _InsertReturnType> _LIBCPP_INLINE_VISIBILITY @@ -2218,7 +2044,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_multi( __node_insert_multi_perform(__src_ptr, __pn); } } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 template <class _Tp, class _Hash, class _Equal, class _Alloc> template <bool _UniqueKeys> @@ -2251,7 +2077,6 @@ template <bool _UniqueKeys> void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __nbc) { - std::__debug_db_invalidate_all(this); __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc(); __bucket_list_.reset(__nbc > 0 ? __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr); @@ -2323,7 +2148,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) { if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__value_, __k)) - return iterator(__nd, this); + return iterator(__nd); } } } @@ -2350,7 +2175,7 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const { if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__value_, __k)) - return const_iterator(__nd, this); + return const_iterator(__nd); } } @@ -2398,12 +2223,9 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) { __next_pointer __np = __p.__node_; - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "unordered container erase(iterator) called with an iterator not" - " referring to this container"); - _LIBCPP_ASSERT(__p != end(), - "unordered container erase(iterator) called with a non-dereferenceable iterator"); - iterator __r(__np, this); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p != end(), + "unordered container::erase(iterator) called with a non-dereferenceable iterator"); + iterator __r(__np); ++__r; remove(__p); return __r; @@ -2414,19 +2236,13 @@ typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, const_iterator __last) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__first)) == this, - "unordered container::erase(iterator, iterator) called with an iterator not" - " referring to this container"); - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__last)) == this, - "unordered container::erase(iterator, iterator) called with an iterator not" - " referring to this container"); for (const_iterator __p = __first; __first != __last; __p = __first) { ++__first; erase(__p); } __next_pointer __np = __last.__node_; - return iterator (__np, this); + return iterator (__np); } template <class _Tp, class _Hash, class _Equal, class _Alloc> @@ -2493,21 +2309,6 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT __pn->__next_ = __cn->__next_; __cn->__next_ = nullptr; --size(); -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __dp = __c->end_; __dp != __c->beg_; ) - { - --__dp; - iterator* __i = static_cast<iterator*>((*__dp)->__i_); - if (__i->__node_ == __cn) - { - (*__dp)->__c_ = nullptr; - if (--__c->end_ != __dp) - _VSTD::memmove(__dp, __dp+1, (__c->end_ - __dp)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#endif return __node_holder(__cn->__upcast(), _Dp(__node_alloc(), true)); } @@ -2622,10 +2423,10 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) _NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value) #endif { - _LIBCPP_ASSERT(__node_traits::propagate_on_container_swap::value || - this->__node_alloc() == __u.__node_alloc(), - "list::swap: Either propagate_on_container_swap must be true" - " or the allocators must compare equal"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__node_traits::propagate_on_container_swap::value || + this->__node_alloc() == __u.__node_alloc(), + "unordered container::swap: Either propagate_on_container_swap " + "must be true or the allocators must compare equal"); { __node_pointer_pointer __npp = __bucket_list_.release(); __bucket_list_.reset(__u.__bucket_list_.release()); @@ -2644,14 +2445,13 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) if (__u.size() > 0) __u.__bucket_list_[std::__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] = __u.__p1_.first().__ptr(); - std::__debug_db_swap(this, std::addressof(__u)); } template <class _Tp, class _Hash, class _Equal, class _Alloc> typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type __hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const { - _LIBCPP_ASSERT(__n < bucket_count(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < bucket_count(), "unordered container::bucket_size(n) called with n >= bucket_count()"); __next_pointer __np = __bucket_list_[__n]; size_type __bc = bucket_count(); @@ -2676,38 +2476,6 @@ swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x, __x.swap(__y); } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - -template <class _Tp, class _Hash, class _Equal, class _Alloc> -bool -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const -{ - return __i->__node_ != nullptr; -} - -template <class _Tp, class _Hash, class _Equal, class _Alloc> -bool -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const -{ - return false; -} - -template <class _Tp, class _Hash, class _Equal, class _Alloc> -bool -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const -{ - return false; -} - -template <class _Tp, class _Hash, class _Equal, class _Alloc> -bool -__hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const -{ - return false; -} - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/libcxx/include/__iterator/access.h b/libcxx/include/__iterator/access.h index 0b8d5230171b..d7bcb3378d56 100644 --- a/libcxx/include/__iterator/access.h +++ b/libcxx/include/__iterator/access.h @@ -69,7 +69,7 @@ end(const _Cp& __c) -> decltype(__c.end()) return __c.end(); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Cp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 diff --git a/libcxx/include/__iterator/advance.h b/libcxx/include/__iterator/advance.h index 154c2736f313..04cbe0767ae4 100644 --- a/libcxx/include/__iterator/advance.h +++ b/libcxx/include/__iterator/advance.h @@ -23,13 +23,15 @@ #include <__utility/declval.h> #include <__utility/move.h> #include <__utility/unreachable.h> -#include <cstdlib> #include <limits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _InputIter> @@ -64,12 +66,12 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void advance(_InputIter& __i, _Distance __orig_n) { typedef typename iterator_traits<_InputIter>::difference_type _Difference; _Difference __n = static_cast<_Difference>(_VSTD::__convert_to_integral(__orig_n)); - _LIBCPP_ASSERT(__n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, - "Attempt to advance(it, n) with negative n on a non-bidirectional iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0 || __has_bidirectional_iterator_category<_InputIter>::value, + "Attempt to advance(it, n) with negative n on a non-bidirectional iterator"); _VSTD::__advance(__i, __n, typename iterator_traits<_InputIter>::iterator_category()); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.iter.op.advance] @@ -101,8 +103,8 @@ public: template <input_or_output_iterator _Ip> _LIBCPP_HIDE_FROM_ABI constexpr void operator()(_Ip& __i, iter_difference_t<_Ip> __n) const { - _LIBCPP_ASSERT(__n >= 0 || bidirectional_iterator<_Ip>, - "If `n < 0`, then `bidirectional_iterator<I>` must be true."); + _LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0 || bidirectional_iterator<_Ip>, + "If `n < 0`, then `bidirectional_iterator<I>` must be true."); // If `I` models `random_access_iterator`, equivalent to `i += n`. if constexpr (random_access_iterator<_Ip>) { @@ -148,8 +150,8 @@ public: template <input_or_output_iterator _Ip, sentinel_for<_Ip> _Sp> _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Ip> operator()(_Ip& __i, iter_difference_t<_Ip> __n, _Sp __bound_sentinel) const { - _LIBCPP_ASSERT((__n >= 0) || (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>), - "If `n < 0`, then `bidirectional_iterator<I> && same_as<I, S>` must be true."); + _LIBCPP_ASSERT_UNCATEGORIZED((__n >= 0) || (bidirectional_iterator<_Ip> && same_as<_Ip, _Sp>), + "If `n < 0`, then `bidirectional_iterator<I> && same_as<I, S>` must be true."); // If `S` and `I` model `sized_sentinel_for<S, I>`: if constexpr (sized_sentinel_for<_Sp, _Ip>) { // If |n| >= |bound_sentinel - i|, equivalent to `ranges::advance(i, bound_sentinel)`. @@ -159,9 +161,9 @@ public: __a > 0 ? __a >= __b : __a <= __b; }; - if (const auto __M = __bound_sentinel - __i; __magnitude_geq(__n, __M)) { + if (const auto __m = __bound_sentinel - __i; __magnitude_geq(__n, __m)) { (*this)(__i, __bound_sentinel); - return __n - __M; + return __n - __m; } // Otherwise, equivalent to `ranges::advance(i, n)`. @@ -196,8 +198,10 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_ADVANCE_H diff --git a/libcxx/include/__iterator/back_insert_iterator.h b/libcxx/include/__iterator/back_insert_iterator.h index 4c00a7e39796..a0083da1519f 100644 --- a/libcxx/include/__iterator/back_insert_iterator.h +++ b/libcxx/include/__iterator/back_insert_iterator.h @@ -21,6 +21,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -36,7 +39,7 @@ protected: public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; @@ -70,4 +73,6 @@ back_inserter(_Container& __x) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_BACK_INSERT_ITERATOR_H diff --git a/libcxx/include/__iterator/bounded_iter.h b/libcxx/include/__iterator/bounded_iter.h index 2682f2a68a22..2a667648871c 100644 --- a/libcxx/include/__iterator/bounded_iter.h +++ b/libcxx/include/__iterator/bounded_iter.h @@ -23,6 +23,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // Iterator wrapper that carries the valid range it is allowed to access. @@ -35,14 +38,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Arithmetic operations are allowed and the bounds of the resulting iterator // are not checked. Hence, it is possible to create an iterator pointing outside // its range, but it is not possible to dereference it. -template <class _Iterator, class = __enable_if_t< __is_cpp17_contiguous_iterator<_Iterator>::value > > +template <class _Iterator, class = __enable_if_t< __libcpp_is_contiguous_iterator<_Iterator>::value > > struct __bounded_iter { using value_type = typename iterator_traits<_Iterator>::value_type; using difference_type = typename iterator_traits<_Iterator>::difference_type; using pointer = typename iterator_traits<_Iterator>::pointer; using reference = typename iterator_traits<_Iterator>::reference; using iterator_category = typename iterator_traits<_Iterator>::iterator_category; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using iterator_concept = contiguous_iterator_tag; #endif @@ -78,7 +81,7 @@ private: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __bounded_iter( _Iterator __current, _Iterator __begin, _Iterator __end) : __current_(__current), __begin_(__begin), __end_(__end) { - _LIBCPP_ASSERT(__begin <= __end, "__bounded_iter(current, begin, end): [begin, end) is not a valid range"); + _LIBCPP_ASSERT_INTERNAL(__begin <= __end, "__bounded_iter(current, begin, end): [begin, end) is not a valid range"); } template <class _It> @@ -89,19 +92,19 @@ public: // // These operations check that the iterator is dereferenceable, that is within [begin, end). _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT { - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __in_bounds(__current_), "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); return *__current_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT { - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __in_bounds(__current_), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); return std::__to_address(__current_); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( __in_bounds(__current_ + __n), "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); return __current_[__n]; } @@ -212,7 +215,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __bounded_iter<_It> __make_bounded_iter( #if _LIBCPP_STD_VER <= 17 template <class _Iterator> -struct __is_cpp17_contiguous_iterator<__bounded_iter<_Iterator> > : true_type {}; +struct __libcpp_is_contiguous_iterator<__bounded_iter<_Iterator> > : true_type {}; #endif template <class _Iterator> @@ -228,4 +231,6 @@ struct pointer_traits<__bounded_iter<_Iterator> > { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_BOUNDED_ITER_H diff --git a/libcxx/include/__iterator/common_iterator.h b/libcxx/include/__iterator/common_iterator.h index f7883e2c372f..95e248d83f4b 100644 --- a/libcxx/include/__iterator/common_iterator.h +++ b/libcxx/include/__iterator/common_iterator.h @@ -25,6 +25,7 @@ #include <__iterator/iter_swap.h> #include <__iterator/iterator_traits.h> #include <__iterator/readable_traits.h> +#include <__memory/addressof.h> #include <__type_traits/is_pointer.h> #include <__utility/declval.h> #include <variant> @@ -33,9 +34,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class _Iter> concept __can_use_postfix_proxy = @@ -46,14 +50,14 @@ template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> requires (!same_as<_Iter, _Sent> && copyable<_Iter>) class common_iterator { struct __proxy { - constexpr const iter_value_t<_Iter>* operator->() const noexcept { + _LIBCPP_HIDE_FROM_ABI constexpr const iter_value_t<_Iter>* operator->() const noexcept { return _VSTD::addressof(__value_); } iter_value_t<_Iter> __value_; }; struct __postfix_proxy { - constexpr const iter_value_t<_Iter>& operator*() const noexcept { + _LIBCPP_HIDE_FROM_ABI constexpr const iter_value_t<_Iter>& operator*() const noexcept { return __value_; } iter_value_t<_Iter> __value_; @@ -62,16 +66,17 @@ class common_iterator { public: variant<_Iter, _Sent> __hold_; - common_iterator() requires default_initializable<_Iter> = default; + _LIBCPP_HIDE_FROM_ABI common_iterator() requires default_initializable<_Iter> = default; - constexpr common_iterator(_Iter __i) : __hold_(in_place_type<_Iter>, _VSTD::move(__i)) {} - constexpr common_iterator(_Sent __s) : __hold_(in_place_type<_Sent>, _VSTD::move(__s)) {} + _LIBCPP_HIDE_FROM_ABI constexpr common_iterator(_Iter __i) : __hold_(in_place_type<_Iter>, _VSTD::move(__i)) {} + _LIBCPP_HIDE_FROM_ABI constexpr common_iterator(_Sent __s) : __hold_(in_place_type<_Sent>, _VSTD::move(__s)) {} template<class _I2, class _S2> requires convertible_to<const _I2&, _Iter> && convertible_to<const _S2&, _Sent> - constexpr common_iterator(const common_iterator<_I2, _S2>& __other) + _LIBCPP_HIDE_FROM_ABI constexpr common_iterator(const common_iterator<_I2, _S2>& __other) : __hold_([&]() -> variant<_Iter, _Sent> { - _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to construct from a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__other.__hold_.valueless_by_exception(), + "Attempted to construct from a valueless common_iterator"); if (__other.__hold_.index() == 0) return variant<_Iter, _Sent>{in_place_index<0>, _VSTD::__unchecked_get<0>(__other.__hold_)}; return variant<_Iter, _Sent>{in_place_index<1>, _VSTD::__unchecked_get<1>(__other.__hold_)}; @@ -80,8 +85,9 @@ public: template<class _I2, class _S2> requires convertible_to<const _I2&, _Iter> && convertible_to<const _S2&, _Sent> && assignable_from<_Iter&, const _I2&> && assignable_from<_Sent&, const _S2&> - common_iterator& operator=(const common_iterator<_I2, _S2>& __other) { - _LIBCPP_ASSERT(!__other.__hold_.valueless_by_exception(), "Attempted to assign from a valueless common_iterator"); + _LIBCPP_HIDE_FROM_ABI common_iterator& operator=(const common_iterator<_I2, _S2>& __other) { + _LIBCPP_ASSERT_UNCATEGORIZED(!__other.__hold_.valueless_by_exception(), + "Attempted to assign from a valueless common_iterator"); auto __idx = __hold_.index(); auto __other_idx = __other.__hold_.index(); @@ -101,27 +107,30 @@ public: return *this; } - constexpr decltype(auto) operator*() + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__hold_), + "Attempted to dereference a non-dereferenceable common_iterator"); return *_VSTD::__unchecked_get<_Iter>(__hold_); } - constexpr decltype(auto) operator*() const + _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const requires __dereferenceable<const _Iter> { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__hold_), + "Attempted to dereference a non-dereferenceable common_iterator"); return *_VSTD::__unchecked_get<_Iter>(__hold_); } template<class _I2 = _Iter> - decltype(auto) operator->() const + _LIBCPP_HIDE_FROM_ABI decltype(auto) operator->() const requires indirectly_readable<const _I2> && (requires(const _I2& __i) { __i.operator->(); } || is_reference_v<iter_reference_t<_I2>> || constructible_from<iter_value_t<_I2>, iter_reference_t<_I2>>) { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to dereference a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__hold_), + "Attempted to dereference a non-dereferenceable common_iterator"); if constexpr (is_pointer_v<_Iter> || requires(const _Iter& __i) { __i.operator->(); }) { return _VSTD::__unchecked_get<_Iter>(__hold_); } else if constexpr (is_reference_v<iter_reference_t<_Iter>>) { @@ -132,13 +141,15 @@ public: } } - common_iterator& operator++() { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); + _LIBCPP_HIDE_FROM_ABI common_iterator& operator++() { + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__hold_), + "Attempted to increment a non-dereferenceable common_iterator"); ++_VSTD::__unchecked_get<_Iter>(__hold_); return *this; } - decltype(auto) operator++(int) { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__hold_), "Attempted to increment a non-dereferenceable common_iterator"); + _LIBCPP_HIDE_FROM_ABI decltype(auto) operator++(int) { + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__hold_), + "Attempted to increment a non-dereferenceable common_iterator"); if constexpr (forward_iterator<_Iter>) { auto __tmp = *this; ++*this; @@ -157,8 +168,10 @@ public: requires sentinel_for<_Sent, _I2> _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { - _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); - _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__x.__hold_.valueless_by_exception(), + "Attempted to compare a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__y.__hold_.valueless_by_exception(), + "Attempted to compare a valueless common_iterator"); auto __x_index = __x.__hold_.index(); auto __y_index = __y.__hold_.index(); @@ -176,8 +189,10 @@ public: requires sentinel_for<_Sent, _I2> && equality_comparable_with<_Iter, _I2> _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { - _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); - _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to compare a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__x.__hold_.valueless_by_exception(), + "Attempted to compare a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__y.__hold_.valueless_by_exception(), + "Attempted to compare a valueless common_iterator"); auto __x_index = __x.__hold_.index(); auto __y_index = __y.__hold_.index(); @@ -198,8 +213,10 @@ public: requires sized_sentinel_for<_Sent, _I2> _LIBCPP_HIDE_FROM_ABI friend constexpr iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { - _LIBCPP_ASSERT(!__x.__hold_.valueless_by_exception(), "Attempted to subtract from a valueless common_iterator"); - _LIBCPP_ASSERT(!__y.__hold_.valueless_by_exception(), "Attempted to subtract a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__x.__hold_.valueless_by_exception(), + "Attempted to subtract from a valueless common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(!__y.__hold_.valueless_by_exception(), + "Attempted to subtract a valueless common_iterator"); auto __x_index = __x.__hold_.index(); auto __y_index = __y.__hold_.index(); @@ -220,7 +237,8 @@ public: noexcept(noexcept(ranges::iter_move(std::declval<const _Iter&>()))) requires input_iterator<_Iter> { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__i.__hold_), "Attempted to iter_move a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__i.__hold_), + "Attempted to iter_move a non-dereferenceable common_iterator"); return ranges::iter_move( _VSTD::__unchecked_get<_Iter>(__i.__hold_)); } @@ -228,8 +246,10 @@ public: _LIBCPP_HIDE_FROM_ABI friend constexpr void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) noexcept(noexcept(ranges::iter_swap(std::declval<const _Iter&>(), std::declval<const _I2&>()))) { - _LIBCPP_ASSERT(std::holds_alternative<_Iter>(__x.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); - _LIBCPP_ASSERT(std::holds_alternative<_I2>(__y.__hold_), "Attempted to iter_swap a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_Iter>(__x.__hold_), + "Attempted to iter_swap a non-dereferenceable common_iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(std::holds_alternative<_I2>(__y.__hold_), + "Attempted to iter_swap a non-dereferenceable common_iterator"); return ranges::iter_swap(_VSTD::__unchecked_get<_Iter>(__x.__hold_), _VSTD::__unchecked_get<_I2>(__y.__hold_)); } }; @@ -274,8 +294,10 @@ struct iterator_traits<common_iterator<_Iter, _Sent>> { using reference = iter_reference_t<_Iter>; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_COMMON_ITERATOR_H diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h index d9d40a4249f4..dd9e8d6ac5fe 100644 --- a/libcxx/include/__iterator/concepts.h +++ b/libcxx/include/__iterator/concepts.h @@ -46,7 +46,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [iterator.concept.readable] template<class _In> @@ -293,7 +293,7 @@ concept indirectly_copyable_storable = // Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle // (both iter_swap and indirectly_swappable require indirectly_readable). -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/counted_iterator.h b/libcxx/include/__iterator/counted_iterator.h index 5fdbff4b4866..41b7e57d28c1 100644 --- a/libcxx/include/__iterator/counted_iterator.h +++ b/libcxx/include/__iterator/counted_iterator.h @@ -34,9 +34,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class> struct __counted_iterator_concept {}; @@ -83,7 +86,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr counted_iterator(_Iter __iter, iter_difference_t<_Iter> __n) : __current_(_VSTD::move(__iter)), __count_(__n) { - _LIBCPP_ASSERT(__n >= 0, "__n must not be negative."); + _LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0, "__n must not be negative."); } template<class _I2> @@ -112,7 +115,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() { - _LIBCPP_ASSERT(__count_ > 0, "Iterator is equal to or past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator is equal to or past end."); return *__current_; } @@ -120,7 +123,7 @@ public: constexpr decltype(auto) operator*() const requires __dereferenceable<const _Iter> { - _LIBCPP_ASSERT(__count_ > 0, "Iterator is equal to or past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator is equal to or past end."); return *__current_; } @@ -133,7 +136,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr counted_iterator& operator++() { - _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator already at or past end."); ++__current_; --__count_; return *this; @@ -141,21 +144,21 @@ public: _LIBCPP_HIDE_FROM_ABI decltype(auto) operator++(int) { - _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator already at or past end."); --__count_; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { return __current_++; } catch(...) { ++__count_; throw; } #else return __current_++; -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } _LIBCPP_HIDE_FROM_ABI constexpr counted_iterator operator++(int) requires forward_iterator<_Iter> { - _LIBCPP_ASSERT(__count_ > 0, "Iterator already at or past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ > 0, "Iterator already at or past end."); counted_iterator __tmp = *this; ++*this; return __tmp; @@ -198,7 +201,7 @@ public: constexpr counted_iterator& operator+=(iter_difference_t<_Iter> __n) requires random_access_iterator<_Iter> { - _LIBCPP_ASSERT(__n <= __count_, "Cannot advance iterator past end."); + _LIBCPP_ASSERT_UNCATEGORIZED(__n <= __count_, "Cannot advance iterator past end."); __current_ += __n; __count_ -= __n; return *this; @@ -237,9 +240,10 @@ public: constexpr counted_iterator& operator-=(iter_difference_t<_Iter> __n) requires random_access_iterator<_Iter> { - _LIBCPP_ASSERT(-__n <= __count_, "Attempt to subtract too large of a size: " - "counted_iterator would be decremented before the " - "first element of its range."); + _LIBCPP_ASSERT_UNCATEGORIZED(-__n <= __count_, + "Attempt to subtract too large of a size: " + "counted_iterator would be decremented before the " + "first element of its range."); __current_ -= __n; __count_ += __n; return *this; @@ -249,7 +253,7 @@ public: constexpr decltype(auto) operator[](iter_difference_t<_Iter> __n) const requires random_access_iterator<_Iter> { - _LIBCPP_ASSERT(__n < __count_, "Subscript argument must be less than size."); + _LIBCPP_ASSERT_UNCATEGORIZED(__n < __count_, "Subscript argument must be less than size."); return __current_[__n]; } @@ -280,7 +284,7 @@ public: noexcept(noexcept(ranges::iter_move(__i.__current_))) requires input_iterator<_Iter> { - _LIBCPP_ASSERT(__i.__count_ > 0, "Iterator must not be past end of range."); + _LIBCPP_ASSERT_UNCATEGORIZED(__i.__count_ > 0, "Iterator must not be past end of range."); return ranges::iter_move(__i.__current_); } @@ -289,8 +293,8 @@ public: friend constexpr void iter_swap(const counted_iterator& __x, const counted_iterator<_I2>& __y) noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) { - _LIBCPP_ASSERT(__x.__count_ > 0 && __y.__count_ > 0, - "Iterators must not be past end of range."); + _LIBCPP_ASSERT_UNCATEGORIZED(__x.__count_ > 0 && __y.__count_ > 0, + "Iterators must not be past end of range."); return ranges::iter_swap(__x.__current_, __y.__current_); } }; @@ -303,8 +307,10 @@ struct iterator_traits<counted_iterator<_Iter>> : iterator_traits<_Iter> { add_pointer_t<iter_reference_t<_Iter>>, void>; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_COUNTED_ITERATOR_H diff --git a/libcxx/include/__iterator/cpp17_iterator_concepts.h b/libcxx/include/__iterator/cpp17_iterator_concepts.h new file mode 100644 index 000000000000..c4f49fe74227 --- /dev/null +++ b/libcxx/include/__iterator/cpp17_iterator_concepts.h @@ -0,0 +1,185 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H +#define _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H + +#include <__concepts/boolean_testable.h> +#include <__concepts/convertible_to.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_signed.h> +#include <__type_traits/is_void.h> +#include <__utility/as_const.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/swap.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp> +concept __cpp17_move_constructible = is_move_constructible_v<_Tp>; + +template <class _Tp> +concept __cpp17_copy_constructible = __cpp17_move_constructible<_Tp> && is_copy_constructible_v<_Tp>; + +template <class _Tp> +concept __cpp17_move_assignable = requires(_Tp __lhs, _Tp __rhs) { + { __lhs = std::move(__rhs) } -> same_as<_Tp&>; +}; + +template <class _Tp> +concept __cpp17_copy_assignable = __cpp17_move_assignable<_Tp> && requires(_Tp __lhs, _Tp __rhs) { + { __lhs = __rhs } -> same_as<_Tp&>; + { __lhs = std::as_const(__rhs) } -> same_as<_Tp&>; +}; + +template <class _Tp> +concept __cpp17_destructible = requires(_Tp __v) { __v.~_Tp(); }; + +template <class _Tp> +concept __cpp17_equality_comparable = requires(_Tp __lhs, _Tp __rhs) { + { __lhs == __rhs } -> __boolean_testable; + { std::as_const(__lhs) == __rhs } -> __boolean_testable; + { __lhs == std::as_const(__rhs) } -> __boolean_testable; + { std::as_const(__lhs) == std::as_const(__rhs) } -> __boolean_testable; +}; + +template <class _Tp> +concept __cpp17_default_constructible = is_default_constructible_v<_Tp>; + +template <class _Iter> +concept __cpp17_iterator = + __cpp17_copy_constructible<_Iter> && __cpp17_copy_assignable<_Iter> && __cpp17_destructible<_Iter> && + (is_signed_v<__iter_diff_t<_Iter>> || is_void_v<__iter_diff_t<_Iter>>)&&requires(_Iter __iter) { + { *__iter }; + { ++__iter } -> same_as<_Iter&>; + }; + +template <class _Iter> +concept __cpp17_input_iterator = + __cpp17_iterator<_Iter> && __cpp17_equality_comparable<_Iter> && requires(_Iter __lhs, _Iter __rhs) { + { __lhs != __rhs } -> __boolean_testable; + { std::as_const(__lhs) != __rhs } -> __boolean_testable; + { __lhs != std::as_const(__rhs) } -> __boolean_testable; + { std::as_const(__lhs) != std::as_const(__rhs) } -> __boolean_testable; + + { *__lhs } -> same_as<__iter_reference<_Iter>>; + { *std::as_const(__lhs) } -> same_as<__iter_reference<_Iter>>; + + { ++__lhs } -> same_as<_Iter&>; + { (void)__lhs++ }; + { *__lhs++ }; + }; + +template <class _Iter, class _WriteTo> +concept __cpp17_output_iterator = __cpp17_iterator<_Iter> && requires(_Iter __iter, _WriteTo __write) { + { *__iter = std::forward<_WriteTo>(__write) }; + { ++__iter } -> same_as<_Iter&>; + { __iter++ } -> convertible_to<const _Iter&>; + { *__iter++ = std::forward<_WriteTo>(__write) }; +}; + +template <class _Iter> +concept __cpp17_forward_iterator = + __cpp17_input_iterator<_Iter> && __cpp17_default_constructible<_Iter> && requires(_Iter __iter) { + { __iter++ } -> convertible_to<const _Iter&>; + { *__iter++ } -> same_as<__iter_reference<_Iter>>; + }; + +template <class _Iter> +concept __cpp17_bidirectional_iterator = __cpp17_forward_iterator<_Iter> && requires(_Iter __iter) { + { --__iter } -> same_as<_Iter&>; + { __iter-- } -> convertible_to<const _Iter&>; + { *__iter-- } -> same_as<__iter_reference<_Iter>>; +}; + +template <class _Iter> +concept __cpp17_random_access_iterator = + __cpp17_bidirectional_iterator<_Iter> && requires(_Iter __iter, __iter_diff_t<_Iter> __n) { + { __iter += __n } -> same_as<_Iter&>; + + { __iter + __n } -> same_as<_Iter>; + { __n + __iter } -> same_as<_Iter>; + { std::as_const(__iter) + __n } -> same_as<_Iter>; + { __n + std::as_const(__iter) } -> same_as<_Iter>; + + { __iter -= __n } -> same_as<_Iter&>; + { __iter - __n } -> same_as<_Iter>; + { std::as_const(__iter) - __n } -> same_as<_Iter>; + + { __iter - __iter } -> same_as<__iter_diff_t<_Iter>>; + { std::as_const(__iter) - __iter } -> same_as<__iter_diff_t<_Iter>>; + { __iter - std::as_const(__iter) } -> same_as<__iter_diff_t<_Iter>>; + { std::as_const(__iter) - std::as_const(__iter) } -> same_as<__iter_diff_t<_Iter>>; + + { __iter[__n] } -> convertible_to<__iter_reference<_Iter>>; + { std::as_const(__iter)[__n] } -> convertible_to<__iter_reference<_Iter>>; + + { __iter < __iter } -> __boolean_testable; + { std::as_const(__iter) < __iter } -> __boolean_testable; + { __iter < std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) < std::as_const(__iter) } -> __boolean_testable; + + { __iter > __iter } -> __boolean_testable; + { std::as_const(__iter) > __iter } -> __boolean_testable; + { __iter > std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) > std::as_const(__iter) } -> __boolean_testable; + + { __iter >= __iter } -> __boolean_testable; + { std::as_const(__iter) >= __iter } -> __boolean_testable; + { __iter >= std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) >= std::as_const(__iter) } -> __boolean_testable; + + { __iter <= __iter } -> __boolean_testable; + { std::as_const(__iter) <= __iter } -> __boolean_testable; + { __iter <= std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) <= std::as_const(__iter) } -> __boolean_testable; + }; + +_LIBCPP_END_NAMESPACE_STD + +# ifndef _LIBCPP_DISABLE_ITERATOR_CHECKS +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) static_assert(::std::__cpp17_input_iterator<iter_t>); +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) \ + static_assert(::std::__cpp17_output_iterator<iter_t, write_t>); +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) static_assert(::std::__cpp17_forward_iterator<iter_t>); +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) \ + static_assert(::std::__cpp17_bidirectional_iterator<iter_t>); +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) \ + static_assert(::std::__cpp17_random_access_iterator<iter_t>); +# else +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) +# endif + +#else // _LIBCPP_STD_VER >= 20 + +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H diff --git a/libcxx/include/__iterator/data.h b/libcxx/include/__iterator/data.h index 88eb752b642e..f10680744fc3 100644 --- a/libcxx/include/__iterator/data.h +++ b/libcxx/include/__iterator/data.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Cont> constexpr _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__iterator/default_sentinel.h b/libcxx/include/__iterator/default_sentinel.h index 669032aa9729..d5fb2b699ad4 100644 --- a/libcxx/include/__iterator/default_sentinel.h +++ b/libcxx/include/__iterator/default_sentinel.h @@ -18,12 +18,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct default_sentinel_t { }; inline constexpr default_sentinel_t default_sentinel{}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/distance.h b/libcxx/include/__iterator/distance.h index 681e20d045b7..ebe5473371f2 100644 --- a/libcxx/include/__iterator/distance.h +++ b/libcxx/include/__iterator/distance.h @@ -53,7 +53,7 @@ distance(_InputIter __first, _InputIter __last) return _VSTD::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category()); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.iter.op.distance] @@ -101,7 +101,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/empty.h b/libcxx/include/__iterator/empty.h index 748ca9ecbd59..2cd4c7abf48c 100644 --- a/libcxx/include/__iterator/empty.h +++ b/libcxx/include/__iterator/empty.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Cont> _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY @@ -37,7 +37,7 @@ template <class _Ep> _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY constexpr bool empty(initializer_list<_Ep> __il) noexcept { return __il.size() == 0; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/erase_if_container.h b/libcxx/include/__iterator/erase_if_container.h index d7c71a947a2b..532ec9c1de0b 100644 --- a/libcxx/include/__iterator/erase_if_container.h +++ b/libcxx/include/__iterator/erase_if_container.h @@ -16,6 +16,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _Container, class _Predicate> @@ -37,4 +40,6 @@ __libcpp_erase_if_container(_Container& __c, _Predicate& __pred) { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_ERASE_IF_CONTAINER_H diff --git a/libcxx/include/__iterator/front_insert_iterator.h b/libcxx/include/__iterator/front_insert_iterator.h index e278359d870d..7c77daebb299 100644 --- a/libcxx/include/__iterator/front_insert_iterator.h +++ b/libcxx/include/__iterator/front_insert_iterator.h @@ -21,6 +21,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -36,7 +39,7 @@ protected: public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; @@ -68,4 +71,6 @@ front_inserter(_Container& __x) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_FRONT_INSERT_ITERATOR_H diff --git a/libcxx/include/__iterator/incrementable_traits.h b/libcxx/include/__iterator/incrementable_traits.h index 3d06dc05359b..604e9580ef7c 100644 --- a/libcxx/include/__iterator/incrementable_traits.h +++ b/libcxx/include/__iterator/incrementable_traits.h @@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [incrementable.traits] template<class> struct incrementable_traits {}; @@ -71,7 +71,7 @@ using iter_difference_t = typename conditional_t<__is_primary_template<iterator_ incrementable_traits<remove_cvref_t<_Ip> >, iterator_traits<remove_cvref_t<_Ip> > >::difference_type; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/indirectly_comparable.h b/libcxx/include/__iterator/indirectly_comparable.h index 868190fc48da..e60ba25ca768 100644 --- a/libcxx/include/__iterator/indirectly_comparable.h +++ b/libcxx/include/__iterator/indirectly_comparable.h @@ -21,13 +21,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _I1, class _I2, class _Rp, class _P1 = identity, class _P2 = identity> concept indirectly_comparable = indirect_binary_predicate<_Rp, projected<_I1, _P1>, projected<_I2, _P2>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/insert_iterator.h b/libcxx/include/__iterator/insert_iterator.h index ecaea61c61e7..4e833733d202 100644 --- a/libcxx/include/__iterator/insert_iterator.h +++ b/libcxx/include/__iterator/insert_iterator.h @@ -22,9 +22,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Container> using __insert_iterator_iter_t = ranges::iterator_t<_Container>; #else @@ -46,7 +49,7 @@ protected: public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; @@ -78,4 +81,6 @@ inserter(_Container& __x, __insert_iterator_iter_t<_Container> __i) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_INSERT_ITERATOR_H diff --git a/libcxx/include/__iterator/istream_iterator.h b/libcxx/include/__iterator/istream_iterator.h index a056961c10a8..989902f212bd 100644 --- a/libcxx/include/__iterator/istream_iterator.h +++ b/libcxx/include/__iterator/istream_iterator.h @@ -47,9 +47,9 @@ private: _Tp __value_; public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istream_iterator() : __in_stream_(nullptr), __value_() {} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr istream_iterator(default_sentinel_t) : istream_iterator() {} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY istream_iterator(istream_type& __s) : __in_stream_(_VSTD::addressof(__s)) { if (!(*__in_stream_ >> __value_)) @@ -73,11 +73,11 @@ public: operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x, const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y); -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const istream_iterator& __i, default_sentinel_t) { return __i.__in_stream_ == nullptr; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 }; template <class _Tp, class _CharT, class _Traits, class _Distance> diff --git a/libcxx/include/__iterator/istreambuf_iterator.h b/libcxx/include/__iterator/istreambuf_iterator.h index bc53a6a1c80e..e39fec6d72dd 100644 --- a/libcxx/include/__iterator/istreambuf_iterator.h +++ b/libcxx/include/__iterator/istreambuf_iterator.h @@ -67,10 +67,10 @@ private: } public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istreambuf_iterator() _NOEXCEPT : __sbuf_(nullptr) {} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY constexpr istreambuf_iterator(default_sentinel_t) noexcept : istreambuf_iterator() {} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(istream_type& __s) _NOEXCEPT : __sbuf_(__s.rdbuf()) {} _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(streambuf_type* __s) _NOEXCEPT @@ -93,11 +93,11 @@ public: _LIBCPP_INLINE_VISIBILITY bool equal(const istreambuf_iterator& __b) const {return __test_for_eof() == __b.__test_for_eof();} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const istreambuf_iterator& __i, default_sentinel_t) { return __i.__test_for_eof(); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 }; template <class _CharT, class _Traits> diff --git a/libcxx/include/__iterator/iter_move.h b/libcxx/include/__iterator/iter_move.h index a7d9413fb84b..d9ff90bf6545 100644 --- a/libcxx/include/__iterator/iter_move.h +++ b/libcxx/include/__iterator/iter_move.h @@ -23,9 +23,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [iterator.cust.move] @@ -97,8 +100,10 @@ template<__dereferenceable _Tp> requires requires(_Tp& __t) { { ranges::iter_move(__t) } -> __can_reference; } using iter_rvalue_reference_t = decltype(ranges::iter_move(std::declval<_Tp&>())); -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_ITER_MOVE_H diff --git a/libcxx/include/__iterator/iter_swap.h b/libcxx/include/__iterator/iter_swap.h index d4c0dca1f63d..2fa92f6ef232 100644 --- a/libcxx/include/__iterator/iter_swap.h +++ b/libcxx/include/__iterator/iter_swap.h @@ -26,9 +26,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [iter.cust.swap] @@ -106,8 +109,10 @@ concept indirectly_swappable = ranges::iter_swap(__i2, __i1); }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_ITER_SWAP_H diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h index c9d8944bfee3..248987e9b560 100644 --- a/libcxx/include/__iterator/iterator_traits.h +++ b/libcxx/include/__iterator/iterator_traits.h @@ -43,7 +43,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp> using __with_reference = _Tp&; @@ -62,7 +62,7 @@ concept __dereferenceable = requires(_Tp& __t) { template<__dereferenceable _Tp> using iter_reference_t = decltype(*std::declval<_Tp&>()); -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template <class _Iter> struct _LIBCPP_TEMPLATE_VIS iterator_traits; @@ -72,7 +72,7 @@ struct _LIBCPP_TEMPLATE_VIS output_iterator_tag {}; struct _LIBCPP_TEMPLATE_VIS forward_iterator_tag : public input_iterator_tag {}; struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator_tag {}; struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct _LIBCPP_TEMPLATE_VIS contiguous_iterator_tag : public random_access_iterator_tag {}; #endif @@ -157,7 +157,7 @@ public: static const bool value = decltype(__test<_Tp>(nullptr))::value; }; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // The `cpp17-*-iterator` exposition-only concepts have very similar names to the `Cpp17*Iterator` named requirements // from `[iterator.cpp17]`. To avoid confusion between the two, the exposition-only concepts have been banished to @@ -190,7 +190,7 @@ template<class _Ip> concept __cpp17_forward_iterator = __cpp17_input_iterator<_Ip> && constructible_from<_Ip> && - is_lvalue_reference_v<iter_reference_t<_Ip>> && + is_reference_v<iter_reference_t<_Ip>> && same_as<remove_cvref_t<iter_reference_t<_Ip>>, typename indirectly_readable_traits<_Ip>::value_type> && requires(_Ip __i) { @@ -381,7 +381,7 @@ struct iterator_traits : __iterator_traits<_Ip> { using __primary_template = iterator_traits; }; -#else // _LIBCPP_STD_VER > 17 +#else // _LIBCPP_STD_VER >= 20 template <class _Iter, bool> struct __iterator_traits {}; @@ -418,10 +418,10 @@ struct _LIBCPP_TEMPLATE_VIS iterator_traits using __primary_template = iterator_traits; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template<class _Tp> -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires is_object_v<_Tp> #endif struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> @@ -431,7 +431,7 @@ struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> typedef _Tp* pointer; typedef _Tp& reference; typedef random_access_iterator_tag iterator_category; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef contiguous_iterator_tag iterator_concept; #endif }; @@ -453,60 +453,60 @@ template <class _Tp, class _Up> struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {}; template <class _Tp> -struct __is_cpp17_input_iterator : public __has_iterator_category_convertible_to<_Tp, input_iterator_tag> {}; +using __has_input_iterator_category = __has_iterator_category_convertible_to<_Tp, input_iterator_tag>; template <class _Tp> -struct __is_cpp17_forward_iterator : public __has_iterator_category_convertible_to<_Tp, forward_iterator_tag> {}; +using __has_forward_iterator_category = __has_iterator_category_convertible_to<_Tp, forward_iterator_tag>; template <class _Tp> -struct __is_cpp17_bidirectional_iterator : public __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag> {}; +using __has_bidirectional_iterator_category = __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>; template <class _Tp> -struct __is_cpp17_random_access_iterator : public __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag> {}; +using __has_random_access_iterator_category = __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>; -// __is_cpp17_contiguous_iterator determines if an iterator is known by +// __libcpp_is_contiguous_iterator determines if an iterator is known by // libc++ to be contiguous, either because it advertises itself as such // (in C++20) or because it is a pointer type or a known trivial wrapper // around a (possibly fancy) pointer type, such as __wrap_iter<T*>. // Such iterators receive special "contiguous" optimizations in // std::copy and std::sort. // -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp> -struct __is_cpp17_contiguous_iterator : _Or< +struct __libcpp_is_contiguous_iterator : _Or< __has_iterator_category_convertible_to<_Tp, contiguous_iterator_tag>, __has_iterator_concept_convertible_to<_Tp, contiguous_iterator_tag> > {}; #else template <class _Tp> -struct __is_cpp17_contiguous_iterator : false_type {}; +struct __libcpp_is_contiguous_iterator : false_type {}; #endif // Any native pointer which is an iterator is also a contiguous iterator. template <class _Up> -struct __is_cpp17_contiguous_iterator<_Up*> : true_type {}; +struct __libcpp_is_contiguous_iterator<_Up*> : true_type {}; template <class _Iter> class __wrap_iter; template <class _Tp> -struct __is_exactly_cpp17_input_iterator - : public integral_constant<bool, +using __has_exactly_input_iterator_category + = integral_constant<bool, __has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value && - !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {}; + !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value>; template <class _Tp> -struct __is_exactly_cpp17_forward_iterator - : public integral_constant<bool, +using __has_exactly_forward_iterator_category + = integral_constant<bool, __has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value && - !__has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value> {}; + !__has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value>; template <class _Tp> -struct __is_exactly_cpp17_bidirectional_iterator - : public integral_constant<bool, +using __has_exactly_bidirectional_iterator_category + = integral_constant<bool, __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value && - !__has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>::value> {}; + !__has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>::value>; template<class _InputIterator> using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; @@ -531,8 +531,23 @@ using __iterator_pointer_type = typename iterator_traits<_Iter>::pointer; template <class _Iter> using __iter_diff_t = typename iterator_traits<_Iter>::difference_type; -template<class _InputIterator> -using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; +template <class _Iter> +using __iter_reference = typename iterator_traits<_Iter>::reference; + +#if _LIBCPP_STD_VER >= 20 + +// [readable.traits] + +// Let `RI` be `remove_cvref_t<I>`. The type `iter_value_t<I>` denotes +// `indirectly_readable_traits<RI>::value_type` if `iterator_traits<RI>` names a specialization +// generated from the primary template, and `iterator_traits<RI>::value_type` otherwise. +// This has to be in this file and not readable_traits.h to break the include cycle between the two. +template <class _Ip> +using iter_value_t = typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value, + indirectly_readable_traits<remove_cvref_t<_Ip> >, + iterator_traits<remove_cvref_t<_Ip> > >::value_type; + +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/mergeable.h b/libcxx/include/__iterator/mergeable.h index b9f2d081dc7e..494fda956e27 100644 --- a/libcxx/include/__iterator/mergeable.h +++ b/libcxx/include/__iterator/mergeable.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Input1, class _Input2, class _Output, class _Comp = ranges::less, class _Proj1 = identity, class _Proj2 = identity> @@ -34,7 +34,7 @@ concept mergeable = indirectly_copyable<_Input2, _Output> && indirect_strict_weak_order<_Comp, projected<_Input1, _Proj1>, projected<_Input2, _Proj2>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/move_iterator.h b/libcxx/include/__iterator/move_iterator.h index fa806dbaf70e..2f79d9a3d263 100644 --- a/libcxx/include/__iterator/move_iterator.h +++ b/libcxx/include/__iterator/move_iterator.h @@ -39,9 +39,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class _Iter, class = void> struct __move_iter_category_base {}; @@ -59,18 +62,33 @@ template<class _Iter, class _Sent> concept __move_iter_comparable = requires { { std::declval<const _Iter&>() == std::declval<_Sent>() } -> convertible_to<bool>; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template <class _Iter> class _LIBCPP_TEMPLATE_VIS move_iterator -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 : public __move_iter_category_base<_Iter> #endif { + #if _LIBCPP_STD_VER >= 20 +private: + _LIBCPP_HIDE_FROM_ABI + static constexpr auto __get_iter_concept() { + if constexpr (random_access_iterator<_Iter>) { + return random_access_iterator_tag{}; + } else if constexpr (bidirectional_iterator<_Iter>) { + return bidirectional_iterator_tag{}; + } else if constexpr (forward_iterator<_Iter>) { + return forward_iterator_tag{}; + } else { + return input_iterator_tag{}; + } + } +#endif // _LIBCPP_STD_VER >= 20 public: -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using iterator_type = _Iter; - using iterator_concept = input_iterator_tag; + using iterator_concept = decltype(__get_iter_concept()); // iterator_category is inherited and not always present using value_type = iter_value_t<_Iter>; using difference_type = iter_difference_t<_Iter>; @@ -79,7 +97,7 @@ public: #else typedef _Iter iterator_type; typedef _If< - __is_cpp17_random_access_iterator<_Iter>::value, + __has_random_access_iterator_category<_Iter>::value, random_access_iterator_tag, typename iterator_traits<_Iter>::iterator_category > iterator_category; @@ -93,7 +111,7 @@ public: __libcpp_remove_reference_t<__reference>&&, __reference >::type reference; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {} @@ -104,7 +122,7 @@ public: _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pointer operator->() const { return __current_; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr move_iterator() requires is_constructible_v<_Iter> : __current_() {} @@ -171,7 +189,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator++(int) { move_iterator __tmp(*this); ++__current_; return __tmp; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator--() { --__current_; return *this; } @@ -186,7 +204,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator-=(difference_type __n) { __current_ -= __n; return *this; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<sentinel_for<_Iter> _Sent> friend _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) @@ -223,7 +241,7 @@ public: { return ranges::iter_swap(__x.__current_, __y.__current_); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 private: template<class _It2> friend class move_iterator; @@ -276,7 +294,7 @@ bool operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& _ return __x.base() >= __y.base(); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Iter1, three_way_comparable_with<_Iter1> _Iter2> inline _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) @@ -284,7 +302,7 @@ auto operator<=>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& { return __x.base() <=> __y.base(); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #ifndef _LIBCPP_CXX03_LANG template <class _Iter1, class _Iter2> @@ -304,7 +322,7 @@ operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) } #endif // !_LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Iter> inline _LIBCPP_HIDE_FROM_ABI constexpr move_iterator<_Iter> operator+(iter_difference_t<_Iter> __n, const move_iterator<_Iter>& __x) @@ -320,7 +338,7 @@ operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterato { return move_iterator<_Iter>(__x.base() + __n); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template <class _Iter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 @@ -332,4 +350,6 @@ make_move_iterator(_Iter __i) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_MOVE_ITERATOR_H diff --git a/libcxx/include/__iterator/move_sentinel.h b/libcxx/include/__iterator/move_sentinel.h index 0d7336a1dc2a..34b3c25417c4 100644 --- a/libcxx/include/__iterator/move_sentinel.h +++ b/libcxx/include/__iterator/move_sentinel.h @@ -19,9 +19,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <semiregular _Sent> class _LIBCPP_TEMPLATE_VIS move_sentinel @@ -44,7 +47,7 @@ public: move_sentinel& operator=(const move_sentinel<_S2>& __s) { __last_ = __s.base(); return *this; } - constexpr _Sent base() const { return __last_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Sent base() const { return __last_; } private: _Sent __last_ = _Sent(); @@ -52,8 +55,10 @@ private: _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_sentinel); -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_MOVE_SENTINEL_H diff --git a/libcxx/include/__iterator/next.h b/libcxx/include/__iterator/next.h index 49970ae24808..5aba095dc485 100644 --- a/libcxx/include/__iterator/next.h +++ b/libcxx/include/__iterator/next.h @@ -26,16 +26,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _InputIter> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 - typename enable_if<__is_cpp17_input_iterator<_InputIter>::value, _InputIter>::type + typename enable_if<__has_input_iterator_category<_InputIter>::value, _InputIter>::type next(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) { - _LIBCPP_ASSERT(__n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, - "Attempt to next(it, n) with negative n on a non-bidirectional iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n >= 0 || __has_bidirectional_iterator_category<_InputIter>::value, + "Attempt to next(it, n) with negative n on a non-bidirectional iterator"); _VSTD::advance(__x, __n); return __x; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.iter.op.next] @@ -77,7 +77,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/ostream_iterator.h b/libcxx/include/__iterator/ostream_iterator.h index d16f5a26ebaa..025712bb1ca9 100644 --- a/libcxx/include/__iterator/ostream_iterator.h +++ b/libcxx/include/__iterator/ostream_iterator.h @@ -34,7 +34,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; diff --git a/libcxx/include/__iterator/ostreambuf_iterator.h b/libcxx/include/__iterator/ostreambuf_iterator.h index b75f7b6e8466..898ef90e7e85 100644 --- a/libcxx/include/__iterator/ostreambuf_iterator.h +++ b/libcxx/include/__iterator/ostreambuf_iterator.h @@ -33,7 +33,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; diff --git a/libcxx/include/__iterator/permutable.h b/libcxx/include/__iterator/permutable.h index 28d193eaae2c..adf88f506529 100644 --- a/libcxx/include/__iterator/permutable.h +++ b/libcxx/include/__iterator/permutable.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Iterator> concept permutable = @@ -28,7 +28,7 @@ concept permutable = indirectly_movable_storable<_Iterator, _Iterator> && indirectly_swappable<_Iterator, _Iterator>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/prev.h b/libcxx/include/__iterator/prev.h index af1e1bab115b..d31cd8e49bbf 100644 --- a/libcxx/include/__iterator/prev.h +++ b/libcxx/include/__iterator/prev.h @@ -26,15 +26,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _InputIter> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 - typename enable_if<__is_cpp17_input_iterator<_InputIter>::value, _InputIter>::type + typename enable_if<__has_input_iterator_category<_InputIter>::value, _InputIter>::type prev(_InputIter __x, typename iterator_traits<_InputIter>::difference_type __n = 1) { - _LIBCPP_ASSERT(__n <= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, - "Attempt to prev(it, n) with a positive n on a non-bidirectional iterator"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n <= 0 || __has_bidirectional_iterator_category<_InputIter>::value, + "Attempt to prev(it, n) with a positive n on a non-bidirectional iterator"); _VSTD::advance(__x, -__n); return __x; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.iter.op.prev] @@ -70,7 +70,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/projected.h b/libcxx/include/__iterator/projected.h index 19c076b2e560..e74e56d6fb71 100644 --- a/libcxx/include/__iterator/projected.h +++ b/libcxx/include/__iterator/projected.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<indirectly_readable _It, indirectly_regular_unary_invocable<_It> _Proj> struct projected { @@ -34,7 +34,7 @@ struct incrementable_traits<projected<_It, _Proj>> { using difference_type = iter_difference_t<_It>; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/ranges_iterator_traits.h b/libcxx/include/__iterator/ranges_iterator_traits.h new file mode 100644 index 000000000000..a30864199df7 --- /dev/null +++ b/libcxx/include/__iterator/ranges_iterator_traits.h @@ -0,0 +1,42 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_RANGES_ITERATOR_TRAITS_H +#define _LIBCPP___ITERATOR_RANGES_ITERATOR_TRAITS_H + +#include <__config> +#include <__fwd/pair.h> +#include <__ranges/concepts.h> +#include <__type_traits/add_const.h> +#include <__type_traits/remove_const.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template <ranges::input_range _Range> +using __range_key_type = __remove_const_t<typename ranges::range_value_t<_Range>::first_type>; + +template <ranges::input_range _Range> +using __range_mapped_type = typename ranges::range_value_t<_Range>::second_type; + +template <ranges::input_range _Range> +using __range_to_alloc_type = + pair<add_const_t<typename ranges::range_value_t<_Range>::first_type>, + typename ranges::range_value_t<_Range>::second_type>; + +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ITERATOR_RANGES_ITERATOR_TRAITS_H diff --git a/libcxx/include/__iterator/readable_traits.h b/libcxx/include/__iterator/readable_traits.h index 8f17757c5a3d..9e101fc28a6f 100644 --- a/libcxx/include/__iterator/readable_traits.h +++ b/libcxx/include/__iterator/readable_traits.h @@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [readable.traits] template<class> struct __cond_value_type {}; @@ -74,18 +74,7 @@ template<__has_member_value_type _Tp> struct indirectly_readable_traits<_Tp> : __cond_value_type<typename _Tp::value_type> {}; -template <class> -struct iterator_traits; - -// Let `RI` be `remove_cvref_t<I>`. The type `iter_value_t<I>` denotes -// `indirectly_readable_traits<RI>::value_type` if `iterator_traits<RI>` names a specialization -// generated from the primary template, and `iterator_traits<RI>::value_type` otherwise. -template <class _Ip> -using iter_value_t = typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value, - indirectly_readable_traits<remove_cvref_t<_Ip> >, - iterator_traits<remove_cvref_t<_Ip> > >::value_type; - -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/reverse_access.h b/libcxx/include/__iterator/reverse_access.h index 79b599c47c12..b8c5a071cc63 100644 --- a/libcxx/include/__iterator/reverse_access.h +++ b/libcxx/include/__iterator/reverse_access.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp, size_t _Np> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 @@ -93,7 +93,7 @@ auto crend(const _Cp& __c) -> decltype(_VSTD::rend(__c)) return _VSTD::rend(__c); } -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/reverse_iterator.h b/libcxx/include/__iterator/reverse_iterator.h index f272e03c17a6..beb10f7f4f23 100644 --- a/libcxx/include/__iterator/reverse_iterator.h +++ b/libcxx/include/__iterator/reverse_iterator.h @@ -63,21 +63,21 @@ private: _Iter __t_; // no longer used as of LWG #2360, not removed due to ABI break #endif -#if _LIBCPP_STD_VER > 17 - static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value || bidirectional_iterator<_Iter>, +#if _LIBCPP_STD_VER >= 20 + static_assert(__has_bidirectional_iterator_category<_Iter>::value || bidirectional_iterator<_Iter>, "reverse_iterator<It> requires It to be a bidirectional iterator."); -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 protected: _Iter current; public: using iterator_type = _Iter; - using iterator_category = _If<__is_cpp17_random_access_iterator<_Iter>::value, + using iterator_category = _If<__has_random_access_iterator_category<_Iter>::value, random_access_iterator_tag, typename iterator_traits<_Iter>::iterator_category>; using pointer = typename iterator_traits<_Iter>::pointer; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using iterator_concept = _If<random_access_iterator<_Iter>, random_access_iterator_tag, bidirectional_iterator_tag>; using value_type = iter_value_t<_Iter>; using difference_type = iter_difference_t<_Iter>; @@ -144,7 +144,7 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator*() const {_Iter __tmp = current; return *--__tmp;} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY constexpr pointer operator->() const requires is_pointer_v<_Iter> || requires(const _Iter __i) { __i.operator->(); } @@ -160,7 +160,7 @@ public: pointer operator->() const { return std::addressof(operator*()); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reverse_iterator& operator++() {--current; return *this;} @@ -181,7 +181,7 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator[](difference_type __n) const {return *(*this + __n);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI friend constexpr iter_rvalue_reference_t<_Iter> iter_move(const reverse_iterator& __i) noexcept(is_nothrow_copy_constructible_v<_Iter> && @@ -200,18 +200,18 @@ public: auto __ytmp = __y.base(); ranges::iter_swap(--__xtmp, --__ytmp); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 }; template <class _Iter1, class _Iter2> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator==(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() == __y.base() } -> convertible_to<bool>; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() == __y.base(); } @@ -220,11 +220,11 @@ template <class _Iter1, class _Iter2> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator<(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() > __y.base() } -> convertible_to<bool>; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() > __y.base(); } @@ -233,11 +233,11 @@ template <class _Iter1, class _Iter2> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator!=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() != __y.base() } -> convertible_to<bool>; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() != __y.base(); } @@ -246,11 +246,11 @@ template <class _Iter1, class _Iter2> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() < __y.base() } -> convertible_to<bool>; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() < __y.base(); } @@ -259,11 +259,11 @@ template <class _Iter1, class _Iter2> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator>=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() <= __y.base() } -> convertible_to<bool>; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() <= __y.base(); } @@ -272,16 +272,16 @@ template <class _Iter1, class _Iter2> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 bool operator<=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 requires requires { { __x.base() >= __y.base() } -> convertible_to<bool>; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 { return __x.base() >= __y.base(); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Iter1, three_way_comparable_with<_Iter1> _Iter2> _LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Iter1, _Iter2> @@ -289,7 +289,7 @@ operator<=>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& { return __y.base() <=> __x.base(); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #ifndef _LIBCPP_CXX03_LANG template <class _Iter1, class _Iter2> @@ -318,13 +318,13 @@ operator+(typename reverse_iterator<_Iter>::difference_type __n, const reverse_i return reverse_iterator<_Iter>(__x.base() - __n); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Iter1, class _Iter2> requires (!sized_sentinel_for<_Iter1, _Iter2>) inline constexpr bool disable_sized_sentinel_for<reverse_iterator<_Iter1>, reverse_iterator<_Iter2>> = true; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Iter> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reverse_iterator<_Iter> make_reverse_iterator(_Iter __i) @@ -365,11 +365,11 @@ class __unconstrained_reverse_iterator { _Iter __iter_; public: - static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value || bidirectional_iterator<_Iter>); + static_assert(__has_bidirectional_iterator_category<_Iter>::value || bidirectional_iterator<_Iter>); using iterator_type = _Iter; using iterator_category = - _If<__is_cpp17_random_access_iterator<_Iter>::value, random_access_iterator_tag, __iterator_category_type<_Iter>>; + _If<__has_random_access_iterator_category<_Iter>::value, random_access_iterator_tag, __iterator_category_type<_Iter>>; using pointer = __iterator_pointer_type<_Iter>; using value_type = iter_value_t<_Iter>; using difference_type = iter_difference_t<_Iter>; @@ -498,7 +498,7 @@ struct __unwrap_reverse_iter_impl { } }; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <ranges::bidirectional_range _Range> _LIBCPP_HIDE_FROM_ABI constexpr ranges:: subrange<reverse_iterator<ranges::iterator_t<_Range>>, reverse_iterator<ranges::iterator_t<_Range>>> @@ -512,7 +512,7 @@ template <class _Iter, bool __b> struct __unwrap_iter_impl<reverse_iterator<reverse_iterator<_Iter> >, __b> : __unwrap_reverse_iter_impl<reverse_iterator, reverse_iterator, _Iter> {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Iter, bool __b> struct __unwrap_iter_impl<reverse_iterator<__unconstrained_reverse_iterator<_Iter>>, __b> @@ -526,7 +526,7 @@ template <class _Iter, bool __b> struct __unwrap_iter_impl<__unconstrained_reverse_iterator<__unconstrained_reverse_iterator<_Iter>>, __b> : __unwrap_reverse_iter_impl<__unconstrained_reverse_iterator, __unconstrained_reverse_iterator, _Iter> {}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/size.h b/libcxx/include/__iterator/size.h index 1452bd1d55cd..625eeb165bf5 100644 --- a/libcxx/include/__iterator/size.h +++ b/libcxx/include/__iterator/size.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Cont> _LIBCPP_INLINE_VISIBILITY @@ -34,7 +34,7 @@ template <class _Tp, size_t _Sz> _LIBCPP_INLINE_VISIBILITY constexpr size_t size(const _Tp (&)[_Sz]) noexcept { return _Sz; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Cont> _LIBCPP_INLINE_VISIBILITY constexpr auto ssize(const _Cont& __c) @@ -52,7 +52,7 @@ constexpr ptrdiff_t ssize(const _Tp (&)[_Sz]) noexcept { return _Sz; } _LIBCPP_DIAGNOSTIC_POP #endif -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/sortable.h b/libcxx/include/__iterator/sortable.h index bcf934f87be0..d4d77d6cf334 100644 --- a/libcxx/include/__iterator/sortable.h +++ b/libcxx/include/__iterator/sortable.h @@ -23,14 +23,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Iter, class _Comp = ranges::less, class _Proj = identity> concept sortable = permutable<_Iter> && indirect_strict_weak_order<_Comp, projected<_Iter, _Proj>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/unreachable_sentinel.h b/libcxx/include/__iterator/unreachable_sentinel.h index d77cc99f02f7..91fd0a57ab3f 100644 --- a/libcxx/include/__iterator/unreachable_sentinel.h +++ b/libcxx/include/__iterator/unreachable_sentinel.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 struct unreachable_sentinel_t { template<weakly_incrementable _Iter> @@ -31,7 +31,7 @@ struct unreachable_sentinel_t { inline constexpr unreachable_sentinel_t unreachable_sentinel{}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/wrap_iter.h b/libcxx/include/__iterator/wrap_iter.h index 16defc1d8b02..774276baa81c 100644 --- a/libcxx/include/__iterator/wrap_iter.h +++ b/libcxx/include/__iterator/wrap_iter.h @@ -11,12 +11,12 @@ #define _LIBCPP___ITERATOR_WRAP_ITER_H #include <__config> -#include <__debug> #include <__iterator/iterator_traits.h> #include <__memory/addressof.h> #include <__memory/pointer_traits.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_convertible.h> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -34,7 +34,7 @@ public: typedef typename iterator_traits<iterator_type>::pointer pointer; typedef typename iterator_traits<iterator_type>::reference reference; typedef typename iterator_traits<iterator_type>::iterator_category iterator_category; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef contiguous_iterator_tag iterator_concept; #endif @@ -44,60 +44,23 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter() _NOEXCEPT : __i_() { - _VSTD::__debug_db_insert_i(this); } template <class _Up> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter(const __wrap_iter<_Up>& __u, typename enable_if<is_convertible<_Up, iterator_type>::value>::type* = nullptr) _NOEXCEPT : __i_(__u.base()) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__iterator_copy(this, _VSTD::addressof(__u)); -#endif - } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - __wrap_iter(const __wrap_iter& __x) - : __i_(__x.base()) - { - if (!__libcpp_is_constant_evaluated()) - __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); - } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - __wrap_iter& operator=(const __wrap_iter& __x) - { - if (this != _VSTD::addressof(__x)) - { - if (!__libcpp_is_constant_evaluated()) - __get_db()->__iterator_copy(this, _VSTD::addressof(__x)); - __i_ = __x.__i_; - } - return *this; - } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - ~__wrap_iter() - { - if (!__libcpp_is_constant_evaluated()) - __get_db()->__erase_i(this); } -#endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable iterator"); return *__i_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable iterator"); return _VSTD::__to_address(__i_); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter& operator++() _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable iterator"); ++__i_; return *this; } @@ -106,8 +69,6 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter& operator--() _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__decrementable(this), - "Attempted to decrement a non-decrementable iterator"); --__i_; return *this; } @@ -117,8 +78,6 @@ public: {__wrap_iter __w(*this); __w += __n; return __w;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter& operator+=(difference_type __n) _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__addable(this, __n), - "Attempted to add/subtract an iterator outside its valid range"); __i_ += __n; return *this; } @@ -128,8 +87,6 @@ public: {*this += -__n; return *this;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__subscriptable(this, __n), - "Attempted to subscript an iterator outside its valid range"); return __i_[__n]; } @@ -137,13 +94,8 @@ public: private: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - explicit __wrap_iter(const void* __p, iterator_type __x) _NOEXCEPT : __i_(__x) + explicit __wrap_iter(iterator_type __x) _NOEXCEPT : __i_(__x) { - (void)__p; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) - __get_db()->__insert_ic(this, __p); -#endif } template <class _Up> friend class __wrap_iter; @@ -170,8 +122,6 @@ template <class _Iter1> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__less_than_comparable(_VSTD::addressof(__x), _VSTD::addressof(__y)), - "Attempted to compare incomparable iterators"); return __x.base() < __y.base(); } @@ -179,8 +129,6 @@ template <class _Iter1, class _Iter2> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y), - "Attempted to compare incomparable iterators"); return __x.base() < __y.base(); } @@ -250,8 +198,6 @@ typename __wrap_iter<_Iter1>::difference_type operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT #endif // C++03 { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__less_than_comparable(_VSTD::addressof(__x), _VSTD::addressof(__y)), - "Attempted to subtract incompatible iterators"); return __x.base() - __y.base(); } @@ -265,7 +211,7 @@ __wrap_iter<_Iter1> operator+(typename __wrap_iter<_Iter1>::difference_type __n, #if _LIBCPP_STD_VER <= 17 template <class _It> -struct __is_cpp17_contiguous_iterator<__wrap_iter<_It> > : true_type {}; +struct __libcpp_is_contiguous_iterator<__wrap_iter<_It> > : true_type {}; #endif template <class _It> diff --git a/libcxx/include/__locale b/libcxx/include/__locale index e0ffa0ca00ff..5c060ab04c76 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -12,9 +12,12 @@ #include <__availability> #include <__config> +#include <__memory/shared_ptr.h> // __shared_count +#include <__type_traits/make_unsigned.h> #include <cctype> +#include <clocale> #include <cstdint> -#include <locale.h> +#include <cstdlib> #include <mutex> #include <string> @@ -22,15 +25,18 @@ #include <cstddef> #include <cstring> +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# include <cwchar> +#else +# include <__std_mbstate_t.h> +#endif + #if defined(_LIBCPP_MSVCRT_LIKE) # include <__support/win32/locale_win32.h> #elif defined(_AIX) || defined(__MVS__) # include <__support/ibm/xlocale.h> #elif defined(__ANDROID__) # include <__support/android/locale_bionic.h> -#elif defined(__sun__) -# include <__support/solaris/xlocale.h> -# include <xlocale.h> #elif defined(_NEWLIB_VERSION) # include <__support/newlib/xlocale.h> #elif defined(__OpenBSD__) @@ -52,64 +58,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS) -struct __libcpp_locale_guard { - _LIBCPP_INLINE_VISIBILITY - __libcpp_locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {} - - _LIBCPP_INLINE_VISIBILITY - ~__libcpp_locale_guard() { - if (__old_loc_) - uselocale(__old_loc_); - } - - locale_t __old_loc_; -private: - __libcpp_locale_guard(__libcpp_locale_guard const&); - __libcpp_locale_guard& operator=(__libcpp_locale_guard const&); -}; -#elif defined(_LIBCPP_MSVCRT_LIKE) -struct __libcpp_locale_guard { - __libcpp_locale_guard(locale_t __l) : - __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) { - // Setting the locale can be expensive even when the locale given is - // already the current locale, so do an explicit check to see if the - // current locale is already the one we want. - const char* __lc = __setlocale(nullptr); - // If every category is the same, the locale string will simply be the - // locale name, otherwise it will be a semicolon-separated string listing - // each category. In the second case, we know at least one category won't - // be what we want, so we only have to check the first case. - if (_VSTD::strcmp(__l.__get_locale(), __lc) != 0) { - __locale_all = _strdup(__lc); - if (__locale_all == nullptr) - __throw_bad_alloc(); - __setlocale(__l.__get_locale()); - } - } - ~__libcpp_locale_guard() { - // The CRT documentation doesn't explicitly say, but setlocale() does the - // right thing when given a semicolon-separated list of locale settings - // for the different categories in the same format as returned by - // setlocale(LC_ALL, nullptr). - if (__locale_all != nullptr) { - __setlocale(__locale_all); - free(__locale_all); - } - _configthreadlocale(__status); - } - static const char* __setlocale(const char* __locale) { - const char* __new_locale = setlocale(LC_ALL, __locale); - if (__new_locale == nullptr) - __throw_bad_alloc(); - return __new_locale; - } - int __status; - char* __locale_all = nullptr; -}; -#endif - -class _LIBCPP_TYPE_VIS locale; +class _LIBCPP_EXPORTED_FROM_ABI locale; template <class _Facet> _LIBCPP_INLINE_VISIBILITY @@ -121,12 +70,12 @@ _LIBCPP_INLINE_VISIBILITY const _Facet& use_facet(const locale&); -class _LIBCPP_TYPE_VIS locale +class _LIBCPP_EXPORTED_FROM_ABI locale { public: // types: - class _LIBCPP_TYPE_VIS facet; - class _LIBCPP_TYPE_VIS id; + class _LIBCPP_EXPORTED_FROM_ABI facet; + class _LIBCPP_EXPORTED_FROM_ABI id; typedef int category; _LIBCPP_AVAILABILITY_LOCALE_CATEGORY @@ -162,7 +111,9 @@ public: // locale operations: string name() const; bool operator==(const locale&) const; - bool operator!=(const locale& __y) const {return !(*this == __y);} +#if _LIBCPP_STD_VER <= 17 + _LIBCPP_HIDE_FROM_ABI bool operator!=(const locale& __y) const {return !(*this == __y);} +#endif template <class _CharT, class _Traits, class _Allocator> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool operator()(const basic_string<_CharT, _Traits, _Allocator>&, @@ -185,7 +136,7 @@ private: template <class _Facet> friend const _Facet& use_facet(const locale&); }; -class _LIBCPP_TYPE_VIS locale::facet +class _LIBCPP_EXPORTED_FROM_ABI locale::facet : public __shared_count { protected: @@ -201,7 +152,7 @@ private: void __on_zero_shared() _NOEXCEPT override; }; -class _LIBCPP_TYPE_VIS locale::id +class _LIBCPP_EXPORTED_FROM_ABI locale::id { once_flag __flag_; int32_t __id_; @@ -349,7 +300,7 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate<wchar_t>; template <class _CharT> class _LIBCPP_TEMPLATE_VIS collate_byname; template <> -class _LIBCPP_TYPE_VIS collate_byname<char> +class _LIBCPP_EXPORTED_FROM_ABI collate_byname<char> : public collate<char> { locale_t __l_; @@ -369,7 +320,7 @@ protected: #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS collate_byname<wchar_t> +class _LIBCPP_EXPORTED_FROM_ABI collate_byname<wchar_t> : public collate<wchar_t> { locale_t __l_; @@ -401,7 +352,7 @@ locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x, // template <class charT> class ctype -class _LIBCPP_TYPE_VIS ctype_base +class _LIBCPP_EXPORTED_FROM_ABI ctype_base { public: #if defined(_LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE) @@ -482,7 +433,7 @@ public: static const mask blank = _CTYPE_B; static const mask __regex_word = 0x80; # endif -#elif defined(__sun__) || defined(_AIX) +#elif defined(_AIX) typedef unsigned int mask; static const mask space = _ISSPACE; static const mask print = _ISPRINT; @@ -494,11 +445,7 @@ public: static const mask punct = _ISPUNCT; static const mask xdigit = _ISXDIGIT; static const mask blank = _ISBLANK; -# if defined(_AIX) static const mask __regex_word = 0x8000; -# else - static const mask __regex_word = 0x80; -# endif #elif defined(_NEWLIB_VERSION) // Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h. typedef char mask; @@ -561,7 +508,7 @@ template <class _CharT> class _LIBCPP_TEMPLATE_VIS ctype; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS ctype<wchar_t> +class _LIBCPP_EXPORTED_FROM_ABI ctype<wchar_t> : public locale::facet, public ctype_base { @@ -664,7 +611,7 @@ protected: #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS ctype<char> +class _LIBCPP_EXPORTED_FROM_ABI ctype<char> : public locale::facet, public ctype_base { const mask* __tab_; @@ -793,7 +740,7 @@ protected: template <class _CharT> class _LIBCPP_TEMPLATE_VIS ctype_byname; template <> -class _LIBCPP_TYPE_VIS ctype_byname<char> +class _LIBCPP_EXPORTED_FROM_ABI ctype_byname<char> : public ctype<char> { locale_t __l_; @@ -812,7 +759,7 @@ protected: #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS ctype_byname<wchar_t> +class _LIBCPP_EXPORTED_FROM_ABI ctype_byname<wchar_t> : public ctype<wchar_t> { locale_t __l_; @@ -927,6 +874,11 @@ isgraph(_CharT __c, const locale& __loc) } template <class _CharT> +_LIBCPP_HIDE_FROM_ABI bool isblank(_CharT __c, const locale& __loc) { + return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::blank, __c); +} + +template <class _CharT> inline _LIBCPP_INLINE_VISIBILITY _CharT toupper(_CharT __c, const locale& __loc) @@ -944,7 +896,7 @@ tolower(_CharT __c, const locale& __loc) // codecvt_base -class _LIBCPP_TYPE_VIS codecvt_base +class _LIBCPP_EXPORTED_FROM_ABI codecvt_base { public: _LIBCPP_INLINE_VISIBILITY codecvt_base() {} @@ -958,7 +910,7 @@ template <class _InternT, class _ExternT, class _StateT> class _LIBCPP_TEMPLATE_ // template <> class codecvt<char, char, mbstate_t> template <> -class _LIBCPP_TYPE_VIS codecvt<char, char, mbstate_t> +class _LIBCPP_EXPORTED_FROM_ABI codecvt<char, char, mbstate_t> : public locale::facet, public codecvt_base { @@ -1045,7 +997,7 @@ protected: #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS codecvt<wchar_t, char, mbstate_t> +class _LIBCPP_EXPORTED_FROM_ABI codecvt<wchar_t, char, mbstate_t> : public locale::facet, public codecvt_base { @@ -1129,7 +1081,7 @@ protected: // template <> class codecvt<char16_t, char, mbstate_t> // deprecated in C++20 template <> -class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_TYPE_VIS codecvt<char16_t, char, mbstate_t> +class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXPORTED_FROM_ABI codecvt<char16_t, char, mbstate_t> : public locale::facet, public codecvt_base { @@ -1217,7 +1169,7 @@ protected: // template <> class codecvt<char16_t, char8_t, mbstate_t> // C++20 template <> -class _LIBCPP_TYPE_VIS codecvt<char16_t, char8_t, mbstate_t> +class _LIBCPP_EXPORTED_FROM_ABI codecvt<char16_t, char8_t, mbstate_t> : public locale::facet, public codecvt_base { @@ -1305,7 +1257,7 @@ protected: // template <> class codecvt<char32_t, char, mbstate_t> // deprecated in C++20 template <> -class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_TYPE_VIS codecvt<char32_t, char, mbstate_t> +class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXPORTED_FROM_ABI codecvt<char32_t, char, mbstate_t> : public locale::facet, public codecvt_base { @@ -1393,7 +1345,7 @@ protected: // template <> class codecvt<char32_t, char8_t, mbstate_t> // C++20 template <> -class _LIBCPP_TYPE_VIS codecvt<char32_t, char8_t, mbstate_t> +class _LIBCPP_EXPORTED_FROM_ABI codecvt<char32_t, char8_t, mbstate_t> : public locale::facet, public codecvt_base { @@ -1537,7 +1489,7 @@ struct __narrow_to_utf8<8> _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -struct _LIBCPP_TYPE_VIS __narrow_to_utf8<16> +struct _LIBCPP_EXPORTED_FROM_ABI __narrow_to_utf8<16> : public codecvt<char16_t, char, mbstate_t> { _LIBCPP_INLINE_VISIBILITY @@ -1573,7 +1525,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -struct _LIBCPP_TYPE_VIS __narrow_to_utf8<32> +struct _LIBCPP_EXPORTED_FROM_ABI __narrow_to_utf8<32> : public codecvt<char32_t, char, mbstate_t> { _LIBCPP_INLINE_VISIBILITY @@ -1631,7 +1583,7 @@ struct __widen_from_utf8<8> _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -struct _LIBCPP_TYPE_VIS __widen_from_utf8<16> +struct _LIBCPP_EXPORTED_FROM_ABI __widen_from_utf8<16> : public codecvt<char16_t, char, mbstate_t> { _LIBCPP_INLINE_VISIBILITY @@ -1667,7 +1619,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -struct _LIBCPP_TYPE_VIS __widen_from_utf8<32> +struct _LIBCPP_EXPORTED_FROM_ABI __widen_from_utf8<32> : public codecvt<char32_t, char, mbstate_t> { _LIBCPP_INLINE_VISIBILITY @@ -1706,7 +1658,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP template <class _CharT> class _LIBCPP_TEMPLATE_VIS numpunct; template <> -class _LIBCPP_TYPE_VIS numpunct<char> +class _LIBCPP_EXPORTED_FROM_ABI numpunct<char> : public locale::facet { public: @@ -1738,7 +1690,7 @@ protected: #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS numpunct<wchar_t> +class _LIBCPP_EXPORTED_FROM_ABI numpunct<wchar_t> : public locale::facet { public: @@ -1774,7 +1726,7 @@ protected: template <class _CharT> class _LIBCPP_TEMPLATE_VIS numpunct_byname; template <> -class _LIBCPP_TYPE_VIS numpunct_byname<char> +class _LIBCPP_EXPORTED_FROM_ABI numpunct_byname<char> : public numpunct<char> { public: @@ -1793,7 +1745,7 @@ private: #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS numpunct_byname<wchar_t> +class _LIBCPP_EXPORTED_FROM_ABI numpunct_byname<wchar_t> : public numpunct<wchar_t> { public: diff --git a/libcxx/include/__bsd_locale_defaults.h b/libcxx/include/__locale_dir/locale_base_api/bsd_locale_defaults.h index 4d990482d4a3..38d36f0aa8fc 100644 --- a/libcxx/include/__bsd_locale_defaults.h +++ b/libcxx/include/__locale_dir/locale_base_api/bsd_locale_defaults.h @@ -11,8 +11,8 @@ // we will define the mapping from an internal macro to the real BSD symbol. //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___BSD_LOCALE_DEFAULTS_H -#define _LIBCPP___BSD_LOCALE_DEFAULTS_H +#ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_DEFAULTS_H +#define _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_DEFAULTS_H #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -33,4 +33,4 @@ #define __libcpp_asprintf_l(...) asprintf_l(__VA_ARGS__) #define __libcpp_sscanf_l(...) sscanf_l(__VA_ARGS__) -#endif // _LIBCPP___BSD_LOCALE_DEFAULTS_H +#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_DEFAULTS_H diff --git a/libcxx/include/__bsd_locale_fallbacks.h b/libcxx/include/__locale_dir/locale_base_api/bsd_locale_fallbacks.h index 9abd7e7e5ff4..7776a744d916 100644 --- a/libcxx/include/__bsd_locale_fallbacks.h +++ b/libcxx/include/__locale_dir/locale_base_api/bsd_locale_fallbacks.h @@ -10,12 +10,18 @@ // of those functions for non-BSD platforms. //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___BSD_LOCALE_FALLBACKS_H -#define _LIBCPP___BSD_LOCALE_FALLBACKS_H +#ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_FALLBACKS_H +#define _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_FALLBACKS_H +#include <__locale_dir/locale_base_api/locale_guard.h> +#include <cstdio> #include <stdarg.h> #include <stdlib.h> +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# include <cwchar> +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif @@ -139,4 +145,4 @@ int __libcpp_sscanf_l(const char *__s, locale_t __l, const char *__format, ...) _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP___BSD_LOCALE_FALLBACKS_H +#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_BSD_LOCALE_FALLBACKS_H diff --git a/libcxx/include/__locale_dir/locale_base_api/locale_guard.h b/libcxx/include/__locale_dir/locale_base_api/locale_guard.h new file mode 100644 index 000000000000..0e2e91af7d19 --- /dev/null +++ b/libcxx/include/__locale_dir/locale_base_api/locale_guard.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_LOCALE_GUARD_H +#define _LIBCPP___LOCALE_LOCALE_BASE_API_LOCALE_GUARD_H + +#include <__config> +#include <clocale> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS) +struct __libcpp_locale_guard { + _LIBCPP_INLINE_VISIBILITY __libcpp_locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {} + + _LIBCPP_INLINE_VISIBILITY ~__libcpp_locale_guard() { + if (__old_loc_) + uselocale(__old_loc_); + } + + locale_t __old_loc_; + +private: + __libcpp_locale_guard(__libcpp_locale_guard const&); + __libcpp_locale_guard& operator=(__libcpp_locale_guard const&); +}; +#elif defined(_LIBCPP_MSVCRT_LIKE) +struct __libcpp_locale_guard { + __libcpp_locale_guard(locale_t __l) : + __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) { + // Setting the locale can be expensive even when the locale given is + // already the current locale, so do an explicit check to see if the + // current locale is already the one we want. + const char* __lc = __setlocale(nullptr); + // If every category is the same, the locale string will simply be the + // locale name, otherwise it will be a semicolon-separated string listing + // each category. In the second case, we know at least one category won't + // be what we want, so we only have to check the first case. + if (_VSTD::strcmp(__l.__get_locale(), __lc) != 0) { + __locale_all = _strdup(__lc); + if (__locale_all == nullptr) + __throw_bad_alloc(); + __setlocale(__l.__get_locale()); + } + } + ~__libcpp_locale_guard() { + // The CRT documentation doesn't explicitly say, but setlocale() does the + // right thing when given a semicolon-separated list of locale settings + // for the different categories in the same format as returned by + // setlocale(LC_ALL, nullptr). + if (__locale_all != nullptr) { + __setlocale(__locale_all); + free(__locale_all); + } + _configthreadlocale(__status); + } + static const char* __setlocale(const char* __locale) { + const char* __new_locale = setlocale(LC_ALL, __locale); + if (__new_locale == nullptr) + __throw_bad_alloc(); + return __new_locale; + } + int __status; + char* __locale_all = nullptr; +}; +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___LOCALE_LOCALE_BASE_API_LOCALE_GUARD_H diff --git a/libcxx/include/__mbstate_t.h b/libcxx/include/__mbstate_t.h index 487a6d092c71..2b9e719b1f2e 100644 --- a/libcxx/include/__mbstate_t.h +++ b/libcxx/include/__mbstate_t.h @@ -16,29 +16,39 @@ # pragma GCC system_header #endif -// TODO(ldionne): -// The goal of this header is to provide mbstate_t without having to pull in -// <wchar.h> or <uchar.h>. This is necessary because we need that type even -// when we don't have (or try to provide) support for wchar_t, because several -// types like std::fpos are defined in terms of mbstate_t. +// The goal of this header is to provide mbstate_t without requiring all of +// <uchar.h> or <wchar.h>. It's also used by the libc++ versions of <uchar.h> +// and <wchar.h> to get mbstate_t when the C library doesn't provide <uchar.h> +// or <wchar.h>, hence the #include_next of those headers instead of #include. +// (e.g. if <wchar.h> isn't present in the C library, the libc++ <wchar.h> +// will include this header. This header needs to not turn around and cyclically +// include <wchar.h>, but fall through to <uchar.h>.) // -// This is a gruesome hack, but I don't know how to make it cleaner for -// the time being. +// This does not define std::mbstate_t -- this only brings in the declaration +// in the global namespace. + +// We define this here to support older versions of glibc <wchar.h> that do +// not define this for clang. This is also set in libc++'s <wchar.h> header, +// and we need to do so here too to avoid a different function signature given +// a different include order. +#ifdef __cplusplus +# define __CORRECT_ISO_CPP_WCHAR_H_PROTO +#endif -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -# include <wchar.h> // for mbstate_t +#if defined(_LIBCPP_HAS_MUSL_LIBC) +# define __NEED_mbstate_t +# include <bits/alltypes.h> +# undef __NEED_mbstate_t #elif __has_include(<bits/types/mbstate_t.h>) # include <bits/types/mbstate_t.h> // works on most Unixes #elif __has_include(<sys/_types/_mbstate_t.h>) # include <sys/_types/_mbstate_t.h> // works on Darwin +#elif !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) && __has_include_next(<wchar.h>) +# include_next <wchar.h> // fall back to the C standard provider of mbstate_t +#elif __has_include_next(<uchar.h>) +# include_next <uchar.h> // <uchar.h> is also required to make mbstate_t visible #else -# error "The library was configured without support for wide-characters, but we don't know how to get the definition of mbstate_t without <wchar.h> on your platform." +# error "We don't know how to get the definition of mbstate_t without <wchar.h> on your platform." #endif -_LIBCPP_BEGIN_NAMESPACE_STD - -using ::mbstate_t _LIBCPP_USING_IF_EXISTS; - -_LIBCPP_END_NAMESPACE_STD - #endif // _LIBCPP___MBSTATE_T_H diff --git a/libcxx/include/__mdspan/default_accessor.h b/libcxx/include/__mdspan/default_accessor.h new file mode 100644 index 000000000000..1cc5f15545fc --- /dev/null +++ b/libcxx/include/__mdspan/default_accessor.h @@ -0,0 +1,66 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___MDSPAN_DEFAULT_ACCESSOR_H +#define _LIBCPP___MDSPAN_DEFAULT_ACCESSOR_H + +#include <__config> +#include <__type_traits/is_abstract.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/remove_const.h> +#include <cinttypes> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template <class _ElementType> +struct default_accessor { + static_assert(!is_array_v<_ElementType>, "default_accessor: template argument may not be an array type"); + static_assert(!is_abstract_v<_ElementType>, "default_accessor: template argument may not be an abstract class"); + + using offset_policy = default_accessor; + using element_type = _ElementType; + using reference = _ElementType&; + using data_handle_type = _ElementType*; + + _LIBCPP_HIDE_FROM_ABI constexpr default_accessor() noexcept = default; + template <class _OtherElementType> + requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]>) + _LIBCPP_HIDE_FROM_ABI constexpr default_accessor(default_accessor<_OtherElementType>) noexcept {} + + _LIBCPP_HIDE_FROM_ABI constexpr reference access(data_handle_type __p, size_t __i) const noexcept { return __p[__i]; } + _LIBCPP_HIDE_FROM_ABI constexpr data_handle_type offset(data_handle_type __p, size_t __i) const noexcept { + return __p + __i; + } +}; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_DEFAULT_ACCESSOR_H diff --git a/libcxx/include/__mdspan/extents.h b/libcxx/include/__mdspan/extents.h new file mode 100644 index 000000000000..42355678d60c --- /dev/null +++ b/libcxx/include/__mdspan/extents.h @@ -0,0 +1,498 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___MDSPAN_EXTENTS_H +#define _LIBCPP___MDSPAN_EXTENTS_H + +#include <__assert> +#include <__config> +#include <__type_traits/common_type.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/make_unsigned.h> +#include <__utility/integer_sequence.h> +#include <__utility/unreachable.h> +#include <array> +#include <cinttypes> +#include <concepts> +#include <cstddef> +#include <limits> +#include <span> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +namespace __mdspan_detail { + +// ------------------------------------------------------------------ +// ------------ __static_array -------------------------------------- +// ------------------------------------------------------------------ +// array like class which provides an array of static values with get +template <class _Tp, _Tp... _Values> +struct __static_array { + static constexpr array<_Tp, sizeof...(_Values)> __array = {_Values...}; + +public: + _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return sizeof...(_Values); } + _LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get(size_t __index) noexcept { return __array[__index]; } + + template <size_t _Index> + _LIBCPP_HIDE_FROM_ABI static constexpr _Tp __get() { + return __get(_Index); + } +}; + +// ------------------------------------------------------------------ +// ------------ __possibly_empty_array ----------------------------- +// ------------------------------------------------------------------ + +// array like class which provides get function and operator [], and +// has a specialization for the size 0 case. +// This is needed to make the __maybe_static_array be truly empty, for +// all static values. + +template <class _Tp, size_t _Size> +struct __possibly_empty_array { + _Tp __vals_[_Size]; + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator[](size_t __index) { return __vals_[__index]; } + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t __index) const { return __vals_[__index]; } +}; + +template <class _Tp> +struct __possibly_empty_array<_Tp, 0> { + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator[](size_t) { __libcpp_unreachable(); } + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t) const { __libcpp_unreachable(); } +}; + +// ------------------------------------------------------------------ +// ------------ static_partial_sums --------------------------------- +// ------------------------------------------------------------------ + +// Provides a compile time partial sum one can index into + +template <size_t... _Values> +struct __static_partial_sums { + _LIBCPP_HIDE_FROM_ABI static constexpr array<size_t, sizeof...(_Values)> __static_partial_sums_impl() { + array<size_t, sizeof...(_Values)> __values{_Values...}; + array<size_t, sizeof...(_Values)> __partial_sums{{}}; + size_t __running_sum = 0; + for (int __i = 0; __i != sizeof...(_Values); ++__i) { + __partial_sums[__i] = __running_sum; + __running_sum += __values[__i]; + } + return __partial_sums; + } + static constexpr array<size_t, sizeof...(_Values)> __result{__static_partial_sums_impl()}; + + _LIBCPP_HIDE_FROM_ABI static constexpr size_t __get(size_t __index) { return __result[__index]; } +}; + +// ------------------------------------------------------------------ +// ------------ __maybe_static_array -------------------------------- +// ------------------------------------------------------------------ + +// array like class which has a mix of static and runtime values but +// only stores the runtime values. +// The type of the static and the runtime values can be different. +// The position of a dynamic value is indicated through a tag value. +template <class _TDynamic, class _TStatic, _TStatic _DynTag, _TStatic... _Values> +struct __maybe_static_array { + static_assert(is_convertible<_TStatic, _TDynamic>::value, + "__maybe_static_array: _TStatic must be convertible to _TDynamic"); + static_assert(is_convertible<_TDynamic, _TStatic>::value, + "__maybe_static_array: _TDynamic must be convertible to _TStatic"); + +private: + // Static values member + static constexpr size_t __size_ = sizeof...(_Values); + static constexpr size_t __size_dynamic_ = ((_Values == _DynTag) + ... + 0); + using _StaticValues = __static_array<_TStatic, _Values...>; + using _DynamicValues = __possibly_empty_array<_TDynamic, __size_dynamic_>; + + // Dynamic values member + _LIBCPP_NO_UNIQUE_ADDRESS _DynamicValues __dyn_vals_; + + // static mapping of indices to the position in the dynamic values array + using _DynamicIdxMap = __static_partial_sums<static_cast<size_t>(_Values == _DynTag)...>; + + template <size_t... Indices> + _LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(index_sequence<Indices...>) noexcept { + return _DynamicValues{((void)Indices, 0)...}; + } + +public: + _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array() noexcept + : __dyn_vals_{__zeros(make_index_sequence<__size_dynamic_>())} {} + + // constructors from dynamic values only -- this covers the case for rank() == 0 + template <class... _DynVals> + requires(sizeof...(_DynVals) == __size_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals) + : __dyn_vals_{static_cast<_TDynamic>(__vals)...} {} + + template <class _Tp, size_t _Size > + requires(_Size == __size_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array([[maybe_unused]] const span<_Tp, _Size>& __vals) { + if constexpr (_Size > 0) { + for (size_t __i = 0; __i < _Size; __i++) + __dyn_vals_[__i] = static_cast<_TDynamic>(__vals[__i]); + } + } + + // constructors from all values -- here rank will be greater than 0 + template <class... _DynVals> + requires(sizeof...(_DynVals) != __size_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(_DynVals... __vals) { + static_assert((sizeof...(_DynVals) == __size_), "Invalid number of values."); + _TDynamic __values[__size_] = {static_cast<_TDynamic>(__vals)...}; + for (size_t __i = 0; __i < __size_; __i++) { + _TStatic __static_val = _StaticValues::__get(__i); + if (__static_val == _DynTag) { + __dyn_vals_[_DynamicIdxMap::__get(__i)] = __values[__i]; + } + // Precondition check + else + _LIBCPP_ASSERT_UNCATEGORIZED(__values[__i] == static_cast<_TDynamic>(__static_val), + "extents construction: mismatch of provided arguments with static extents."); + } + } + + template <class _Tp, size_t _Size> + requires(_Size != __size_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr __maybe_static_array(const span<_Tp, _Size>& __vals) { + static_assert((_Size == __size_) || (__size_ == dynamic_extent)); + for (size_t __i = 0; __i < __size_; __i++) { + _TStatic __static_val = _StaticValues::__get(__i); + if (__static_val == _DynTag) { + __dyn_vals_[_DynamicIdxMap::__get(__i)] = static_cast<_TDynamic>(__vals[__i]); + } + // Precondition check + else + _LIBCPP_ASSERT_UNCATEGORIZED(static_cast<_TDynamic>(__vals[__i]) == static_cast<_TDynamic>(__static_val), + "extents construction: mismatch of provided arguments with static extents."); + } + } + + // access functions + _LIBCPP_HIDE_FROM_ABI static constexpr _TStatic __static_value(size_t __i) noexcept { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank"); + return _StaticValues::__get(__i); + } + + _LIBCPP_HIDE_FROM_ABI constexpr _TDynamic __value(size_t __i) const { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank"); + _TStatic __static_val = _StaticValues::__get(__i); + return __static_val == _DynTag ? __dyn_vals_[_DynamicIdxMap::__get(__i)] : static_cast<_TDynamic>(__static_val); + } + _LIBCPP_HIDE_FROM_ABI constexpr _TDynamic operator[](size_t __i) const { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < __size_, "extents access: index must be less than rank"); + return __value(__i); + } + + // observers + _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size() { return __size_; } + _LIBCPP_HIDE_FROM_ABI static constexpr size_t __size_dynamic() { return __size_dynamic_; } +}; + +// Function to check whether a value is representable as another type +// value must be a positive integer otherwise returns false +// if _From is not an integral, we just check positivity +template <integral _To, class _From> + requires(integral<_From>) +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_representable_as(_From __value) { + using _To_u = make_unsigned_t<_To>; + using _From_u = make_unsigned_t<_From>; + if constexpr (is_signed_v<_From>) { + if (__value < 0) + return false; + } + if constexpr (static_cast<_To_u>(numeric_limits<_To>::max()) >= static_cast<_From_u>(numeric_limits<_From>::max())) { + return true; + } else { + return static_cast<_To_u>(numeric_limits<_To>::max()) >= static_cast<_From_u>(__value); + } +} + +template <integral _To, class _From> + requires(!integral<_From>) +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_representable_as(_From __value) { + if constexpr (is_signed_v<_To>) { + if (static_cast<_To>(__value) < 0) + return false; + } + return true; +} + +template <integral _To, class... _From> +_LIBCPP_HIDE_FROM_ABI constexpr bool __are_representable_as(_From... __values) { + return (__mdspan_detail::__is_representable_as<_To>(__values) && ... && true); +} + +template <integral _To, class _From, size_t _Size> +_LIBCPP_HIDE_FROM_ABI constexpr bool __are_representable_as(span<_From, _Size> __values) { + for (size_t __i = 0; __i < _Size; __i++) + if (!__mdspan_detail::__is_representable_as<_To>(__values[__i])) + return false; + return true; +} + +} // namespace __mdspan_detail + +// ------------------------------------------------------------------ +// ------------ extents --------------------------------------------- +// ------------------------------------------------------------------ + +// Class to describe the extents of a multi dimensional array. +// Used by mdspan, mdarray and layout mappings. +// See ISO C++ standard [mdspan.extents] + +template <class _IndexType, size_t... _Extents> +class extents { +public: + // typedefs for integral types used + using index_type = _IndexType; + using size_type = make_unsigned_t<index_type>; + using rank_type = size_t; + + static_assert(is_integral<index_type>::value && !is_same<index_type, bool>::value, + "extents::index_type must be a signed or unsigned integer type"); + static_assert(((__mdspan_detail::__is_representable_as<index_type>(_Extents) || (_Extents == dynamic_extent)) && ...), + "extents ctor: arguments must be representable as index_type and nonnegative"); + +private: + static constexpr rank_type __rank_ = sizeof...(_Extents); + static constexpr rank_type __rank_dynamic_ = ((_Extents == dynamic_extent) + ... + 0); + + // internal storage type using __maybe_static_array + using _Values = __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>; + [[no_unique_address]] _Values __vals_; + +public: + // [mdspan.extents.obs], observers of multidimensional index space + _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank() noexcept { return __rank_; } + _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept { return __rank_dynamic_; } + + _LIBCPP_HIDE_FROM_ABI constexpr index_type extent(rank_type __r) const noexcept { return __vals_.__value(__r); } + _LIBCPP_HIDE_FROM_ABI static constexpr size_t static_extent(rank_type __r) noexcept { + return _Values::__static_value(__r); + } + + // [mdspan.extents.cons], constructors + _LIBCPP_HIDE_FROM_ABI constexpr extents() noexcept = default; + + // Construction from just dynamic or all values. + // Precondition check is deferred to __maybe_static_array constructor + template <class... _OtherIndexTypes> + requires((is_convertible_v<_OtherIndexTypes, index_type> && ...) && + (is_nothrow_constructible_v<index_type, _OtherIndexTypes> && ...) && + (sizeof...(_OtherIndexTypes) == __rank_ || sizeof...(_OtherIndexTypes) == __rank_dynamic_)) + _LIBCPP_HIDE_FROM_ABI constexpr explicit extents(_OtherIndexTypes... __dynvals) noexcept + : __vals_(static_cast<index_type>(__dynvals)...) { + _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__are_representable_as<index_type>(__dynvals...), + "extents ctor: arguments must be representable as index_type and nonnegative"); + } + + template <class _OtherIndexType, size_t _Size> + requires(is_convertible_v<_OtherIndexType, index_type> && is_nothrow_constructible_v<index_type, _OtherIndexType> && + (_Size == __rank_ || _Size == __rank_dynamic_)) + explicit(_Size != __rank_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr extents(const array<_OtherIndexType, _Size>& __exts) noexcept + : __vals_(span(__exts)) { + _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__are_representable_as<index_type>(span(__exts)), + "extents ctor: arguments must be representable as index_type and nonnegative"); + } + + template <class _OtherIndexType, size_t _Size> + requires(is_convertible_v<_OtherIndexType, index_type> && is_nothrow_constructible_v<index_type, _OtherIndexType> && + (_Size == __rank_ || _Size == __rank_dynamic_)) + explicit(_Size != __rank_dynamic_) + _LIBCPP_HIDE_FROM_ABI constexpr extents(const span<_OtherIndexType, _Size>& __exts) noexcept + : __vals_(__exts) { + _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__are_representable_as<index_type>(__exts), + "extents ctor: arguments must be representable as index_type and nonnegative"); + } + +private: + // Function to construct extents storage from other extents. + template <size_t _DynCount, size_t _Idx, class _OtherExtents, class... _DynamicValues> + requires(_Idx < __rank_) + _LIBCPP_HIDE_FROM_ABI constexpr _Values __construct_vals_from_extents( + integral_constant<size_t, _DynCount>, + integral_constant<size_t, _Idx>, + const _OtherExtents& __exts, + _DynamicValues... __dynamic_values) noexcept { + if constexpr (static_extent(_Idx) == dynamic_extent) + return __construct_vals_from_extents( + integral_constant<size_t, _DynCount + 1>(), + integral_constant<size_t, _Idx + 1>(), + __exts, + __dynamic_values..., + __exts.extent(_Idx)); + else + return __construct_vals_from_extents( + integral_constant<size_t, _DynCount>(), integral_constant<size_t, _Idx + 1>(), __exts, __dynamic_values...); + } + + template <size_t _DynCount, size_t _Idx, class _OtherExtents, class... _DynamicValues> + requires((_Idx == __rank_) && (_DynCount == __rank_dynamic_)) + _LIBCPP_HIDE_FROM_ABI constexpr _Values __construct_vals_from_extents( + integral_constant<size_t, _DynCount>, + integral_constant<size_t, _Idx>, + const _OtherExtents&, + _DynamicValues... __dynamic_values) noexcept { + return _Values{static_cast<index_type>(__dynamic_values)...}; + } + +public: + // Converting constructor from other extents specializations + template <class _OtherIndexType, size_t... _OtherExtents> + requires((sizeof...(_OtherExtents) == sizeof...(_Extents)) && + ((_OtherExtents == dynamic_extent || _Extents == dynamic_extent || _OtherExtents == _Extents) && ...)) + explicit((((_Extents != dynamic_extent) && (_OtherExtents == dynamic_extent)) || ...) || + (static_cast<make_unsigned_t<index_type>>(numeric_limits<index_type>::max()) < + static_cast<make_unsigned_t<_OtherIndexType>>(numeric_limits<_OtherIndexType>::max()))) + _LIBCPP_HIDE_FROM_ABI constexpr extents(const extents<_OtherIndexType, _OtherExtents...>& __other) noexcept + : __vals_( + __construct_vals_from_extents(integral_constant<size_t, 0>(), integral_constant<size_t, 0>(), __other)) { + if constexpr (rank() > 0) { + for (size_t __r = 0; __r < rank(); __r++) { + if constexpr (static_cast<make_unsigned_t<index_type>>(numeric_limits<index_type>::max()) < + static_cast<make_unsigned_t<_OtherIndexType>>(numeric_limits<_OtherIndexType>::max())) { + _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__is_representable_as<index_type>(__other.extent(__r)), + "extents ctor: arguments must be representable as index_type and nonnegative"); + } + _LIBCPP_ASSERT_UNCATEGORIZED( + (_Values::__static_value(__r) == dynamic_extent) || + (static_cast<index_type>(__other.extent(__r)) == static_cast<index_type>(_Values::__static_value(__r))), + "extents construction: mismatch of provided arguments with static extents."); + } + } + } + + // Comparison operator + template <class _OtherIndexType, size_t... _OtherExtents> + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const extents& __lhs, const extents<_OtherIndexType, _OtherExtents...>& __rhs) noexcept { + if constexpr (rank() != sizeof...(_OtherExtents)) { + return false; + } else { + for (rank_type __r = 0; __r < __rank_; __r++) { + // avoid warning when comparing signed and unsigner integers and pick the wider of two types + using _CommonType = common_type_t<index_type, _OtherIndexType>; + if (static_cast<_CommonType>(__lhs.extent(__r)) != static_cast<_CommonType>(__rhs.extent(__r))) { + return false; + } + } + } + return true; + } +}; + +// Recursive helper classes to implement dextents alias for extents +namespace __mdspan_detail { + +template <class _IndexType, size_t _Rank, class _Extents = extents<_IndexType>> +struct __make_dextents; + +template <class _IndexType, size_t _Rank, size_t... _ExtentsPack> +struct __make_dextents< _IndexType, _Rank, extents<_IndexType, _ExtentsPack...>> { + using type = + typename __make_dextents< _IndexType, _Rank - 1, extents<_IndexType, dynamic_extent, _ExtentsPack...>>::type; +}; + +template <class _IndexType, size_t... _ExtentsPack> +struct __make_dextents< _IndexType, 0, extents<_IndexType, _ExtentsPack...>> { + using type = extents<_IndexType, _ExtentsPack...>; +}; + +} // end namespace __mdspan_detail + +// [mdspan.extents.dextents], alias template +template <class _IndexType, size_t _Rank> +using dextents = typename __mdspan_detail::__make_dextents<_IndexType, _Rank>::type; + +// Deduction guide for extents +template <class... _IndexTypes> +extents(_IndexTypes...) -> extents<size_t, size_t((_IndexTypes(), dynamic_extent))...>; + +namespace __mdspan_detail { + +// Helper type traits for identifying a class as extents. +template <class _Tp> +struct __is_extents : false_type {}; + +template <class _IndexType, size_t... _ExtentsPack> +struct __is_extents<extents<_IndexType, _ExtentsPack...>> : true_type {}; + +template <class _Tp> +inline constexpr bool __is_extents_v = __is_extents<_Tp>::value; + +// Function to check whether a set of indices are a multidimensional +// index into extents. This is a word of power in the C++ standard +// requiring that the indices are larger than 0 and smaller than +// the respective extents. + +template <integral _IndexType, class _From> + requires(integral<_From>) +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_index_in_extent(_IndexType __extent, _From __value) { + if constexpr (is_signed_v<_From>) { + if (__value < 0) + return false; + } + using _Tp = common_type_t<_IndexType, _From>; + return static_cast<_Tp>(__value) < static_cast<_Tp>(__extent); +} + +template <integral _IndexType, class _From> + requires(!integral<_From>) +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_index_in_extent(_IndexType __extent, _From __value) { + if constexpr (is_signed_v<_IndexType>) { + if (static_cast<_IndexType>(__value) < 0) + return false; + } + return static_cast<_IndexType>(__value) < __extent; +} + +template <size_t... _Idxs, class _Extents, class... _From> +_LIBCPP_HIDE_FROM_ABI constexpr bool +__is_multidimensional_index_in_impl(index_sequence<_Idxs...>, const _Extents& __ext, _From... __values) { + return (__mdspan_detail::__is_index_in_extent(__ext.extent(_Idxs), __values) && ...); +} + +template <class _Extents, class... _From> +_LIBCPP_HIDE_FROM_ABI constexpr bool __is_multidimensional_index_in(const _Extents& __ext, _From... __values) { + return __mdspan_detail::__is_multidimensional_index_in_impl( + make_index_sequence<_Extents::rank()>(), __ext, __values...); +} + +} // namespace __mdspan_detail + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_EXTENTS_H diff --git a/libcxx/include/__mdspan/layout_left.h b/libcxx/include/__mdspan/layout_left.h new file mode 100644 index 000000000000..e81e0d10b595 --- /dev/null +++ b/libcxx/include/__mdspan/layout_left.h @@ -0,0 +1,171 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___MDSPAN_LAYOUT_LEFT_H +#define _LIBCPP___MDSPAN_LAYOUT_LEFT_H + +#include <__assert> +#include <__config> +#include <__fwd/mdspan.h> +#include <__mdspan/extents.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__utility/integer_sequence.h> +#include <array> +#include <cinttypes> +#include <cstddef> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template <class _Extents> +class layout_left::mapping { +public: + static_assert(__mdspan_detail::__is_extents<_Extents>::value, + "layout_left::mapping template argument must be a specialization of extents."); + + using extents_type = _Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_left; + +private: + _LIBCPP_HIDE_FROM_ABI static constexpr bool __required_span_size_is_representable(const extents_type& __ext) { + if constexpr (extents_type::rank() == 0) + return true; + + index_type __prod = __ext.extent(0); + for (rank_type __r = 1; __r < extents_type::rank(); __r++) { + bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), &__prod); + if (__overflowed) + return false; + } + return true; + } + + static_assert((extents_type::rank_dynamic() > 0) || __required_span_size_is_representable(extents_type()), + "layout_left::mapping product of static extents must be representable as index_type."); + +public: + // [mdspan.layout.left.cons], constructors + _LIBCPP_HIDE_FROM_ABI constexpr mapping() noexcept = default; + _LIBCPP_HIDE_FROM_ABI constexpr mapping(const mapping&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext) noexcept : __extents_(__ext) { + _LIBCPP_ASSERT(__required_span_size_is_representable(__ext), + "layout_left::mapping extents ctor: product of extents must be representable as index_type."); + } + + template <class _OtherExtents> + requires(is_constructible_v<extents_type, _OtherExtents>) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) + mapping(const mapping<_OtherExtents>& __other) noexcept + : __extents_(__other.extents()) { + _LIBCPP_ASSERT( + __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()), + "layout_left::mapping converting ctor: other.required_span_size() must be representable as index_type."); + } + + template <class _OtherExtents> + requires(is_constructible_v<extents_type, _OtherExtents> && _OtherExtents::rank() <= 1) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) + mapping(const layout_right::mapping<_OtherExtents>& __other) noexcept + : __extents_(__other.extents()) { + _LIBCPP_ASSERT( + __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()), + "layout_left::mapping converting ctor: other.required_span_size() must be representable as index_type."); + } + +// FIXME: add when we add other layouts +# if 0 + template<class _OtherExtents> + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping_<OtherExtents>&) noexcept; +# endif + + _LIBCPP_HIDE_FROM_ABI constexpr mapping& operator=(const mapping&) noexcept = default; + + // [mdspan.layout.left.obs], observers + _LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept { return __extents_; } + + _LIBCPP_HIDE_FROM_ABI constexpr index_type required_span_size() const noexcept { + index_type __size = 1; + for (size_t __r = 0; __r < extents_type::rank(); __r++) + __size *= __extents_.extent(__r); + return __size; + } + + template <class... _Indices> + requires((sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...) && + (is_nothrow_constructible_v<index_type, _Indices> && ...)) + _LIBCPP_HIDE_FROM_ABI constexpr index_type operator()(_Indices... __idx) const noexcept { + _LIBCPP_ASSERT(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...), + "layout_left::mapping: out of bounds indexing"); + array<index_type, extents_type::rank()> __idx_a{static_cast<index_type>(__idx)...}; + return [&]<size_t... _Pos>(index_sequence<_Pos...>) { + index_type __res = 0; + ((__res = __idx_a[extents_type::rank() - 1 - _Pos] + __extents_.extent(extents_type::rank() - 1 - _Pos) * __res), + ...); + return __res; + }(make_index_sequence<sizeof...(_Indices)>()); + } + + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept { return true; } + + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_unique() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_exhaustive() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_strided() noexcept { return true; } + + _LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept + requires(extents_type::rank() > 0) + { + _LIBCPP_ASSERT(__r < extents_type::rank(), "layout_left::mapping::stride(): invalid rank index"); + index_type __s = 1; + for (rank_type __i = extents_type::rank() - 1; __i > __r; __i--) + __s *= __extents_.extent(__i); + return __s; + } + + template <class _OtherExtents> + requires(_OtherExtents::rank() == extents_type::rank()) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const mapping& __lhs, const mapping<_OtherExtents>& __rhs) noexcept { + return __lhs.extents() == __rhs.extents(); + } + +private: + extents_type __extents_{}; // exposition only +}; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_LAYOUT_LEFT_H diff --git a/libcxx/include/__mdspan/layout_right.h b/libcxx/include/__mdspan/layout_right.h new file mode 100644 index 000000000000..a8a91b86c714 --- /dev/null +++ b/libcxx/include/__mdspan/layout_right.h @@ -0,0 +1,168 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___MDSPAN_LAYOUT_RIGHT_H +#define _LIBCPP___MDSPAN_LAYOUT_RIGHT_H + +#include <__assert> +#include <__config> +#include <__fwd/mdspan.h> +#include <__mdspan/extents.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__utility/integer_sequence.h> +#include <cinttypes> +#include <cstddef> +#include <limits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template <class _Extents> +class layout_right::mapping { +public: + static_assert(__mdspan_detail::__is_extents<_Extents>::value, + "layout_right::mapping template argument must be a specialization of extents."); + + using extents_type = _Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_right; + +private: + _LIBCPP_HIDE_FROM_ABI static constexpr bool __required_span_size_is_representable(const extents_type& __ext) { + if constexpr (extents_type::rank() == 0) + return true; + + index_type __prod = __ext.extent(0); + for (rank_type __r = 1; __r < extents_type::rank(); __r++) { + bool __overflowed = __builtin_mul_overflow(__prod, __ext.extent(__r), &__prod); + if (__overflowed) + return false; + } + return true; + } + + static_assert((extents_type::rank_dynamic() > 0) || __required_span_size_is_representable(extents_type()), + "layout_right::mapping product of static extents must be representable as index_type."); + +public: + // [mdspan.layout.right.cons], constructors + _LIBCPP_HIDE_FROM_ABI constexpr mapping() noexcept = default; + _LIBCPP_HIDE_FROM_ABI constexpr mapping(const mapping&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext) noexcept : __extents_(__ext) { + _LIBCPP_ASSERT(__required_span_size_is_representable(__ext), + "layout_right::mapping extents ctor: product of extents must be representable as index_type."); + } + + template <class _OtherExtents> + requires(is_constructible_v<extents_type, _OtherExtents>) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) + mapping(const mapping<_OtherExtents>& __other) noexcept + : __extents_(__other.extents()) { + _LIBCPP_ASSERT( + __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()), + "layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type."); + } + + template <class _OtherExtents> + requires(is_constructible_v<extents_type, _OtherExtents> && _OtherExtents::rank() <= 1) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) + mapping(const layout_left::mapping<_OtherExtents>& __other) noexcept + : __extents_(__other.extents()) { + _LIBCPP_ASSERT( + __mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()), + "layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type."); + } + +// FIXME: add when we add other layouts +# if 0 + template<class _OtherExtents> + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping_<OtherExtents>&) noexcept; +# endif + + _LIBCPP_HIDE_FROM_ABI constexpr mapping& operator=(const mapping&) noexcept = default; + + // [mdspan.layout.right.obs], observers + _LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept { return __extents_; } + + _LIBCPP_HIDE_FROM_ABI constexpr index_type required_span_size() const noexcept { + index_type __size = 1; + for (size_t __r = 0; __r < extents_type::rank(); __r++) + __size *= __extents_.extent(__r); + return __size; + } + + template <class... _Indices> + requires((sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...) && + (is_nothrow_constructible_v<index_type, _Indices> && ...)) + _LIBCPP_HIDE_FROM_ABI constexpr index_type operator()(_Indices... __idx) const noexcept { + _LIBCPP_ASSERT(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...), + "layout_right::mapping: out of bounds indexing"); + return [&]<size_t... _Pos>(index_sequence<_Pos...>) { + index_type __res = 0; + ((__res = static_cast<index_type>(__idx) + __extents_.extent(_Pos) * __res), ...); + return __res; + }(make_index_sequence<sizeof...(_Indices)>()); + } + + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept { return true; } + + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_unique() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_exhaustive() noexcept { return true; } + _LIBCPP_HIDE_FROM_ABI static constexpr bool is_strided() noexcept { return true; } + + _LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept + requires(extents_type::rank() > 0) + { + _LIBCPP_ASSERT(__r < extents_type::rank(), "layout_right::mapping::stride(): invalid rank index"); + index_type __s = 1; + for (rank_type __i = extents_type::rank() - 1; __i > __r; __i--) + __s *= __extents_.extent(__i); + return __s; + } + + template <class _OtherExtents> + requires(_OtherExtents::rank() == extents_type::rank()) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const mapping& __lhs, const mapping<_OtherExtents>& __rhs) noexcept { + return __lhs.extents() == __rhs.extents(); + } + +private: + extents_type __extents_{}; // exposition only +}; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_LAYOUT_RIGHT_H diff --git a/libcxx/include/__memory/align.h b/libcxx/include/__memory/align.h index c6792206b075..bbb995f4a8c8 100644 --- a/libcxx/include/__memory/align.h +++ b/libcxx/include/__memory/align.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -_LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space); +_LIBCPP_EXPORTED_FROM_ABI void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space); _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__memory/aligned_alloc.h b/libcxx/include/__memory/aligned_alloc.h new file mode 100644 index 000000000000..786963c72dfc --- /dev/null +++ b/libcxx/include/__memory/aligned_alloc.h @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MEMORY_ALIGNED_ALLOC_H +#define _LIBCPP___MEMORY_ALIGNED_ALLOC_H + +#include <__config> +#include <cstddef> +#include <cstdlib> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION + +// Low-level helpers to call the aligned allocation and deallocation functions +// on the target platform. This is used to implement libc++'s own memory +// allocation routines -- if you need to allocate memory inside the library, +// chances are that you want to use `__libcpp_allocate` instead. +// +// Returns the allocated memory, or `nullptr` on failure. +inline _LIBCPP_HIDE_FROM_ABI +void* __libcpp_aligned_alloc(std::size_t __alignment, std::size_t __size) { +# if defined(_LIBCPP_MSVCRT_LIKE) + return ::_aligned_malloc(__size, __alignment); +# elif _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_C11_ALIGNED_ALLOC) + // aligned_alloc() requires that __size is a multiple of __alignment, + // but for C++ [new.delete.general], only states "if the value of an + // alignment argument passed to any of these functions is not a valid + // alignment value, the behavior is undefined". + // To handle calls such as ::operator new(1, std::align_val_t(128)), we + // round __size up to the next multiple of __alignment. + size_t __rounded_size = (__size + __alignment - 1) & ~(__alignment - 1); + // Rounding up could have wrapped around to zero, so we have to add another + // max() ternary to the actual call site to avoid succeeded in that case. + return ::aligned_alloc(__alignment, __size > __rounded_size ? __size : __rounded_size); +# else + void* __result = nullptr; + (void)::posix_memalign(&__result, __alignment, __size); + // If posix_memalign fails, __result is unmodified so we still return `nullptr`. + return __result; +# endif +} + +inline _LIBCPP_HIDE_FROM_ABI +void __libcpp_aligned_free(void* __ptr) { +#if defined(_LIBCPP_MSVCRT_LIKE) + ::_aligned_free(__ptr); +#else + ::free(__ptr); +#endif +} + +#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MEMORY_ALIGNED_ALLOC_H diff --git a/libcxx/include/__memory/allocate_at_least.h b/libcxx/include/__memory/allocate_at_least.h index ef205f855cb2..8d8ad071e2c2 100644 --- a/libcxx/include/__memory/allocate_at_least.h +++ b/libcxx/include/__memory/allocate_at_least.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _Pointer> struct allocation_result { _Pointer ptr; @@ -55,7 +55,7 @@ __allocation_result<typename allocator_traits<_Alloc>::pointer> __allocate_at_le return {__alloc.allocate(__n), __n}; } -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__memory/allocation_guard.h b/libcxx/include/__memory/allocation_guard.h index 424598cc8158..f63b17430ed1 100644 --- a/libcxx/include/__memory/allocation_guard.h +++ b/libcxx/include/__memory/allocation_guard.h @@ -11,6 +11,7 @@ #define _LIBCPP___MEMORY_ALLOCATION_GUARD_H #include <__config> +#include <__memory/addressof.h> #include <__memory/allocator_traits.h> #include <__utility/move.h> #include <cstddef> @@ -19,6 +20,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // Helper class to allocate memory using an Allocator in an exception safe @@ -55,9 +59,29 @@ struct __allocation_guard { _LIBCPP_HIDE_FROM_ABI ~__allocation_guard() _NOEXCEPT { - if (__ptr_ != nullptr) { - allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_); + __destroy(); + } + + _LIBCPP_HIDE_FROM_ABI __allocation_guard(const __allocation_guard&) = delete; + _LIBCPP_HIDE_FROM_ABI __allocation_guard(__allocation_guard&& __other) _NOEXCEPT + : __alloc_(std::move(__other.__alloc_)) + , __n_(__other.__n_) + , __ptr_(__other.__ptr_) { + __other.__ptr_ = nullptr; + } + + _LIBCPP_HIDE_FROM_ABI __allocation_guard& operator=(const __allocation_guard& __other) = delete; + _LIBCPP_HIDE_FROM_ABI __allocation_guard& operator=(__allocation_guard&& __other) _NOEXCEPT { + if (std::addressof(__other) != this) { + __destroy(); + + __alloc_ = std::move(__other.__alloc_); + __n_ = __other.__n_; + __ptr_ = __other.__ptr_; + __other.__ptr_ = nullptr; } + + return *this; } _LIBCPP_HIDE_FROM_ABI @@ -73,6 +97,13 @@ struct __allocation_guard { } private: + _LIBCPP_HIDE_FROM_ABI + void __destroy() _NOEXCEPT { + if (__ptr_ != nullptr) { + allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_); + } + } + _Alloc __alloc_; _Size __n_; _Pointer __ptr_; @@ -80,4 +111,6 @@ private: _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_ALLOCATION_GUARD_H diff --git a/libcxx/include/__memory/allocator.h b/libcxx/include/__memory/allocator.h index 54c9b78d524d..47e1ef926a4a 100644 --- a/libcxx/include/__memory/allocator.h +++ b/libcxx/include/__memory/allocator.h @@ -11,6 +11,7 @@ #define _LIBCPP___MEMORY_ALLOCATOR_H #include <__config> +#include <__memory/addressof.h> #include <__memory/allocate_at_least.h> #include <__memory/allocator_traits.h> #include <__type_traits/is_constant_evaluated.h> @@ -20,7 +21,6 @@ #include <__utility/forward.h> #include <cstddef> #include <new> -#include <stdexcept> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -98,8 +98,7 @@ public: typedef true_type propagate_on_container_move_assignment; typedef true_type is_always_equal; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 - allocator() _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator() _NOEXCEPT = default; template <class _Up> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -116,7 +115,7 @@ public: } } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr allocation_result<_Tp*> allocate_at_least(size_t __n) { return {allocate(__n), __n}; @@ -187,8 +186,7 @@ public: typedef true_type propagate_on_container_move_assignment; typedef true_type is_always_equal; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 - allocator() _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator() _NOEXCEPT = default; template <class _Up> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -205,7 +203,7 @@ public: } } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr allocation_result<const _Tp*> allocate_at_least(size_t __n) { return {allocate(__n), __n}; @@ -264,10 +262,14 @@ template <class _Tp, class _Up> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool operator==(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return true;} +#if _LIBCPP_STD_VER <= 17 + template <class _Tp, class _Up> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const allocator<_Tp>&, const allocator<_Up>&) _NOEXCEPT {return false;} +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___MEMORY_ALLOCATOR_H diff --git a/libcxx/include/__memory/allocator_arg_t.h b/libcxx/include/__memory/allocator_arg_t.h index 15f8c98c4c90..4d9c115f7293 100644 --- a/libcxx/include/__memory/allocator_arg_t.h +++ b/libcxx/include/__memory/allocator_arg_t.h @@ -25,10 +25,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { explicit allocator_arg_t() = default; }; -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) -extern _LIBCPP_EXPORTED_FROM_ABI const allocator_arg_t allocator_arg; -#else -/* inline */ constexpr allocator_arg_t allocator_arg = allocator_arg_t(); +#if _LIBCPP_STD_VER >= 17 +inline constexpr allocator_arg_t allocator_arg = allocator_arg_t(); +#elif !defined(_LIBCPP_CXX03_LANG) +constexpr allocator_arg_t allocator_arg = allocator_arg_t(); #endif #ifndef _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h index 3a23b47c74b3..4658098d64c9 100644 --- a/libcxx/include/__memory/allocator_traits.h +++ b/libcxx/include/__memory/allocator_traits.h @@ -300,7 +300,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits __enable_if_t<!__has_construct<allocator_type, _Tp*, _Args...>::value> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 static void construct(allocator_type&, _Tp* __p, _Args&&... __args) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _VSTD::construct_at(__p, _VSTD::forward<_Args>(__args)...); #else ::new ((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...); @@ -319,7 +319,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits __enable_if_t<!__has_destroy<allocator_type, _Tp*>::value> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 static void destroy(allocator_type&, _Tp* __p) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _VSTD::destroy_at(__p); #else __p->~_Tp(); @@ -401,6 +401,25 @@ struct __is_cpp17_copy_insertable<_Alloc, __enable_if_t< : __is_cpp17_move_insertable<_Alloc> { }; +// ASan choices +#ifndef _LIBCPP_HAS_NO_ASAN +# define _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS 1 +#endif + +#ifdef _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS +template <class _Alloc> +struct __asan_annotate_container_with_allocator +# if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1600 + : true_type {}; +# else + // TODO(LLVM-18): Remove the special-casing + : false_type {}; +# endif + +template <class _Tp> +struct __asan_annotate_container_with_allocator<allocator<_Tp> > : true_type {}; +#endif + #undef _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__memory/assume_aligned.h b/libcxx/include/__memory/assume_aligned.h index a1fd2441f9a9..00c2928dcce0 100644 --- a/libcxx/include/__memory/assume_aligned.h +++ b/libcxx/include/__memory/assume_aligned.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <size_t _Np, class _Tp> [[nodiscard]] @@ -34,12 +34,12 @@ constexpr _Tp* assume_aligned(_Tp* __ptr) { if (is_constant_evaluated()) { return __ptr; } else { - _LIBCPP_ASSERT(reinterpret_cast<uintptr_t>(__ptr) % _Np == 0, "Alignment assumption is violated"); + _LIBCPP_ASSERT_UNCATEGORIZED(reinterpret_cast<uintptr_t>(__ptr) % _Np == 0, "Alignment assumption is violated"); return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Np)); } } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__memory/builtin_new_allocator.h b/libcxx/include/__memory/builtin_new_allocator.h index cd1a866ca615..ab449ad29987 100644 --- a/libcxx/include/__memory/builtin_new_allocator.h +++ b/libcxx/include/__memory/builtin_new_allocator.h @@ -28,10 +28,10 @@ struct __builtin_new_allocator { struct __builtin_new_deleter { typedef void* pointer_type; - _LIBCPP_CONSTEXPR explicit __builtin_new_deleter(size_t __size, size_t __align) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __builtin_new_deleter(size_t __size, size_t __align) : __size_(__size), __align_(__align) {} - void operator()(void* __p) const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI void operator()(void* __p) const _NOEXCEPT { _VSTD::__libcpp_deallocate(__p, __size_, __align_); } @@ -42,25 +42,25 @@ struct __builtin_new_allocator { typedef unique_ptr<void, __builtin_new_deleter> __holder_t; - static __holder_t __allocate_bytes(size_t __s, size_t __align) { + _LIBCPP_HIDE_FROM_ABI static __holder_t __allocate_bytes(size_t __s, size_t __align) { return __holder_t(_VSTD::__libcpp_allocate(__s, __align), __builtin_new_deleter(__s, __align)); } - static void __deallocate_bytes(void* __p, size_t __s, + _LIBCPP_HIDE_FROM_ABI static void __deallocate_bytes(void* __p, size_t __s, size_t __align) _NOEXCEPT { _VSTD::__libcpp_deallocate(__p, __s, __align); } template <class _Tp> _LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE - static __holder_t __allocate_type(size_t __n) { + _LIBCPP_HIDE_FROM_ABI static __holder_t __allocate_type(size_t __n) { return __allocate_bytes(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); } template <class _Tp> _LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE - static void __deallocate_type(void* __p, size_t __n) _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI static void __deallocate_type(void* __p, size_t __n) _NOEXCEPT { __deallocate_bytes(__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); } }; diff --git a/libcxx/include/__memory/compressed_pair.h b/libcxx/include/__memory/compressed_pair.h index 8093d7c93156..f24b2bac5664 100644 --- a/libcxx/include/__memory/compressed_pair.h +++ b/libcxx/include/__memory/compressed_pair.h @@ -13,7 +13,7 @@ #include <__config> #include <__fwd/get.h> #include <__fwd/tuple.h> -#include <__tuple_dir/tuple_indices.h> +#include <__tuple/tuple_indices.h> #include <__type_traits/decay.h> #include <__type_traits/dependent_type.h> #include <__type_traits/enable_if.h> @@ -31,6 +31,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // Tag used to default initialize one or both of the pair's elements. @@ -46,7 +49,7 @@ struct __compressed_pair_elem { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__default_init_tag) {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__value_init_tag) : __value_() {} - template <class _Up, class = __enable_if_t<!is_same<__compressed_pair_elem, typename decay<_Up>::type>::value> > + template <class _Up, class = __enable_if_t<!is_same<__compressed_pair_elem, __decay_t<_Up> >::value> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(_Up&& __u) : __value_(std::forward<_Up>(__u)) {} @@ -75,7 +78,7 @@ struct __compressed_pair_elem<_Tp, _Idx, true> : private _Tp { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__default_init_tag) {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(__value_init_tag) : __value_type() {} - template <class _Up, class = __enable_if_t<!is_same<__compressed_pair_elem, typename decay<_Up>::type>::value> > + template <class _Up, class = __enable_if_t<!is_same<__compressed_pair_elem, __decay_t<_Up> >::value> > _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair_elem(_Up&& __u) : __value_type(std::forward<_Up>(__u)) {} @@ -174,4 +177,6 @@ void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_COMPRESSED_PAIR_H diff --git a/libcxx/include/__memory/concepts.h b/libcxx/include/__memory/concepts.h index 12d7bf85ed94..97cc3583ec96 100644 --- a/libcxx/include/__memory/concepts.h +++ b/libcxx/include/__memory/concepts.h @@ -19,6 +19,7 @@ #include <__ranges/concepts.h> #include <__type_traits/is_reference.h> #include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> // TODO(modules): This should not be required #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -62,7 +63,7 @@ concept __nothrow_forward_range = } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__memory/construct_at.h b/libcxx/include/__memory/construct_at.h index ffee0022c243..a032c33b47a8 100644 --- a/libcxx/include/__memory/construct_at.h +++ b/libcxx/include/__memory/construct_at.h @@ -26,26 +26,29 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // construct_at -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp, class... _Args, class = decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))> _LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) { - _LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at"); - return ::new (_VSTD::__voidify(*__location)) _Tp(_VSTD::forward<_Args>(__args)...); + _LIBCPP_ASSERT_UNCATEGORIZED(__location != nullptr, "null pointer given to construct_at"); + return ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...); } #endif template <class _Tp, class... _Args, class = decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __construct_at(_Tp* __location, _Args&&... __args) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 return std::construct_at(__location, std::forward<_Args>(__args)...); #else - return _LIBCPP_ASSERT(__location != nullptr, "null pointer given to construct_at"), + return _LIBCPP_ASSERT_UNCATEGORIZED(__location != nullptr, "null pointer given to construct_at"), ::new (std::__voidify(*__location)) _Tp(std::forward<_Args>(__args)...); #endif } @@ -62,16 +65,16 @@ _ForwardIterator __destroy(_ForwardIterator, _ForwardIterator); template <class _Tp, typename enable_if<!is_array<_Tp>::value, int>::type = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy_at(_Tp* __loc) { - _LIBCPP_ASSERT(__loc != nullptr, "null pointer given to destroy_at"); + _LIBCPP_ASSERT_UNCATEGORIZED(__loc != nullptr, "null pointer given to destroy_at"); __loc->~_Tp(); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp, typename enable_if<is_array<_Tp>::value, int>::type = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __destroy_at(_Tp* __loc) { - _LIBCPP_ASSERT(__loc != nullptr, "null pointer given to destroy_at"); - _VSTD::__destroy(_VSTD::begin(*__loc), _VSTD::end(*__loc)); + _LIBCPP_ASSERT_UNCATEGORIZED(__loc != nullptr, "null pointer given to destroy_at"); + std::__destroy(std::begin(*__loc), std::end(*__loc)); } #endif @@ -79,42 +82,54 @@ template <class _ForwardIterator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator __destroy(_ForwardIterator __first, _ForwardIterator __last) { for (; __first != __last; ++__first) - _VSTD::__destroy_at(_VSTD::addressof(*__first)); + std::__destroy_at(std::addressof(*__first)); return __first; } -#if _LIBCPP_STD_VER > 14 +template <class _BidirectionalIterator> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +_BidirectionalIterator __reverse_destroy(_BidirectionalIterator __first, _BidirectionalIterator __last) { + while (__last != __first) { + --__last; + std::__destroy_at(std::addressof(*__last)); + } + return __last; +} + +#if _LIBCPP_STD_VER >= 17 template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* __loc) { - _VSTD::__destroy_at(__loc); + std::__destroy_at(__loc); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp, enable_if_t<is_array_v<_Tp>, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy_at(_Tp* __loc) { - _VSTD::__destroy_at(__loc); + std::__destroy_at(__loc); } #endif template <class _ForwardIterator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy(_ForwardIterator __first, _ForwardIterator __last) { - (void)_VSTD::__destroy(_VSTD::move(__first), _VSTD::move(__last)); + (void)std::__destroy(std::move(__first), std::move(__last)); } template <class _ForwardIterator, class _Size> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) { for (; __n > 0; (void)++__first, --__n) - _VSTD::__destroy_at(_VSTD::addressof(*__first)); + std::__destroy_at(std::addressof(*__first)); return __first; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_CONSTRUCT_AT_H diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h index c4f20def4540..c33e7bd43f29 100644 --- a/libcxx/include/__memory/pointer_traits.h +++ b/libcxx/include/__memory/pointer_traits.h @@ -200,7 +200,7 @@ template <class _Pointer, class = __enable_if_t< _And<is_class<_Pointer>, _IsFancyPointer<_Pointer> >::value > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR -typename decay<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))>::type +__decay_t<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))> __to_address(const _Pointer& __p) _NOEXCEPT { return __to_address_helper<_Pointer>::__call(__p); } @@ -223,7 +223,7 @@ struct __to_address_helper<_Pointer, decltype((void)pointer_traits<_Pointer>::to } }; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY constexpr auto to_address(_Tp *__p) noexcept { diff --git a/libcxx/include/__memory/ranges_construct_at.h b/libcxx/include/__memory/ranges_construct_at.h index e63585d1ab63..ed800f4a75b4 100644 --- a/libcxx/include/__memory/ranges_construct_at.h +++ b/libcxx/include/__memory/ranges_construct_at.h @@ -13,7 +13,7 @@ #include <__concepts/destructible.h> #include <__config> #include <__iterator/incrementable_traits.h> -#include <__iterator/readable_traits.h> +#include <__iterator/iterator_traits.h> #include <__memory/concepts.h> #include <__memory/construct_at.h> #include <__ranges/access.h> @@ -28,9 +28,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { // construct_at @@ -118,8 +121,10 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_RANGES_CONSTRUCT_AT_H diff --git a/libcxx/include/__memory/ranges_uninitialized_algorithms.h b/libcxx/include/__memory/ranges_uninitialized_algorithms.h index 15c78e20bafb..01c3e01003d4 100644 --- a/libcxx/include/__memory/ranges_uninitialized_algorithms.h +++ b/libcxx/include/__memory/ranges_uninitialized_algorithms.h @@ -33,7 +33,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -45,7 +45,7 @@ struct __fn { template <__nothrow_forward_iterator _ForwardIterator, __nothrow_sentinel_for<_ForwardIterator> _Sentinel> requires default_initializable<iter_value_t<_ForwardIterator>> - _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const { + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const { using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>; return _VSTD::__uninitialized_default_construct<_ValueType>( _VSTD::move(__first), _VSTD::move(__last)); @@ -53,7 +53,7 @@ struct __fn { template <__nothrow_forward_range _ForwardRange> requires default_initializable<range_value_t<_ForwardRange>> - borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const { + _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const { return (*this)(ranges::begin(__range), ranges::end(__range)); } }; @@ -71,7 +71,7 @@ namespace __uninitialized_default_construct_n { struct __fn { template <__nothrow_forward_iterator _ForwardIterator> requires default_initializable<iter_value_t<_ForwardIterator>> - _ForwardIterator operator()(_ForwardIterator __first, + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, iter_difference_t<_ForwardIterator> __n) const { using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>; return _VSTD::__uninitialized_default_construct_n<_ValueType>(_VSTD::move(__first), __n); @@ -92,7 +92,7 @@ struct __fn { template <__nothrow_forward_iterator _ForwardIterator, __nothrow_sentinel_for<_ForwardIterator> _Sentinel> requires default_initializable<iter_value_t<_ForwardIterator>> - _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const { + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const { using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>; return _VSTD::__uninitialized_value_construct<_ValueType>( _VSTD::move(__first), _VSTD::move(__last)); @@ -100,7 +100,7 @@ struct __fn { template <__nothrow_forward_range _ForwardRange> requires default_initializable<range_value_t<_ForwardRange>> - borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const { + _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const { return (*this)(ranges::begin(__range), ranges::end(__range)); } }; @@ -118,7 +118,7 @@ namespace __uninitialized_value_construct_n { struct __fn { template <__nothrow_forward_iterator _ForwardIterator> requires default_initializable<iter_value_t<_ForwardIterator>> - _ForwardIterator operator()(_ForwardIterator __first, + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, iter_difference_t<_ForwardIterator> __n) const { using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>; return _VSTD::__uninitialized_value_construct_n<_ValueType>(_VSTD::move(__first), __n); @@ -140,14 +140,14 @@ struct __fn { __nothrow_sentinel_for<_ForwardIterator> _Sentinel, class _Tp> requires constructible_from<iter_value_t<_ForwardIterator>, const _Tp&> - _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) const { + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) const { using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>; return _VSTD::__uninitialized_fill<_ValueType>(_VSTD::move(__first), _VSTD::move(__last), __x); } template <__nothrow_forward_range _ForwardRange, class _Tp> requires constructible_from<range_value_t<_ForwardRange>, const _Tp&> - borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range, const _Tp& __x) const { + _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range, const _Tp& __x) const { return (*this)(ranges::begin(__range), ranges::end(__range), __x); } }; @@ -165,7 +165,7 @@ namespace __uninitialized_fill_n { struct __fn { template <__nothrow_forward_iterator _ForwardIterator, class _Tp> requires constructible_from<iter_value_t<_ForwardIterator>, const _Tp&> - _ForwardIterator operator()(_ForwardIterator __first, + _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, iter_difference_t<_ForwardIterator> __n, const _Tp& __x) const { using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>; @@ -192,7 +192,7 @@ struct __fn { __nothrow_forward_iterator _OutputIterator, __nothrow_sentinel_for<_OutputIterator> _Sentinel2> requires constructible_from<iter_value_t<_OutputIterator>, iter_reference_t<_InputIterator>> - uninitialized_copy_result<_InputIterator, _OutputIterator> + _LIBCPP_HIDE_FROM_ABI uninitialized_copy_result<_InputIterator, _OutputIterator> operator()(_InputIterator __ifirst, _Sentinel1 __ilast, _OutputIterator __ofirst, _Sentinel2 __olast) const { using _ValueType = remove_reference_t<iter_reference_t<_OutputIterator>>; @@ -203,7 +203,7 @@ struct __fn { template <input_range _InputRange, __nothrow_forward_range _OutputRange> requires constructible_from<range_value_t<_OutputRange>, range_reference_t<_InputRange>> - uninitialized_copy_result<borrowed_iterator_t<_InputRange>, borrowed_iterator_t<_OutputRange>> + _LIBCPP_HIDE_FROM_ABI uninitialized_copy_result<borrowed_iterator_t<_InputRange>, borrowed_iterator_t<_OutputRange>> operator()( _InputRange&& __in_range, _OutputRange&& __out_range) const { return (*this)(ranges::begin(__in_range), ranges::end(__in_range), ranges::begin(__out_range), ranges::end(__out_range)); @@ -228,7 +228,7 @@ struct __fn { __nothrow_forward_iterator _OutputIterator, __nothrow_sentinel_for<_OutputIterator> _Sentinel> requires constructible_from<iter_value_t<_OutputIterator>, iter_reference_t<_InputIterator>> - uninitialized_copy_n_result<_InputIterator, _OutputIterator> + _LIBCPP_HIDE_FROM_ABI uninitialized_copy_n_result<_InputIterator, _OutputIterator> operator()(_InputIterator __ifirst, iter_difference_t<_InputIterator> __n, _OutputIterator __ofirst, _Sentinel __olast) const { using _ValueType = remove_reference_t<iter_reference_t<_OutputIterator>>; @@ -257,7 +257,7 @@ struct __fn { __nothrow_forward_iterator _OutputIterator, __nothrow_sentinel_for<_OutputIterator> _Sentinel2> requires constructible_from<iter_value_t<_OutputIterator>, iter_rvalue_reference_t<_InputIterator>> - uninitialized_move_result<_InputIterator, _OutputIterator> + _LIBCPP_HIDE_FROM_ABI uninitialized_move_result<_InputIterator, _OutputIterator> operator()(_InputIterator __ifirst, _Sentinel1 __ilast, _OutputIterator __ofirst, _Sentinel2 __olast) const { using _ValueType = remove_reference_t<iter_reference_t<_OutputIterator>>; auto __iter_move = [](auto&& __iter) -> decltype(auto) { return ranges::iter_move(__iter); }; @@ -268,7 +268,7 @@ struct __fn { template <input_range _InputRange, __nothrow_forward_range _OutputRange> requires constructible_from<range_value_t<_OutputRange>, range_rvalue_reference_t<_InputRange>> - uninitialized_move_result<borrowed_iterator_t<_InputRange>, borrowed_iterator_t<_OutputRange>> + _LIBCPP_HIDE_FROM_ABI uninitialized_move_result<borrowed_iterator_t<_InputRange>, borrowed_iterator_t<_OutputRange>> operator()(_InputRange&& __in_range, _OutputRange&& __out_range) const { return (*this)(ranges::begin(__in_range), ranges::end(__in_range), ranges::begin(__out_range), ranges::end(__out_range)); @@ -293,7 +293,7 @@ struct __fn { __nothrow_forward_iterator _OutputIterator, __nothrow_sentinel_for<_OutputIterator> _Sentinel> requires constructible_from<iter_value_t<_OutputIterator>, iter_rvalue_reference_t<_InputIterator>> - uninitialized_move_n_result<_InputIterator, _OutputIterator> + _LIBCPP_HIDE_FROM_ABI uninitialized_move_n_result<_InputIterator, _OutputIterator> operator()(_InputIterator __ifirst, iter_difference_t<_InputIterator> __n, _OutputIterator __ofirst, _Sentinel __olast) const { using _ValueType = remove_reference_t<iter_reference_t<_OutputIterator>>; @@ -312,7 +312,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__memory/raw_storage_iterator.h b/libcxx/include/__memory/raw_storage_iterator.h index 11971de0fa47..df7ef5afe7d4 100644 --- a/libcxx/include/__memory/raw_storage_iterator.h +++ b/libcxx/include/__memory/raw_storage_iterator.h @@ -39,7 +39,7 @@ private: public: typedef output_iterator_tag iterator_category; typedef void value_type; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef ptrdiff_t difference_type; #else typedef void difference_type; diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index b77ce9230bff..dce44a7b3732 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -29,17 +29,32 @@ #include <__memory/pointer_traits.h> #include <__memory/uninitialized_algorithms.h> #include <__memory/unique_ptr.h> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/conditional.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/disjunction.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_bounded_array.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_unbounded_array.h> +#include <__type_traits/nat.h> +#include <__type_traits/negation.h> +#include <__type_traits/remove_extent.h> +#include <__type_traits/remove_reference.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> +#include <__verbose_abort> #include <cstddef> -#include <cstdlib> // abort #include <iosfwd> #include <new> #include <stdexcept> #include <typeinfo> #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) -# include <atomic> +# include <__atomic/memory_order.h> #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -105,12 +120,12 @@ __libcpp_atomic_refcount_decrement(_Tp& __t) _NOEXCEPT #endif } -class _LIBCPP_EXCEPTION_ABI bad_weak_ptr +class _LIBCPP_EXPORTED_FROM_ABI bad_weak_ptr : public std::exception { public: - bad_weak_ptr() _NOEXCEPT = default; - bad_weak_ptr(const bad_weak_ptr&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI bad_weak_ptr() _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI bad_weak_ptr(const bad_weak_ptr&) _NOEXCEPT = default; ~bad_weak_ptr() _NOEXCEPT override; const char* what() const _NOEXCEPT override; }; @@ -118,16 +133,16 @@ public: _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_weak_ptr() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_weak_ptr(); #else - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("bad_weak_ptr was thrown in -fno-exceptions mode"); #endif } template<class _Tp> class _LIBCPP_TEMPLATE_VIS weak_ptr; -class _LIBCPP_TYPE_VIS __shared_count +class _LIBCPP_EXPORTED_FROM_ABI __shared_count { __shared_count(const __shared_count&); __shared_count& operator=(const __shared_count&); @@ -166,7 +181,7 @@ public: } }; -class _LIBCPP_TYPE_VIS __shared_weak_count +class _LIBCPP_EXPORTED_FROM_ABI __shared_weak_count : private __shared_count { long __shared_weak_owners_; @@ -219,16 +234,16 @@ public: __shared_ptr_pointer(_Tp __p, _Dp __d, _Alloc __a) : __data_(__compressed_pair<_Tp, _Dp>(__p, _VSTD::move(__d)), _VSTD::move(__a)) {} -#ifndef _LIBCPP_NO_RTTI - const void* __get_deleter(const type_info&) const _NOEXCEPT override; +#ifndef _LIBCPP_HAS_NO_RTTI + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const void* __get_deleter(const type_info&) const _NOEXCEPT override; #endif private: - void __on_zero_shared() _NOEXCEPT override; - void __on_zero_shared_weak() _NOEXCEPT override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override; }; -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template <class _Tp, class _Dp, class _Alloc> const void* @@ -237,7 +252,7 @@ __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__get_deleter(const type_info& __t) cons return __t == typeid(_Dp) ? _VSTD::addressof(__data_.first().second()) : nullptr; } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template <class _Tp, class _Dp, class _Alloc> void @@ -260,7 +275,10 @@ __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT __a.deallocate(_PTraits::pointer_to(*this), 1); } -struct __default_initialize_tag {}; +// This tag is used to instantiate an allocator type. The various shared_ptr control blocks +// detect that the allocator has been instantiated for this type and perform alternative +// initialization/destruction based on that. +struct __for_overwrite_tag {}; template <class _Tp, class _Alloc> struct __shared_ptr_emplace @@ -271,25 +289,20 @@ struct __shared_ptr_emplace explicit __shared_ptr_emplace(_Alloc __a, _Args&& ...__args) : __storage_(_VSTD::move(__a)) { -#if _LIBCPP_STD_VER > 17 - using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; - _TpAlloc __tmp(*__get_alloc()); - allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...); +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + static_assert(sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite"); + ::new ((void*)__get_elem()) _Tp; + } else { + using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; + _TpAlloc __tmp(*__get_alloc()); + allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...); + } #else ::new ((void*)__get_elem()) _Tp(_VSTD::forward<_Args>(__args)...); #endif } - -#if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI - explicit __shared_ptr_emplace(__default_initialize_tag, _Alloc __a) - : __storage_(std::move(__a)) - { - ::new ((void*)__get_elem()) _Tp; - } -#endif - _LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT { return __storage_.__get_alloc(); } @@ -297,17 +310,21 @@ struct __shared_ptr_emplace _Tp* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); } private: - void __on_zero_shared() _NOEXCEPT override { -#if _LIBCPP_STD_VER > 17 - using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; - _TpAlloc __tmp(*__get_alloc()); - allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + __get_elem()->~_Tp(); + } else { + using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type; + _TpAlloc __tmp(*__get_alloc()); + allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); + } #else __get_elem()->~_Tp(); #endif } - void __on_zero_shared_weak() _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override { using _ControlBlockAlloc = typename __allocator_traits_rebind<_Alloc, __shared_ptr_emplace>::type; using _ControlBlockPointer = typename allocator_traits<_ControlBlockAlloc>::pointer; _ControlBlockAlloc __tmp(*__get_alloc()); @@ -334,13 +351,13 @@ private: _LIBCPP_HIDE_FROM_ABI ~_Storage() { __get_alloc()->~_Alloc(); } - _Alloc* __get_alloc() _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT { _CompressedPair *__as_pair = reinterpret_cast<_CompressedPair*>(__blob_); typename _CompressedPair::_Base1* __first = _CompressedPair::__get_first_base(__as_pair); _Alloc *__alloc = reinterpret_cast<_Alloc*>(__first); return __alloc; } - _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT { _CompressedPair *__as_pair = reinterpret_cast<_CompressedPair*>(__blob_); typename _CompressedPair::_Base2* __second = _CompressedPair::__get_second_base(__as_pair); _Tp *__elem = reinterpret_cast<_Tp*>(__second); @@ -367,13 +384,57 @@ public: template<class _Tp> class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; -template<class _Tp, class _Up> +// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.general-6 +// A pointer type Y* is said to be compatible with a pointer type T* +// when either Y* is convertible to T* or Y is U[N] and T is cv U[]. +#if _LIBCPP_STD_VER >= 17 +template <class _Yp, class _Tp> +struct __bounded_convertible_to_unbounded : false_type {}; + +template <class _Up, std::size_t _Np, class _Tp> +struct __bounded_convertible_to_unbounded<_Up[_Np], _Tp> + : is_same<__remove_cv_t<_Tp>, _Up[]> {}; + +template <class _Yp, class _Tp> +struct __compatible_with + : _Or< + is_convertible<_Yp*, _Tp*>, + __bounded_convertible_to_unbounded<_Yp, _Tp> + > {}; +#else +template <class _Yp, class _Tp> struct __compatible_with -#if _LIBCPP_STD_VER > 14 - : is_convertible<remove_extent_t<_Tp>*, remove_extent_t<_Up>*> {}; + : is_convertible<_Yp*, _Tp*> {}; +#endif // _LIBCPP_STD_VER >= 17 + +// Constructors that take raw pointers have a different set of "compatible" constraints +// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.const-9.1 +// - If T is an array type, then either T is U[N] and Y(*)[N] is convertible to T*, +// or T is U[] and Y(*)[] is convertible to T*. +// - If T is not an array type, then Y* is convertible to T*. +#if _LIBCPP_STD_VER >= 17 +template <class _Yp, class _Tp, class = void> +struct __raw_pointer_compatible_with : _And< + _Not<is_array<_Tp>>, + is_convertible<_Yp*, _Tp*> + > {}; + +template <class _Yp, class _Up, std::size_t _Np> +struct __raw_pointer_compatible_with<_Yp, _Up[_Np], __enable_if_t< + is_convertible<_Yp(*)[_Np], _Up(*)[_Np]>::value> > + : true_type {}; + +template <class _Yp, class _Up> +struct __raw_pointer_compatible_with<_Yp, _Up[], __enable_if_t< + is_convertible<_Yp(*)[], _Up(*)[]>::value> > + : true_type {}; + #else - : is_convertible<_Tp*, _Up*> {}; -#endif // _LIBCPP_STD_VER > 14 +template <class _Yp, class _Tp> +struct __raw_pointer_compatible_with + : is_convertible<_Yp*, _Tp*> {}; +#endif // _LIBCPP_STD_VER >= 17 + template <class _Ptr, class = void> struct __is_deletable : false_type { }; @@ -387,24 +448,24 @@ struct __is_array_deletable<_Ptr, decltype(delete[] std::declval<_Ptr>())> : tru template <class _Dp, class _Pt, class = decltype(std::declval<_Dp>()(std::declval<_Pt>()))> -static true_type __well_formed_deleter_test(int); +true_type __well_formed_deleter_test(int); template <class, class> -static false_type __well_formed_deleter_test(...); +false_type __well_formed_deleter_test(...); template <class _Dp, class _Pt> struct __well_formed_deleter : decltype(std::__well_formed_deleter_test<_Dp, _Pt>(0)) {}; -template<class _Dp, class _Tp, class _Yp> +template<class _Dp, class _Yp, class _Tp> struct __shared_ptr_deleter_ctor_reqs { - static const bool value = __compatible_with<_Tp, _Yp>::value && + static const bool value = __raw_pointer_compatible_with<_Yp, _Tp>::value && is_move_constructible<_Dp>::value && - __well_formed_deleter<_Dp, _Tp*>::value; + __well_formed_deleter<_Dp, _Yp*>::value; }; #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) -# define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) +# define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__)) #else # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI #endif @@ -413,7 +474,7 @@ template<class _Tp> class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr { public: -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef weak_ptr<_Tp> weak_type; typedef remove_extent_t<_Tp> element_type; #else @@ -439,7 +500,7 @@ public: template<class _Yp, class = __enable_if_t< _And< - __compatible_with<_Yp, _Tp> + __raw_pointer_compatible_with<_Yp, _Tp> // In C++03 we get errors when trying to do SFINAE with the // delete operator, so we always pretend that it's deletable. // The same happens on GCC. @@ -448,7 +509,7 @@ public: #endif >::value > > - explicit shared_ptr(_Yp* __p) : __ptr_(__p) { + _LIBCPP_HIDE_FROM_ABI explicit shared_ptr(_Yp* __p) : __ptr_(__p) { unique_ptr<_Yp> __hold(__p); typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT> _CntrlBlk; @@ -457,15 +518,15 @@ public: __enable_weak_this(__p, __p); } - template<class _Yp, class _Dp, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value> > + template<class _Yp, class _Dp, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr(_Yp* __p, _Dp __d) : __ptr_(__p) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT> _CntrlBlk; #ifndef _LIBCPP_CXX03_LANG @@ -474,25 +535,25 @@ public: __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); #endif // not _LIBCPP_CXX03_LANG __enable_weak_this(__p, __p); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __d(__p); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } - template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value> > + template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr(_Yp* __p, _Dp __d, _Alloc __a) : __ptr_(__p) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef __shared_ptr_pointer<_Yp*, _Dp, _Alloc> _CntrlBlk; typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2; typedef __allocator_destructor<_A2> _D2; @@ -506,14 +567,14 @@ public: #endif // not _LIBCPP_CXX03_LANG __cntrl_ = _VSTD::addressof(*__hold2.release()); __enable_weak_this(__p, __p); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __d(__p); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template<class _Dp> @@ -521,10 +582,10 @@ public: shared_ptr(nullptr_t __p, _Dp __d) : __ptr_(nullptr) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT; typedef __shared_ptr_pointer<nullptr_t, _Dp, _AllocT> _CntrlBlk; #ifndef _LIBCPP_CXX03_LANG @@ -532,14 +593,14 @@ public: #else __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); #endif // not _LIBCPP_CXX03_LANG -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __d(__p); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template<class _Dp, class _Alloc> @@ -547,10 +608,10 @@ public: shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a) : __ptr_(nullptr) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef __shared_ptr_pointer<nullptr_t, _Dp, _Alloc> _CntrlBlk; typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2; typedef __allocator_destructor<_A2> _D2; @@ -563,14 +624,14 @@ public: _CntrlBlk(__p, __d, __a); #endif // not _LIBCPP_CXX03_LANG __cntrl_ = _VSTD::addressof(*__hold2.release()); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __d(__p); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template<class _Yp> @@ -583,6 +644,18 @@ public: __cntrl_->__add_shared(); } +// LWG-2996 +// We don't backport because it is an evolutionary change. +#if _LIBCPP_STD_VER >= 20 + template <class _Yp> + _LIBCPP_HIDE_FROM_ABI shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept + : __ptr_(__p), + __cntrl_(__r.__cntrl_) { + __r.__ptr_ = nullptr; + __r.__cntrl_ = nullptr; + } +#endif + _LIBCPP_HIDE_FROM_ABI shared_ptr(const shared_ptr& __r) _NOEXCEPT : __ptr_(__r.__ptr_), @@ -646,13 +719,14 @@ public: template <class _Yp, class _Dp, class = __enable_if_t< !is_lvalue_reference<_Dp>::value && + __compatible_with<_Yp, _Tp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value > > _LIBCPP_HIDE_FROM_ABI shared_ptr(unique_ptr<_Yp, _Dp>&& __r) : __ptr_(__r.get()) { -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 if (__ptr_ == nullptr) __cntrl_ = nullptr; else @@ -668,13 +742,14 @@ public: template <class _Yp, class _Dp, class = void, class = __enable_if_t< is_lvalue_reference<_Dp>::value && + __compatible_with<_Yp, _Tp>::value && is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value > > _LIBCPP_HIDE_FROM_ABI shared_ptr(unique_ptr<_Yp, _Dp>&& __r) : __ptr_(__r.get()) { -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 if (__ptr_ == nullptr) __cntrl_ = nullptr; else @@ -740,9 +815,10 @@ public: } #endif - template <class _Yp, class _Dp, class = __enable_if_t< - is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value - > > + template <class _Yp, class _Dp, class = __enable_if_t<_And< + __compatible_with<_Yp, _Tp>, + is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*> + >::value> > _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>& operator=(unique_ptr<_Yp, _Dp>&& __r) { @@ -764,7 +840,7 @@ public: } template<class _Yp, class = __enable_if_t< - __compatible_with<_Yp, _Tp>::value + __raw_pointer_compatible_with<_Yp, _Tp>::value > > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p) @@ -773,8 +849,7 @@ public: } template<class _Yp, class _Dp, class = __enable_if_t< - __compatible_with<_Yp, _Tp>::value - > > + __shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p, _Dp __d) { @@ -782,8 +857,7 @@ public: } template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t< - __compatible_with<_Yp, _Tp>::value - > > + __shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> > _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p, _Dp __d, _Alloc __a) { @@ -848,7 +922,7 @@ public: return __cntrl_ == __p.__cntrl_; } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t<element_type> operator[](ptrdiff_t __i) const { @@ -858,7 +932,7 @@ public: } #endif -#ifndef _LIBCPP_NO_RTTI +#ifndef _LIBCPP_HAS_NO_RTTI template <class _Dp> _LIBCPP_HIDE_FROM_ABI _Dp* __get_deleter() const _NOEXCEPT @@ -867,7 +941,7 @@ public: ? const_cast<void *>(__cntrl_->__get_deleter(typeid(_Dp))) : nullptr); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template<class _Yp, class _CntrlBlk> _LIBCPP_HIDE_FROM_ABI @@ -928,7 +1002,7 @@ private: template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr; }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template<class _Tp> shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>; template<class _Tp, class _Dp> @@ -963,12 +1037,9 @@ template<class _Tp, class _Alloc, __enable_if_t<!is_array<_Tp>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) { - using _ControlBlock = __shared_ptr_emplace<_Tp, _Alloc>; - using _ControlBlockAllocator = typename __allocator_traits_rebind<_Alloc, _ControlBlock>::type; - __allocation_guard<_ControlBlockAllocator> __guard(__a, 1); - ::new ((void*)_VSTD::addressof(*__guard.__get())) _ControlBlock(__default_initialize_tag{}, __a); - auto __control_block = __guard.__release_ptr(); - return shared_ptr<_Tp>::__create_with_control_block((*__control_block).__get_elem(), _VSTD::addressof(*__control_block)); + using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; + _ForOverwriteAllocator __alloc(__a); + return std::allocate_shared<_Tp>(__alloc); } template<class _Tp, __enable_if_t<!is_array<_Tp>::value, int> = 0> @@ -980,7 +1051,7 @@ shared_ptr<_Tp> make_shared_for_overwrite() #endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <size_t _Alignment> struct __sp_aligned_storage { @@ -1000,26 +1071,25 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count, _Tp const& __arg) : __alloc_(__alloc), __count_(__count) { - std::__uninitialized_allocator_fill_n(__alloc_, std::begin(__data_), __count_, __arg); + std::__uninitialized_allocator_fill_n_multidimensional(__alloc_, std::begin(__data_), __count_, __arg); } _LIBCPP_HIDE_FROM_ABI explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count) : __alloc_(__alloc), __count_(__count) { - std::__uninitialized_allocator_value_construct_n(__alloc_, std::begin(__data_), __count_); - } - #if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI - explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count, __default_initialize_tag) - : __alloc_(__alloc), __count_(__count) - { - // We are purposefully not using an allocator-aware default construction because the spec says so. - // There's currently no way of expressing default initialization in an allocator-aware manner anyway. - std::uninitialized_default_construct_n(std::begin(__data_), __count_); - } + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + // We are purposefully not using an allocator-aware default construction because the spec says so. + // There's currently no way of expressing default initialization in an allocator-aware manner anyway. + std::uninitialized_default_construct_n(std::begin(__data_), __count_); + } else { + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::begin(__data_), __count_); + } +#else + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::begin(__data_), __count_); #endif + } // Returns the number of bytes required to store a control block followed by the given number // of elements of _Tp, with the whole storage being aligned to a multiple of _Tp's alignment. @@ -1041,12 +1111,21 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count ~__unbounded_array_control_block() override { } // can't be `= default` because of the sometimes-non-trivial union member __data_ private: - void __on_zero_shared() _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + std::__reverse_destroy(__data_, __data_ + __count_); + } else { + __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); + std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + __count_); + } +#else __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + __count_); +#endif } - void __on_zero_shared_weak() _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override { using _AlignedStorage = __sp_aligned_storage<alignof(__unbounded_array_control_block)>; using _StorageAlloc = __allocator_traits_rebind_t<_Alloc, _AlignedStorage>; using _PointerTraits = pointer_traits<typename allocator_traits<_StorageAlloc>::pointer>; @@ -1096,33 +1175,43 @@ struct __bounded_array_control_block<_Tp[_Count], _Alloc> _LIBCPP_HIDE_FROM_ABI explicit __bounded_array_control_block(_Alloc const& __alloc, _Tp const& __arg) : __alloc_(__alloc) { - std::__uninitialized_allocator_fill_n(__alloc_, std::addressof(__data_[0]), _Count, __arg); + std::__uninitialized_allocator_fill_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count, __arg); } _LIBCPP_HIDE_FROM_ABI explicit __bounded_array_control_block(_Alloc const& __alloc) : __alloc_(__alloc) { - std::__uninitialized_allocator_value_construct_n(__alloc_, std::addressof(__data_[0]), _Count); - } - #if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI - explicit __bounded_array_control_block(_Alloc const& __alloc, __default_initialize_tag) : __alloc_(__alloc) { - // We are purposefully not using an allocator-aware default construction because the spec says so. - // There's currently no way of expressing default initialization in an allocator-aware manner anyway. - std::uninitialized_default_construct_n(std::addressof(__data_[0]), _Count); - } + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + // We are purposefully not using an allocator-aware default construction because the spec says so. + // There's currently no way of expressing default initialization in an allocator-aware manner anyway. + std::uninitialized_default_construct_n(std::addressof(__data_[0]), _Count); + } else { + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count); + } +#else + std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count); #endif + } _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~__bounded_array_control_block() override { } // can't be `= default` because of the sometimes-non-trivial union member __data_ private: - void __on_zero_shared() _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { +#if _LIBCPP_STD_VER >= 20 + if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { + std::__reverse_destroy(__data_, __data_ + _Count); + } else { + __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); + std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + _Count); + } +#else __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + _Count); +#endif } - void __on_zero_shared_weak() _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override { using _ControlBlockAlloc = __allocator_traits_rebind_t<_Alloc, __bounded_array_control_block>; using _PointerTraits = pointer_traits<typename allocator_traits<_ControlBlockAlloc>::pointer>; @@ -1152,9 +1241,9 @@ shared_ptr<_Array> __allocate_shared_bounded_array(const _Alloc& __a, _Arg&& ... return shared_ptr<_Array>::__create_with_control_block(__control_block->__get_data(), __control_block); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // bounded array variants template<class _Tp, class _Alloc, class = __enable_if_t<is_bounded_array<_Tp>::value>> @@ -1175,7 +1264,9 @@ template<class _Tp, class _Alloc, __enable_if_t<is_bounded_array<_Tp>::value, in _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) { - return std::__allocate_shared_bounded_array<_Tp>(__a, __default_initialize_tag{}); + using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; + _ForOverwriteAllocator __alloc(__a); + return std::__allocate_shared_bounded_array<_Tp>(__alloc); } template<class _Tp, class = __enable_if_t<is_bounded_array<_Tp>::value>> @@ -1196,7 +1287,7 @@ template<class _Tp, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite() { - return std::__allocate_shared_bounded_array<_Tp>(allocator<_Tp>(), __default_initialize_tag{}); + return std::__allocate_shared_bounded_array<_Tp>(allocator<__for_overwrite_tag>()); } // unbounded array variants @@ -1218,7 +1309,9 @@ template<class _Tp, class _Alloc, __enable_if_t<is_unbounded_array<_Tp>::value, _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a, size_t __n) { - return std::__allocate_shared_unbounded_array<_Tp>(__a, __n, __default_initialize_tag{}); + using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; + _ForOverwriteAllocator __alloc(__a); + return std::__allocate_shared_unbounded_array<_Tp>(__alloc, __n); } template<class _Tp, class = __enable_if_t<is_unbounded_array<_Tp>::value>> @@ -1239,10 +1332,10 @@ template<class _Tp, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite(size_t __n) { - return std::__allocate_shared_unbounded_array<_Tp>(allocator<_Tp>(), __n, __default_initialize_tag{}); + return std::__allocate_shared_unbounded_array<_Tp>(allocator<__for_overwrite_tag>(), __n); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template<class _Tp, class _Up> inline _LIBCPP_INLINE_VISIBILITY @@ -1302,7 +1395,7 @@ operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT #endif // _LIBCPP_STD_VER <= 17 -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class _Tp, class _Up> _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(shared_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) noexcept @@ -1411,7 +1504,7 @@ operator>=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT #endif // _LIBCPP_STD_VER <= 17 -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class _Tp> _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(shared_ptr<_Tp> const& __x, nullptr_t) noexcept @@ -1438,6 +1531,15 @@ static_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT typename shared_ptr<_Tp>::element_type*>(__r.get())); } +// LWG-2996 +// We don't backport because it is an evolutionary change. +#if _LIBCPP_STD_VER >= 20 +template <class _Tp, class _Up> +_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> static_pointer_cast(shared_ptr<_Up>&& __r) noexcept { + return shared_ptr<_Tp>(std::move(__r), static_cast<typename shared_ptr<_Tp>::element_type*>(__r.get())); +} +#endif + template<class _Tp, class _Up> inline _LIBCPP_INLINE_VISIBILITY shared_ptr<_Tp> @@ -1448,6 +1550,16 @@ dynamic_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT return __p ? shared_ptr<_Tp>(__r, __p) : shared_ptr<_Tp>(); } +// LWG-2996 +// We don't backport because it is an evolutionary change. +#if _LIBCPP_STD_VER >= 20 +template <class _Tp, class _Up> +_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept { + auto* __p = dynamic_cast<typename shared_ptr<_Tp>::element_type*>(__r.get()); + return __p ? shared_ptr<_Tp>(std::move(__r), __p) : shared_ptr<_Tp>(); +} +#endif + template<class _Tp, class _Up> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT @@ -1456,6 +1568,15 @@ const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT return shared_ptr<_Tp>(__r, const_cast<_RTp*>(__r.get())); } +// LWG-2996 +// We don't backport because it is an evolutionary change. +#if _LIBCPP_STD_VER >= 20 +template <class _Tp, class _Up> +_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(shared_ptr<_Up>&& __r) noexcept { + return shared_ptr<_Tp>(std::move(__r), const_cast<typename shared_ptr<_Tp>::element_type*>(__r.get())); +} +#endif + template<class _Tp, class _Up> _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT @@ -1465,7 +1586,16 @@ reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT typename shared_ptr<_Tp>::element_type*>(__r.get())); } -#ifndef _LIBCPP_NO_RTTI +// LWG-2996 +// We don't backport because it is an evolutionary change. +#if _LIBCPP_STD_VER >= 20 +template <class _Tp, class _Up> +_LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept { + return shared_ptr<_Tp>(std::move(__r), reinterpret_cast<typename shared_ptr<_Tp>::element_type*>(__r.get())); +} +#endif + +#ifndef _LIBCPP_HAS_NO_RTTI template<class _Dp, class _Tp> inline _LIBCPP_INLINE_VISIBILITY @@ -1475,13 +1605,13 @@ get_deleter(const shared_ptr<_Tp>& __p) _NOEXCEPT return __p.template __get_deleter<_Dp>(); } -#endif // _LIBCPP_NO_RTTI +#endif // _LIBCPP_HAS_NO_RTTI template<class _Tp> class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr { public: -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef remove_extent_t<_Tp> element_type; #else typedef _Tp element_type; @@ -1508,7 +1638,7 @@ public: template<class _Yp> _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr<_Yp>&& __r, typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat*>::type = 0) _NOEXCEPT; - ~weak_ptr(); + _LIBCPP_HIDE_FROM_ABI ~weak_ptr(); _LIBCPP_INLINE_VISIBILITY weak_ptr& operator=(weak_ptr const& __r) _NOEXCEPT; @@ -1552,7 +1682,7 @@ public: _LIBCPP_INLINE_VISIBILITY bool expired() const _NOEXCEPT {return __cntrl_ == nullptr || __cntrl_->use_count() == 0;} - shared_ptr<_Tp> lock() const _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> lock() const _NOEXCEPT; template<class _Up> _LIBCPP_INLINE_VISIBILITY bool owner_before(const shared_ptr<_Up>& __r) const _NOEXCEPT @@ -1566,7 +1696,7 @@ public: template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr; }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template<class _Tp> weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>; #endif @@ -1742,7 +1872,7 @@ weak_ptr<_Tp>::lock() const _NOEXCEPT return __r; } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp = void> struct owner_less; #else template <class _Tp> struct owner_less; @@ -1779,7 +1909,7 @@ struct _LIBCPP_TEMPLATE_VIS owner_less<weak_ptr<_Tp> > {return __x.owner_before(__y);} }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <> struct _LIBCPP_TEMPLATE_VIS owner_less<void> { @@ -1825,7 +1955,7 @@ public: shared_ptr<_Tp const> shared_from_this() const {return shared_ptr<const _Tp>(__weak_this_);} -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY weak_ptr<_Tp> weak_from_this() _NOEXCEPT { return __weak_this_; } @@ -1833,7 +1963,7 @@ public: _LIBCPP_INLINE_VISIBILITY weak_ptr<const _Tp> weak_from_this() const _NOEXCEPT { return __weak_this_; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 template <class _Up> friend class shared_ptr; }; @@ -1863,7 +1993,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, shared_ptr<_Yp> const& __p); #if !defined(_LIBCPP_HAS_NO_THREADS) -class _LIBCPP_TYPE_VIS __sp_mut +class _LIBCPP_EXPORTED_FROM_ABI __sp_mut { void* __lx_; public: @@ -1875,10 +2005,10 @@ private: __sp_mut(const __sp_mut&); __sp_mut& operator=(const __sp_mut&); - friend _LIBCPP_FUNC_VIS __sp_mut& __get_sp_mut(const void*); + friend _LIBCPP_EXPORTED_FROM_ABI __sp_mut& __get_sp_mut(const void*); }; -_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR +_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_ATOMIC_SHARED_PTR __sp_mut& __get_sp_mut(const void*); template <class _Tp> diff --git a/libcxx/include/__memory/swap_allocator.h b/libcxx/include/__memory/swap_allocator.h index c6e1751f4ddc..90851cb79cfc 100644 --- a/libcxx/include/__memory/swap_allocator.h +++ b/libcxx/include/__memory/swap_allocator.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <typename _Alloc> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __swap_allocator(_Alloc& __a1, _Alloc& __a2, true_type) -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) @@ -39,7 +39,7 @@ __swap_allocator(_Alloc&, _Alloc&, false_type) _NOEXCEPT {} template <typename _Alloc> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __swap_allocator(_Alloc& __a1, _Alloc& __a2) -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _NOEXCEPT #else _NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value) diff --git a/libcxx/include/__memory/temp_value.h b/libcxx/include/__memory/temp_value.h index 164688b15f81..3ce8b4bcbb37 100644 --- a/libcxx/include/__memory/temp_value.h +++ b/libcxx/include/__memory/temp_value.h @@ -32,7 +32,7 @@ struct __temp_value { #endif _Alloc &__a; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp *__addr() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp *__addr() { #ifdef _LIBCPP_CXX03_LANG return reinterpret_cast<_Tp*>(std::addressof(__v)); #else @@ -40,15 +40,15 @@ struct __temp_value { #endif } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp & get() { return *__addr(); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp & get() { return *__addr(); } template<class... _Args> - _LIBCPP_NO_CFI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_CONSTEXPR_SINCE_CXX20 __temp_value(_Alloc &__alloc, _Args&& ... __args) : __a(__alloc) { _Traits::construct(__a, __addr(), std::forward<_Args>(__args)...); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__temp_value() { _Traits::destroy(__a, __addr()); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__temp_value() { _Traits::destroy(__a, __addr()); } }; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h index 63a45b2ac87b..2b68df8e6d63 100644 --- a/libcxx/include/__memory/uninitialized_algorithms.h +++ b/libcxx/include/__memory/uninitialized_algorithms.h @@ -12,6 +12,8 @@ #include <__algorithm/copy.h> #include <__algorithm/move.h> +#include <__algorithm/unwrap_iter.h> +#include <__algorithm/unwrap_range.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> @@ -58,12 +60,12 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_copy(_InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _Sentinel2 __olast) { _ForwardIterator __idx = __ofirst; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __ifirst != __ilast && __idx != __olast; ++__ifirst, (void)++__idx) ::new (_VSTD::__voidify(*__idx)) _ValueType(*__ifirst); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__ofirst, __idx); throw; @@ -90,12 +92,12 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _Sentinel __olast) { _ForwardIterator __idx = __ofirst; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __n > 0 && __idx != __olast; ++__ifirst, (void)++__idx, (void)--__n) ::new (_VSTD::__voidify(*__idx)) _ValueType(*__ifirst); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__ofirst, __idx); throw; @@ -121,13 +123,13 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) { _ForwardIterator __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __idx != __last; ++__idx) ::new (_VSTD::__voidify(*__idx)) _ValueType(__x); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -154,13 +156,13 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) { _ForwardIterator __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __n > 0; ++__idx, (void) --__n) ::new (_VSTD::__voidify(*__idx)) _ValueType(__x); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -180,7 +182,7 @@ _ForwardIterator uninitialized_fill_n(_ForwardIterator __first, _Size __n, const return _VSTD::__uninitialized_fill_n<_ValueType>(__first, __n, __x); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 // uninitialized_default_construct @@ -188,12 +190,12 @@ template <class _ValueType, class _ForwardIterator, class _Sentinel> inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) { auto __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __idx != __last; ++__idx) ::new (_VSTD::__voidify(*__idx)) _ValueType; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__first, __idx); throw; @@ -217,12 +219,12 @@ template <class _ValueType, class _ForwardIterator, class _Size> inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) { auto __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __n > 0; ++__idx, (void) --__n) ::new (_VSTD::__voidify(*__idx)) _ValueType; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__first, __idx); throw; @@ -245,12 +247,12 @@ template <class _ValueType, class _ForwardIterator, class _Sentinel> inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) { auto __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __idx != __last; ++__idx) ::new (_VSTD::__voidify(*__idx)) _ValueType(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__first, __idx); throw; @@ -274,12 +276,12 @@ template <class _ValueType, class _ForwardIterator, class _Size> inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { auto __idx = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __n > 0; ++__idx, (void) --__n) ::new (_VSTD::__voidify(*__idx)) _ValueType(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__first, __idx); throw; @@ -304,13 +306,13 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move(_InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _Sentinel2 __olast, _IterMove __iter_move) { auto __idx = __ofirst; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __ifirst != __ilast && __idx != __olast; ++__idx, (void)++__ifirst) { ::new (_VSTD::__voidify(*__idx)) _ValueType(__iter_move(__ifirst)); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__ofirst, __idx); throw; @@ -338,12 +340,12 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _Sentinel __olast, _IterMove __iter_move) { auto __idx = __ofirst; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif for (; __n > 0 && __idx != __olast; ++__idx, (void)++__ifirst, --__n) ::new (_VSTD::__voidify(*__idx)) _ValueType(__iter_move(__ifirst)); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { _VSTD::__destroy(__ofirst, __idx); throw; @@ -371,7 +373,7 @@ uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofir // This function assumes that destructors do not throw, and that the allocator is bound to // the correct type. template<class _Alloc, class _BidirIter, class = __enable_if_t< - __is_cpp17_bidirectional_iterator<_BidirIter>::value + __has_bidirectional_iterator_category<_BidirIter>::value >> _LIBCPP_HIDE_FROM_ABI constexpr void __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter __first, _BidirIter __last) noexcept { @@ -410,7 +412,7 @@ constexpr void __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter // This function assumes that the allocator is bound to the correct type. template<class _Alloc, class _Tp> _LIBCPP_HIDE_FROM_ABI -constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) { +constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc) { static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>, "The allocator should already be rebound to the correct type"); @@ -421,12 +423,12 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) { _Tp& __array = *__loc; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __exception_guard __guard([&]() { + auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); }); for (; __i != extent_v<_Tp>; ++__i) { - std::__allocator_construct_at(__elem_alloc, std::addressof(__array[__i])); + std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i])); } __guard.__complete(); } else { @@ -446,13 +448,13 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) { // This function assumes that the allocator is bound to the correct type. template<class _Alloc, class _Tp, class _Arg> _LIBCPP_HIDE_FROM_ABI -constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) { +constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) { static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>, "The allocator should already be rebound to the correct type"); if constexpr (is_array_v<_Tp>) { static_assert(is_array_v<_Arg>, - "Provided non-array initialization argument to __allocator_construct_at when " + "Provided non-array initialization argument to __allocator_construct_at_multidimensional when " "trying to construct an array."); using _Element = remove_extent_t<_Tp>; @@ -461,11 +463,11 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const& _Tp& __array = *__loc; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __exception_guard __guard([&]() { + auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i); }); for (; __i != extent_v<_Tp>; ++__i) { - std::__allocator_construct_at(__elem_alloc, std::addressof(__array[__i]), __arg[__i]); + std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]), __arg[__i]); } __guard.__complete(); } else { @@ -481,38 +483,38 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const& // initialization using allocator_traits destruction. If the elements in the range are C-style // arrays, they are initialized element-wise using allocator construction, and recursively so. template<class _Alloc, class _BidirIter, class _Tp, class _Size = typename iterator_traits<_BidirIter>::difference_type> -_LIBCPP_HIDE_FROM_ABI -constexpr void __uninitialized_allocator_fill_n(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) { +_LIBCPP_HIDE_FROM_ABI constexpr void +__uninitialized_allocator_fill_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) { using _ValueType = typename iterator_traits<_BidirIter>::value_type; __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc); _BidirIter __begin = __it; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __exception_guard __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); + auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); for (; __n != 0; --__n, ++__it) { - std::__allocator_construct_at(__value_alloc, std::addressof(*__it), __value); + std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it), __value); } __guard.__complete(); } -// Same as __uninitialized_allocator_fill_n, but doesn't pass any initialization argument +// Same as __uninitialized_allocator_fill_n_multidimensional, but doesn't pass any initialization argument // to the allocator's construct method, which results in value initialization. -template<class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type> -_LIBCPP_HIDE_FROM_ABI -constexpr void __uninitialized_allocator_value_construct_n(_Alloc& __alloc, _BidirIter __it, _Size __n) { +template <class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type> +_LIBCPP_HIDE_FROM_ABI constexpr void +__uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n) { using _ValueType = typename iterator_traits<_BidirIter>::value_type; __allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc); _BidirIter __begin = __it; // If an exception is thrown, destroy what we have constructed so far in reverse order. - __exception_guard __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); + auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); }); for (; __n != 0; --__n, ++__it) { - std::__allocator_construct_at(__value_alloc, std::addressof(*__it)); + std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it)); } __guard.__complete(); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 // Destroy all elements in [__first, __last) from left to right using allocator destruction. template <class _Alloc, class _Iter, class _Sent> @@ -545,7 +547,7 @@ private: // already copied elements are destroyed in reverse order of their construction. template <class _Alloc, class _Iter1, class _Sent1, class _Iter2> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 -__uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { +__uninitialized_allocator_copy_impl(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { auto __destruct_first = __first2; auto __guard = std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); @@ -565,14 +567,16 @@ template <class _Type> struct __allocator_has_trivial_copy_construct<allocator<_Type>, _Type> : true_type {}; template <class _Alloc, - class _Type, - class _RawType = __remove_const_t<_Type>, + class _In, + class _RawTypeIn = __remove_const_t<_In>, + class _Out, __enable_if_t< - // using _RawType because of the allocator<T const> extension - is_trivially_copy_constructible<_RawType>::value && is_trivially_copy_assignable<_RawType>::value && - __allocator_has_trivial_copy_construct<_Alloc, _RawType>::value>* = nullptr> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Type* -__uninitialized_allocator_copy(_Alloc&, const _Type* __first1, const _Type* __last1, _Type* __first2) { + // using _RawTypeIn because of the allocator<T const> extension + is_trivially_copy_constructible<_RawTypeIn>::value && is_trivially_copy_assignable<_RawTypeIn>::value && + is_same<__remove_const_t<_In>, __remove_const_t<_Out> >::value && + __allocator_has_trivial_copy_construct<_Alloc, _RawTypeIn>::value>* = nullptr> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Out* +__uninitialized_allocator_copy_impl(_Alloc&, _In* __first1, _In* __last1, _Out* __first2) { // TODO: Remove the const_cast once we drop support for std::allocator<T const> if (__libcpp_is_constant_evaluated()) { while (__first1 != __last1) { @@ -582,10 +586,17 @@ __uninitialized_allocator_copy(_Alloc&, const _Type* __first1, const _Type* __la } return __first2; } else { - return std::copy(__first1, __last1, const_cast<_RawType*>(__first2)); + return std::copy(__first1, __last1, const_cast<_RawTypeIn*>(__first2)); } } +template <class _Alloc, class _Iter1, class _Sent1, class _Iter2> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 __uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) { + auto __unwrapped_range = std::__unwrap_range(__first1, __last1); + auto __result = std::__uninitialized_allocator_copy_impl(__alloc, __unwrapped_range.first, __unwrapped_range.second, std::__unwrap_iter(__first2)); + return std::__rewrap_iter(__first2, __result); +} + // Move-construct the elements [__first1, __last1) into [__first2, __first2 + N) // if the move constructor is noexcept, where N is distance(__first1, __last1). // @@ -600,7 +611,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2 __uninitialized_alloc auto __guard = std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2)); while (__first1 != __last1) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move_if_noexcept(*__first1)); #else allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move(*__first1)); diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h index 9cdbda8eba40..5a9687897196 100644 --- a/libcxx/include/__memory/unique_ptr.h +++ b/libcxx/include/__memory/unique_ptr.h @@ -44,6 +44,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> @@ -115,7 +118,7 @@ struct __unique_ptr_deleter_sfinae<_Deleter&> { }; #if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI) -# define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((trivial_abi)) +# define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__)) #else # define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI #endif @@ -556,7 +559,7 @@ bool operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return !(__x < __y);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _T1, class _D1, class _T2, class _D2> requires three_way_comparable_with<typename unique_ptr<_T1, _D1>::pointer, typename unique_ptr<_T2, _D2>::pointer> @@ -650,7 +653,7 @@ operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) { return !(nullptr < __x); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _T1, class _D1> requires three_way_comparable< typename unique_ptr<_T1, _D1>::pointer> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 @@ -660,7 +663,7 @@ operator<=>(const unique_ptr<_T1, _D1>& __x, nullptr_t) { } #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template<class _Tp> struct __unique_if @@ -697,7 +700,7 @@ template<class _Tp, class... _Args> typename __unique_if<_Tp>::__unique_array_known_bound make_unique(_Args&&...) = delete; -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 #if _LIBCPP_STD_VER >= 20 @@ -743,4 +746,6 @@ struct _LIBCPP_TEMPLATE_VIS hash<__enable_hash_helper< _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_UNIQUE_PTR_H diff --git a/libcxx/include/__memory/uses_allocator.h b/libcxx/include/__memory/uses_allocator.h index fe89704027a0..f82ac1796383 100644 --- a/libcxx/include/__memory/uses_allocator.h +++ b/libcxx/include/__memory/uses_allocator.h @@ -49,9 +49,9 @@ struct _LIBCPP_TEMPLATE_VIS uses_allocator { }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp, class _Alloc> -inline constexpr size_t uses_allocator_v = uses_allocator<_Tp, _Alloc>::value; +inline constexpr bool uses_allocator_v = uses_allocator<_Tp, _Alloc>::value; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__memory/uses_allocator_construction.h b/libcxx/include/__memory/uses_allocator_construction.h index 0f63b080daf3..a2e4f6e26f4b 100644 --- a/libcxx/include/__memory/uses_allocator_construction.h +++ b/libcxx/include/__memory/uses_allocator_construction.h @@ -23,6 +23,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 17 @@ -83,7 +86,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, _Up&& __u, _Vp&& __v) std::forward_as_tuple(std::forward<_Vp>(__v))); } -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 template <class _Pair, class _Alloc, class _Up, class _Vp, __enable_if_t<__is_std_pair<_Pair>, int> = 0> _LIBCPP_HIDE_FROM_ABI constexpr auto __uses_allocator_construction_args(const _Alloc& __alloc, pair<_Up, _Vp>& __pair) noexcept { @@ -109,7 +112,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, pair<_Up, _Vp>&& __pai std::forward_as_tuple(std::get<1>(std::move(__pair)))); } -# if _LIBCPP_STD_VER > 20 +# if _LIBCPP_STD_VER >= 23 template <class _Pair, class _Alloc, class _Up, class _Vp, __enable_if_t<__is_std_pair<_Pair>, int> = 0> _LIBCPP_HIDE_FROM_ABI constexpr auto __uses_allocator_construction_args(const _Alloc& __alloc, const pair<_Up, _Vp>&& __pair) noexcept { @@ -218,4 +221,6 @@ uninitialized_construct_using_allocator(_Type* __ptr, const _Alloc& __alloc, _Ar _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H diff --git a/libcxx/include/__memory_resource/memory_resource.h b/libcxx/include/__memory_resource/memory_resource.h index 02fdd081cce5..418f36dc9b39 100644 --- a/libcxx/include/__memory_resource/memory_resource.h +++ b/libcxx/include/__memory_resource/memory_resource.h @@ -9,14 +9,16 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H +#include <__availability> #include <__config> +#include <__fwd/memory_resource.h> #include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -24,7 +26,7 @@ namespace pmr { // [mem.res.class] -class _LIBCPP_TYPE_VIS memory_resource { +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource { static const size_t __max_align = alignof(max_align_t); public: @@ -51,25 +53,38 @@ private: // [mem.res.eq] -inline _LIBCPP_HIDE_FROM_ABI bool operator==(const memory_resource& __lhs, const memory_resource& __rhs) noexcept { +inline _LIBCPP_AVAILABILITY_PMR _LIBCPP_HIDE_FROM_ABI bool +operator==(const memory_resource& __lhs, const memory_resource& __rhs) noexcept { return &__lhs == &__rhs || __lhs.is_equal(__rhs); } -inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const memory_resource& __lhs, const memory_resource& __rhs) noexcept { +# if _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_AVAILABILITY_PMR _LIBCPP_HIDE_FROM_ABI bool +operator!=(const memory_resource& __lhs, const memory_resource& __rhs) noexcept { return !(__lhs == __rhs); } +# endif + // [mem.res.global] -[[__gnu__::__returns_nonnull__]] _LIBCPP_FUNC_VIS memory_resource* get_default_resource() noexcept; -[[__gnu__::__returns_nonnull__]] _LIBCPP_FUNC_VIS memory_resource* set_default_resource(memory_resource*) noexcept; -[[using __gnu__: __returns_nonnull__, __const__]] _LIBCPP_FUNC_VIS memory_resource* new_delete_resource() noexcept; -[[using __gnu__: __returns_nonnull__, __const__]] _LIBCPP_FUNC_VIS memory_resource* null_memory_resource() noexcept; +[[__gnu__::__returns_nonnull__]] _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource* +get_default_resource() noexcept; + +[[__gnu__::__returns_nonnull__]] _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource* +set_default_resource(memory_resource*) noexcept; + +[[using __gnu__: __returns_nonnull__, __const__]] _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource* +new_delete_resource() noexcept; + +[[using __gnu__: __returns_nonnull__, __const__]] _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI memory_resource* +null_memory_resource() noexcept; } // namespace pmr _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___MEMORY_RESOURCE_MEMORY_RESOURCE_H diff --git a/libcxx/include/__memory_resource/monotonic_buffer_resource.h b/libcxx/include/__memory_resource/monotonic_buffer_resource.h index 5b0d2462582e..0c83f1ebc8db 100644 --- a/libcxx/include/__memory_resource/monotonic_buffer_resource.h +++ b/libcxx/include/__memory_resource/monotonic_buffer_resource.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H +#include <__availability> #include <__config> #include <__memory/addressof.h> #include <__memory_resource/memory_resource.h> @@ -18,7 +19,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -26,7 +27,7 @@ namespace pmr { // [mem.res.monotonic.buffer] -class _LIBCPP_TYPE_VIS monotonic_buffer_resource : public memory_resource { +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI monotonic_buffer_resource : public memory_resource { static const size_t __default_buffer_capacity = 1024; static const size_t __default_buffer_alignment = 16; @@ -35,7 +36,9 @@ class _LIBCPP_TYPE_VIS monotonic_buffer_resource : public memory_resource { char* __start_; char* __cur_; size_t __align_; - size_t __allocation_size() { return (reinterpret_cast<char*>(this) - __start_) + sizeof(*this); } + _LIBCPP_HIDE_FROM_ABI size_t __allocation_size() { + return (reinterpret_cast<char*>(this) - __start_) + sizeof(*this); + } void* __try_allocate_from_chunk(size_t, size_t); }; @@ -115,6 +118,6 @@ private: _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___MEMORY_RESOURCE_MONOTONIC_BUFFER_RESOURCE_H diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h index 2489502bcdaf..8fcce65ad2f4 100644 --- a/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -10,6 +10,7 @@ #define _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H #include <__assert> +#include <__availability> #include <__config> #include <__memory_resource/memory_resource.h> #include <__utility/exception_guard.h> @@ -26,7 +27,7 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -39,7 +40,7 @@ template <class _ValueType = byte # endif > -class _LIBCPP_TEMPLATE_VIS polymorphic_allocator { +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_TEMPLATE_VIS polymorphic_allocator { public: using value_type = _ValueType; @@ -50,7 +51,7 @@ public: _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(memory_resource* __r) noexcept : __res_(__r) {} - polymorphic_allocator(const polymorphic_allocator&) = default; + _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator&) = default; template <class _Tp> _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator<_Tp>& __other) noexcept @@ -68,44 +69,44 @@ public: } _LIBCPP_HIDE_FROM_ABI void deallocate(_ValueType* __p, size_t __n) { - _LIBCPP_ASSERT(__n <= __max_size(), "deallocate called for size which exceeds max_size()"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n <= __max_size(), "deallocate called for size which exceeds max_size()"); __res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType)); } # if _LIBCPP_STD_VER >= 20 - [[nodiscard]] [[using __gnu__: __alloc_size__(2), __alloc_align__(3)]] void* + [[nodiscard]] [[using __gnu__: __alloc_size__(2), __alloc_align__(3)]] _LIBCPP_HIDE_FROM_ABI void* allocate_bytes(size_t __nbytes, size_t __alignment = alignof(max_align_t)) { return __res_->allocate(__nbytes, __alignment); } - void deallocate_bytes(void* __ptr, size_t __nbytes, size_t __alignment = alignof(max_align_t)) { + _LIBCPP_HIDE_FROM_ABI void deallocate_bytes(void* __ptr, size_t __nbytes, size_t __alignment = alignof(max_align_t)) { __res_->deallocate(__ptr, __nbytes, __alignment); } template <class _Type> - [[nodiscard]] _Type* allocate_object(size_t __n = 1) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Type* allocate_object(size_t __n = 1) { if (numeric_limits<size_t>::max() / sizeof(_Type) < __n) std::__throw_bad_array_new_length(); return static_cast<_Type*>(allocate_bytes(__n * sizeof(_Type), alignof(_Type))); } template <class _Type> - void deallocate_object(_Type* __ptr, size_t __n = 1) { + _LIBCPP_HIDE_FROM_ABI void deallocate_object(_Type* __ptr, size_t __n = 1) { deallocate_bytes(__ptr, __n * sizeof(_Type), alignof(_Type)); } template <class _Type, class... _CtorArgs> - [[nodiscard]] _Type* new_object(_CtorArgs&&... __ctor_args) { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Type* new_object(_CtorArgs&&... __ctor_args) { _Type* __ptr = allocate_object<_Type>(); - __exception_guard __guard([&] { deallocate_object(__ptr); }); + auto __guard = std::__make_exception_guard([&] { deallocate_object(__ptr); }); construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...); __guard.__complete(); return __ptr; } template <class _Type> - void delete_object(_Type* __ptr) { + _LIBCPP_HIDE_FROM_ABI void delete_object(_Type* __ptr) { destroy(__ptr); deallocate_object(__ptr); } @@ -207,17 +208,21 @@ operator==(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator< return *__lhs.resource() == *__rhs.resource(); } +# if _LIBCPP_STD_VER <= 17 + template <class _Tp, class _Up> inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator<_Up>& __rhs) noexcept { return !(__lhs == __rhs); } +# endif + } // namespace pmr _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_POP_MACROS diff --git a/libcxx/include/__memory_resource/pool_options.h b/libcxx/include/__memory_resource/pool_options.h index 11585a0e3bc8..442959836c7e 100644 --- a/libcxx/include/__memory_resource/pool_options.h +++ b/libcxx/include/__memory_resource/pool_options.h @@ -16,7 +16,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -24,7 +24,7 @@ namespace pmr { // [mem.res.pool.options] -struct _LIBCPP_TYPE_VIS pool_options { +struct _LIBCPP_EXPORTED_FROM_ABI pool_options { size_t max_blocks_per_chunk = 0; size_t largest_required_pool_block = 0; }; @@ -33,6 +33,6 @@ struct _LIBCPP_TYPE_VIS pool_options { _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___MEMORY_RESOURCE_POOL_OPTIONS_H diff --git a/libcxx/include/__memory_resource/synchronized_pool_resource.h b/libcxx/include/__memory_resource/synchronized_pool_resource.h index 1877147ca16f..b261fb0b194a 100644 --- a/libcxx/include/__memory_resource/synchronized_pool_resource.h +++ b/libcxx/include/__memory_resource/synchronized_pool_resource.h @@ -9,20 +9,19 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_SYNCHRONIZED_POOL_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_SYNCHRONIZED_POOL_RESOURCE_H +#include <__availability> #include <__config> #include <__memory_resource/memory_resource.h> #include <__memory_resource/pool_options.h> #include <__memory_resource/unsynchronized_pool_resource.h> #include <cstddef> -#if !defined(_LIBCPP_HAS_NO_THREADS) -# include <mutex> -#endif +#include <mutex> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -30,7 +29,7 @@ namespace pmr { // [mem.res.pool.overview] -class _LIBCPP_TYPE_VIS synchronized_pool_resource : public memory_resource { +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI synchronized_pool_resource : public memory_resource { public: _LIBCPP_HIDE_FROM_ABI synchronized_pool_resource(const pool_options& __opts, memory_resource* __upstream) : __unsync_(__opts, __upstream) {} @@ -46,7 +45,7 @@ public: synchronized_pool_resource(const synchronized_pool_resource&) = delete; - ~synchronized_pool_resource() override = default; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~synchronized_pool_resource() override = default; synchronized_pool_resource& operator=(const synchronized_pool_resource&) = delete; @@ -89,6 +88,6 @@ private: _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___MEMORY_RESOURCE_SYNCHRONIZED_POOL_RESOURCE_H diff --git a/libcxx/include/__memory_resource/unsynchronized_pool_resource.h b/libcxx/include/__memory_resource/unsynchronized_pool_resource.h index 91d38aac0df0..81d5f9ec4da8 100644 --- a/libcxx/include/__memory_resource/unsynchronized_pool_resource.h +++ b/libcxx/include/__memory_resource/unsynchronized_pool_resource.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___MEMORY_RESOURCE_UNSYNCHRONIZED_POOL_RESOURCE_H #define _LIBCPP___MEMORY_RESOURCE_UNSYNCHRONIZED_POOL_RESOURCE_H +#include <__availability> #include <__config> #include <__memory_resource/memory_resource.h> #include <__memory_resource/pool_options.h> @@ -19,7 +20,7 @@ # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -27,7 +28,7 @@ namespace pmr { // [mem.res.pool.overview] -class _LIBCPP_TYPE_VIS unsynchronized_pool_resource : public memory_resource { +class _LIBCPP_AVAILABILITY_PMR _LIBCPP_EXPORTED_FROM_ABI unsynchronized_pool_resource : public memory_resource { class __fixed_pool; class __adhoc_pool { @@ -101,6 +102,6 @@ private: _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // _LIBCPP___MEMORY_RESOURCE_UNSYNCHRONIZED_POOL_RESOURCE_H diff --git a/libcxx/include/__mutex/lock_guard.h b/libcxx/include/__mutex/lock_guard.h new file mode 100644 index 000000000000..c075512fb97a --- /dev/null +++ b/libcxx/include/__mutex/lock_guard.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MUTEX_LOCK_GUARD_H +#define _LIBCPP___MUTEX_LOCK_GUARD_H + +#include <__config> +#include <__mutex/tag_types.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_HAS_NO_THREADS + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Mutex> +class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) lock_guard { +public: + typedef _Mutex mutex_type; + +private: + mutex_type& __m_; + +public: + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) + _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) + : __m_(__m) { + __m_.lock(); + } + + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t) + _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) + : __m_(__m) {} + _LIBCPP_HIDE_FROM_ABI ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); } + +private: + lock_guard(lock_guard const&) = delete; + lock_guard& operator=(lock_guard const&) = delete; +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(lock_guard); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP___MUTEX_LOCK_GUARD_H diff --git a/libcxx/include/__mutex/mutex.h b/libcxx/include/__mutex/mutex.h new file mode 100644 index 000000000000..4423abf62b8b --- /dev/null +++ b/libcxx/include/__mutex/mutex.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MUTEX_MUTEX_H +#define _LIBCPP___MUTEX_MUTEX_H + +#include <__config> +#include <__threading_support> +#include <__type_traits/is_nothrow_default_constructible.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_HAS_NO_THREADS + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex { + __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; + +public: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR mutex() = default; + + mutex(const mutex&) = delete; + mutex& operator=(const mutex&) = delete; + +# if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) + _LIBCPP_HIDE_FROM_ABI ~mutex() = default; +# else + ~mutex() _NOEXCEPT; +# endif + + void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); + bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); + void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); + + typedef __libcpp_mutex_t* native_handle_type; + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; } +}; + +static_assert(is_nothrow_default_constructible<mutex>::value, "the default constructor for std::mutex must be nothrow"); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP___MUTEX_MUTEX_H diff --git a/libcxx/include/__mutex/tag_types.h b/libcxx/include/__mutex/tag_types.h new file mode 100644 index 000000000000..05ccb8b23a6f --- /dev/null +++ b/libcxx/include/__mutex/tag_types.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MUTEX_TAG_TYPES_H +#define _LIBCPP___MUTEX_TAG_TYPES_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_HAS_NO_THREADS + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct _LIBCPP_EXPORTED_FROM_ABI defer_lock_t { + explicit defer_lock_t() = default; +}; + +struct _LIBCPP_EXPORTED_FROM_ABI try_to_lock_t { + explicit try_to_lock_t() = default; +}; + +struct _LIBCPP_EXPORTED_FROM_ABI adopt_lock_t { + explicit adopt_lock_t() = default; +}; + +# if _LIBCPP_STD_VER >= 17 +inline constexpr defer_lock_t defer_lock = defer_lock_t(); +inline constexpr try_to_lock_t try_to_lock = try_to_lock_t(); +inline constexpr adopt_lock_t adopt_lock = adopt_lock_t(); +# elif !defined(_LIBCPP_CXX03_LANG) +constexpr defer_lock_t defer_lock = defer_lock_t(); +constexpr try_to_lock_t try_to_lock = try_to_lock_t(); +constexpr adopt_lock_t adopt_lock = adopt_lock_t(); +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP___MUTEX_TAG_TYPES_H diff --git a/libcxx/include/__mutex/unique_lock.h b/libcxx/include/__mutex/unique_lock.h new file mode 100644 index 000000000000..c27ce4b24c1a --- /dev/null +++ b/libcxx/include/__mutex/unique_lock.h @@ -0,0 +1,173 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MUTEX_UNIQUE_LOCK_H +#define _LIBCPP___MUTEX_UNIQUE_LOCK_H + +#include <__chrono/duration.h> +#include <__chrono/time_point.h> +#include <__config> +#include <__memory/addressof.h> +#include <__mutex/tag_types.h> +#include <__system_error/system_error.h> +#include <__utility/swap.h> +#include <cerrno> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifndef _LIBCPP_HAS_NO_THREADS + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Mutex> +class _LIBCPP_TEMPLATE_VIS unique_lock { +public: + typedef _Mutex mutex_type; + +private: + mutex_type* __m_; + bool __owns_; + +public: + _LIBCPP_HIDE_FROM_ABI unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} + _LIBCPP_HIDE_FROM_ABI explicit unique_lock(mutex_type& __m) : __m_(std::addressof(__m)), __owns_(true) { + __m_->lock(); + } + + _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT + : __m_(std::addressof(__m)), + __owns_(false) {} + + _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, try_to_lock_t) + : __m_(std::addressof(__m)), __owns_(__m.try_lock()) {} + + _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, adopt_lock_t) : __m_(std::addressof(__m)), __owns_(true) {} + + template <class _Clock, class _Duration> + _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) + : __m_(std::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} + + template <class _Rep, class _Period> + _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) + : __m_(std::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} + + _LIBCPP_HIDE_FROM_ABI ~unique_lock() { + if (__owns_) + __m_->unlock(); + } + + unique_lock(unique_lock const&) = delete; + unique_lock& operator=(unique_lock const&) = delete; + + _LIBCPP_HIDE_FROM_ABI unique_lock(unique_lock&& __u) _NOEXCEPT : __m_(__u.__m_), __owns_(__u.__owns_) { + __u.__m_ = nullptr; + __u.__owns_ = false; + } + + _LIBCPP_HIDE_FROM_ABI unique_lock& operator=(unique_lock&& __u) _NOEXCEPT { + if (__owns_) + __m_->unlock(); + + __m_ = __u.__m_; + __owns_ = __u.__owns_; + __u.__m_ = nullptr; + __u.__owns_ = false; + return *this; + } + + void lock(); + bool try_lock(); + + template <class _Rep, class _Period> + bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); + + template <class _Clock, class _Duration> + bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); + + void unlock(); + + _LIBCPP_HIDE_FROM_ABI void swap(unique_lock& __u) _NOEXCEPT { + std::swap(__m_, __u.__m_); + std::swap(__owns_, __u.__owns_); + } + + _LIBCPP_HIDE_FROM_ABI mutex_type* release() _NOEXCEPT { + mutex_type* __m = __m_; + __m_ = nullptr; + __owns_ = false; + return __m; + } + + _LIBCPP_HIDE_FROM_ABI bool owns_lock() const _NOEXCEPT { return __owns_; } + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __owns_; } + _LIBCPP_HIDE_FROM_ABI mutex_type* mutex() const _NOEXCEPT { return __m_; } +}; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(unique_lock); + +template <class _Mutex> +void unique_lock<_Mutex>::lock() { + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); + __m_->lock(); + __owns_ = true; +} + +template <class _Mutex> +bool unique_lock<_Mutex>::try_lock() { + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); + __owns_ = __m_->try_lock(); + return __owns_; +} + +template <class _Mutex> +template <class _Rep, class _Period> +bool unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) { + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); + __owns_ = __m_->try_lock_for(__d); + return __owns_; +} + +template <class _Mutex> +template <class _Clock, class _Duration> +bool unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); + __owns_ = __m_->try_lock_until(__t); + return __owns_; +} + +template <class _Mutex> +void unique_lock<_Mutex>::unlock() { + if (!__owns_) + __throw_system_error(EPERM, "unique_lock::unlock: not locked"); + __m_->unlock(); + __owns_ = false; +} + +template <class _Mutex> +inline _LIBCPP_HIDE_FROM_ABI void swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT { + __x.swap(__y); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP___MUTEX_UNIQUE_LOCK_H diff --git a/libcxx/include/__mutex_base b/libcxx/include/__mutex_base deleted file mode 100644 index 82d9fa6ecbac..000000000000 --- a/libcxx/include/__mutex_base +++ /dev/null @@ -1,523 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___MUTEX_BASE -#define _LIBCPP___MUTEX_BASE - -#include <__chrono/duration.h> -#include <__chrono/steady_clock.h> -#include <__chrono/system_clock.h> -#include <__chrono/time_point.h> -#include <__config> -#include <__threading_support> -#include <ratio> -#include <system_error> -#include <time.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - - -_LIBCPP_BEGIN_NAMESPACE_STD - -#ifndef _LIBCPP_HAS_NO_THREADS - -class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex -{ - __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; - -public: - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR mutex() = default; - - mutex(const mutex&) = delete; - mutex& operator=(const mutex&) = delete; - -#if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) - ~mutex() = default; -#else - ~mutex() _NOEXCEPT; -#endif - - void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); - bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); - void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); - - typedef __libcpp_mutex_t* native_handle_type; - _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} -}; - -static_assert(is_nothrow_default_constructible<mutex>::value, - "the default constructor for std::mutex must be nothrow"); - -struct _LIBCPP_TYPE_VIS defer_lock_t { explicit defer_lock_t() = default; }; -struct _LIBCPP_TYPE_VIS try_to_lock_t { explicit try_to_lock_t() = default; }; -struct _LIBCPP_TYPE_VIS adopt_lock_t { explicit adopt_lock_t() = default; }; - -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) - -extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock; -extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock; -extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock; - -#else - -/* inline */ constexpr defer_lock_t defer_lock = defer_lock_t(); -/* inline */ constexpr try_to_lock_t try_to_lock = try_to_lock_t(); -/* inline */ constexpr adopt_lock_t adopt_lock = adopt_lock_t(); - -#endif - -template <class _Mutex> -class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) -lock_guard -{ -public: - typedef _Mutex mutex_type; - -private: - mutex_type& __m_; -public: - - _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY - explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) - : __m_(__m) {__m_.lock();} - - _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY - lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) - : __m_(__m) {} - _LIBCPP_INLINE_VISIBILITY - ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} - -private: - lock_guard(lock_guard const&) = delete; - lock_guard& operator=(lock_guard const&) = delete; -}; -_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(lock_guard); - -template <class _Mutex> -class _LIBCPP_TEMPLATE_VIS unique_lock -{ -public: - typedef _Mutex mutex_type; - -private: - mutex_type* __m_; - bool __owns_; - -public: - _LIBCPP_INLINE_VISIBILITY - unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} - _LIBCPP_INLINE_VISIBILITY - explicit unique_lock(mutex_type& __m) - : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();} - _LIBCPP_INLINE_VISIBILITY - unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT - : __m_(_VSTD::addressof(__m)), __owns_(false) {} - _LIBCPP_INLINE_VISIBILITY - unique_lock(mutex_type& __m, try_to_lock_t) - : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {} - _LIBCPP_INLINE_VISIBILITY - unique_lock(mutex_type& __m, adopt_lock_t) - : __m_(_VSTD::addressof(__m)), __owns_(true) {} - template <class _Clock, class _Duration> - _LIBCPP_INLINE_VISIBILITY - unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) - : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} - template <class _Rep, class _Period> - _LIBCPP_INLINE_VISIBILITY - unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) - : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} - _LIBCPP_INLINE_VISIBILITY - ~unique_lock() - { - if (__owns_) - __m_->unlock(); - } - - unique_lock(unique_lock const&) = delete; - unique_lock& operator=(unique_lock const&) = delete; - - _LIBCPP_INLINE_VISIBILITY - unique_lock(unique_lock&& __u) _NOEXCEPT - : __m_(__u.__m_), __owns_(__u.__owns_) - {__u.__m_ = nullptr; __u.__owns_ = false;} - _LIBCPP_INLINE_VISIBILITY - unique_lock& operator=(unique_lock&& __u) _NOEXCEPT - { - if (__owns_) - __m_->unlock(); - __m_ = __u.__m_; - __owns_ = __u.__owns_; - __u.__m_ = nullptr; - __u.__owns_ = false; - return *this; - } - - void lock(); - bool try_lock(); - - template <class _Rep, class _Period> - bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); - template <class _Clock, class _Duration> - bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); - - void unlock(); - - _LIBCPP_INLINE_VISIBILITY - void swap(unique_lock& __u) _NOEXCEPT - { - _VSTD::swap(__m_, __u.__m_); - _VSTD::swap(__owns_, __u.__owns_); - } - _LIBCPP_INLINE_VISIBILITY - mutex_type* release() _NOEXCEPT - { - mutex_type* __m = __m_; - __m_ = nullptr; - __owns_ = false; - return __m; - } - - _LIBCPP_INLINE_VISIBILITY - bool owns_lock() const _NOEXCEPT {return __owns_;} - _LIBCPP_INLINE_VISIBILITY - explicit operator bool() const _NOEXCEPT {return __owns_;} - _LIBCPP_INLINE_VISIBILITY - mutex_type* mutex() const _NOEXCEPT {return __m_;} -}; -_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(unique_lock); - -template <class _Mutex> -void -unique_lock<_Mutex>::lock() -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); - __m_->lock(); - __owns_ = true; -} - -template <class _Mutex> -bool -unique_lock<_Mutex>::try_lock() -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); - __owns_ = __m_->try_lock(); - return __owns_; -} - -template <class _Mutex> -template <class _Rep, class _Period> -bool -unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); - __owns_ = __m_->try_lock_for(__d); - return __owns_; -} - -template <class _Mutex> -template <class _Clock, class _Duration> -bool -unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); - __owns_ = __m_->try_lock_until(__t); - return __owns_; -} - -template <class _Mutex> -void -unique_lock<_Mutex>::unlock() -{ - if (!__owns_) - __throw_system_error(EPERM, "unique_lock::unlock: not locked"); - __m_->unlock(); - __owns_ = false; -} - -template <class _Mutex> -inline _LIBCPP_INLINE_VISIBILITY -void -swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT - {__x.swap(__y);} - -//enum class cv_status -_LIBCPP_DECLARE_STRONG_ENUM(cv_status) -{ - no_timeout, - timeout -}; -_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) - -class _LIBCPP_TYPE_VIS condition_variable -{ - __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; -public: - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; - -#ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION - ~condition_variable() = default; -#else - ~condition_variable(); -#endif - - condition_variable(const condition_variable&) = delete; - condition_variable& operator=(const condition_variable&) = delete; - - void notify_one() _NOEXCEPT; - void notify_all() _NOEXCEPT; - - void wait(unique_lock<mutex>& __lk) _NOEXCEPT; - template <class _Predicate> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - void wait(unique_lock<mutex>& __lk, _Predicate __pred); - - template <class _Clock, class _Duration> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - cv_status - wait_until(unique_lock<mutex>& __lk, - const chrono::time_point<_Clock, _Duration>& __t); - - template <class _Clock, class _Duration, class _Predicate> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - bool - wait_until(unique_lock<mutex>& __lk, - const chrono::time_point<_Clock, _Duration>& __t, - _Predicate __pred); - - template <class _Rep, class _Period> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - cv_status - wait_for(unique_lock<mutex>& __lk, - const chrono::duration<_Rep, _Period>& __d); - - template <class _Rep, class _Period, class _Predicate> - bool - _LIBCPP_INLINE_VISIBILITY - wait_for(unique_lock<mutex>& __lk, - const chrono::duration<_Rep, _Period>& __d, - _Predicate __pred); - - typedef __libcpp_condvar_t* native_handle_type; - _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} - -private: - void __do_timed_wait(unique_lock<mutex>& __lk, - chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT; -#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) - void __do_timed_wait(unique_lock<mutex>& __lk, - chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT; -#endif - template <class _Clock> - void __do_timed_wait(unique_lock<mutex>& __lk, - chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; -}; -#endif // !_LIBCPP_HAS_NO_THREADS - -template <class _Rep, class _Period> -inline _LIBCPP_INLINE_VISIBILITY -__enable_if_t<is_floating_point<_Rep>::value, chrono::nanoseconds> -__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) -{ - using namespace chrono; - using __ratio = ratio_divide<_Period, nano>; - using __ns_rep = nanoseconds::rep; - _Rep __result_float = __d.count() * __ratio::num / __ratio::den; - - _Rep __result_max = numeric_limits<__ns_rep>::max(); - if (__result_float >= __result_max) { - return nanoseconds::max(); - } - - _Rep __result_min = numeric_limits<__ns_rep>::min(); - if (__result_float <= __result_min) { - return nanoseconds::min(); - } - - return nanoseconds(static_cast<__ns_rep>(__result_float)); -} - -template <class _Rep, class _Period> -inline _LIBCPP_INLINE_VISIBILITY -__enable_if_t<!is_floating_point<_Rep>::value, chrono::nanoseconds> -__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) -{ - using namespace chrono; - if (__d.count() == 0) { - return nanoseconds(0); - } - - using __ratio = ratio_divide<_Period, nano>; - using __ns_rep = nanoseconds::rep; - __ns_rep __result_max = numeric_limits<__ns_rep>::max(); - if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) { - return nanoseconds::max(); - } - - __ns_rep __result_min = numeric_limits<__ns_rep>::min(); - if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) { - return nanoseconds::min(); - } - - __ns_rep __result = __d.count() * __ratio::num / __ratio::den; - if (__result == 0) { - return nanoseconds(1); - } - - return nanoseconds(__result); -} - -#ifndef _LIBCPP_HAS_NO_THREADS -template <class _Predicate> -void -condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) -{ - while (!__pred()) - wait(__lk); -} - -template <class _Clock, class _Duration> -cv_status -condition_variable::wait_until(unique_lock<mutex>& __lk, - const chrono::time_point<_Clock, _Duration>& __t) -{ - using namespace chrono; - using __clock_tp_ns = time_point<_Clock, nanoseconds>; - - typename _Clock::time_point __now = _Clock::now(); - if (__t <= __now) - return cv_status::timeout; - - __clock_tp_ns __t_ns = __clock_tp_ns(_VSTD::__safe_nanosecond_cast(__t.time_since_epoch())); - - __do_timed_wait(__lk, __t_ns); - return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; -} - -template <class _Clock, class _Duration, class _Predicate> -bool -condition_variable::wait_until(unique_lock<mutex>& __lk, - const chrono::time_point<_Clock, _Duration>& __t, - _Predicate __pred) -{ - while (!__pred()) - { - if (wait_until(__lk, __t) == cv_status::timeout) - return __pred(); - } - return true; -} - -template <class _Rep, class _Period> -cv_status -condition_variable::wait_for(unique_lock<mutex>& __lk, - const chrono::duration<_Rep, _Period>& __d) -{ - using namespace chrono; - if (__d <= __d.zero()) - return cv_status::timeout; - using __ns_rep = nanoseconds::rep; - steady_clock::time_point __c_now = steady_clock::now(); - -#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) - using __clock_tp_ns = time_point<steady_clock, nanoseconds>; - __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(__c_now.time_since_epoch()).count(); -#else - using __clock_tp_ns = time_point<system_clock, nanoseconds>; - __ns_rep __now_count_ns = _VSTD::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); -#endif - - __ns_rep __d_ns_count = _VSTD::__safe_nanosecond_cast(__d).count(); - - if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) { - __do_timed_wait(__lk, __clock_tp_ns::max()); - } else { - __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count))); - } - - return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : - cv_status::timeout; -} - -template <class _Rep, class _Period, class _Predicate> -inline -bool -condition_variable::wait_for(unique_lock<mutex>& __lk, - const chrono::duration<_Rep, _Period>& __d, - _Predicate __pred) -{ - return wait_until(__lk, chrono::steady_clock::now() + __d, - _VSTD::move(__pred)); -} - -#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) -inline -void -condition_variable::__do_timed_wait(unique_lock<mutex>& __lk, - chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT -{ - using namespace chrono; - if (!__lk.owns_lock()) - __throw_system_error(EPERM, - "condition_variable::timed wait: mutex not locked"); - nanoseconds __d = __tp.time_since_epoch(); - timespec __ts; - seconds __s = duration_cast<seconds>(__d); - using __ts_sec = decltype(__ts.tv_sec); - const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); - if (__s.count() < __ts_sec_max) - { - __ts.tv_sec = static_cast<__ts_sec>(__s.count()); - __ts.tv_nsec = (__d - __s).count(); - } - else - { - __ts.tv_sec = __ts_sec_max; - __ts.tv_nsec = giga::num - 1; - } - int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts); - if (__ec != 0 && __ec != ETIMEDOUT) - __throw_system_error(__ec, "condition_variable timed_wait failed"); -} -#endif // _LIBCPP_HAS_COND_CLOCKWAIT - -template <class _Clock> -inline -void -condition_variable::__do_timed_wait(unique_lock<mutex>& __lk, - chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT -{ - wait_for(__lk, __tp - _Clock::now()); -} - -#endif // !_LIBCPP_HAS_NO_THREADS - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___MUTEX_BASE diff --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle index bc49272b9f1c..cc4eaf73c0bb 100644 --- a/libcxx/include/__node_handle +++ b/libcxx/include/__node_handle @@ -68,9 +68,12 @@ public: # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 // Specialized in __tree & __hash_table for their _NodeType. template <class _NodeType, class _Alloc> @@ -146,7 +149,7 @@ public: _LIBCPP_INLINE_VISIBILITY __basic_node_handle& operator=(__basic_node_handle&& __other) { - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __alloc_ == _VSTD::nullopt || __alloc_traits::propagate_on_container_move_assignment::value || __alloc_ == __other.__alloc_, @@ -247,8 +250,10 @@ struct _LIBCPP_TEMPLATE_VIS __insert_return_type _NodeType node; }; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NODE_HANDLE diff --git a/libcxx/include/__numeric/accumulate.h b/libcxx/include/__numeric/accumulate.h index 81fc0c2943d9..d75c16ead2f2 100644 --- a/libcxx/include/__numeric/accumulate.h +++ b/libcxx/include/__numeric/accumulate.h @@ -17,6 +17,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _InputIterator, class _Tp> @@ -25,7 +28,7 @@ _Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init) { for (; __first != __last; ++__first) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __init = _VSTD::move(__init) + *__first; #else __init = __init + *__first; @@ -39,7 +42,7 @@ _Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op) { for (; __first != __last; ++__first) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __init = __binary_op(_VSTD::move(__init), *__first); #else __init = __binary_op(__init, *__first); @@ -49,4 +52,6 @@ accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOpe _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NUMERIC_ACCUMULATE_H diff --git a/libcxx/include/__numeric/adjacent_difference.h b/libcxx/include/__numeric/adjacent_difference.h index 57e2f5b2803f..4b06f9f29f8d 100644 --- a/libcxx/include/__numeric/adjacent_difference.h +++ b/libcxx/include/__numeric/adjacent_difference.h @@ -18,6 +18,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _InputIterator, class _OutputIterator> @@ -32,7 +35,7 @@ adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterat for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) { typename iterator_traits<_InputIterator>::value_type __val(*__first); -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 *__result = __val - _VSTD::move(__acc); #else *__result = __val - __acc; @@ -56,7 +59,7 @@ adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterat for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) { typename iterator_traits<_InputIterator>::value_type __val(*__first); -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 *__result = __binary_op(__val, _VSTD::move(__acc)); #else *__result = __binary_op(__val, __acc); @@ -69,4 +72,6 @@ adjacent_difference(_InputIterator __first, _InputIterator __last, _OutputIterat _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NUMERIC_ADJACENT_DIFFERENCE_H diff --git a/libcxx/include/__numeric/exclusive_scan.h b/libcxx/include/__numeric/exclusive_scan.h index d02e126b5317..b6091f153a46 100644 --- a/libcxx/include/__numeric/exclusive_scan.h +++ b/libcxx/include/__numeric/exclusive_scan.h @@ -18,9 +18,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator @@ -46,8 +49,10 @@ exclusive_scan(_InputIterator __first, _InputIterator __last, _OutputIterator __ return _VSTD::exclusive_scan(__first, __last, __result, __init, _VSTD::plus<>()); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NUMERIC_EXCLUSIVE_SCAN_H diff --git a/libcxx/include/__numeric/gcd_lcm.h b/libcxx/include/__numeric/gcd_lcm.h index 5a3f81b695e2..1e5ab5713d7f 100644 --- a/libcxx/include/__numeric/gcd_lcm.h +++ b/libcxx/include/__numeric/gcd_lcm.h @@ -28,7 +28,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <typename _Result, typename _Source, bool _IsSigned = is_signed<_Source>::value> struct __ct_abs; @@ -87,7 +87,7 @@ lcm(_Tp __m, _Up __n) using _Rp = common_type_t<_Tp,_Up>; _Rp __val1 = __ct_abs<_Rp, _Tp>()(__m) / _VSTD::gcd(__m, __n); _Rp __val2 = __ct_abs<_Rp, _Up>()(__n); - _LIBCPP_ASSERT((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm"); + _LIBCPP_ASSERT_UNCATEGORIZED((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm"); return __val1 * __val2; } diff --git a/libcxx/include/__numeric/inclusive_scan.h b/libcxx/include/__numeric/inclusive_scan.h index e5bf5ac5b7d5..bd963446027d 100644 --- a/libcxx/include/__numeric/inclusive_scan.h +++ b/libcxx/include/__numeric/inclusive_scan.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator @@ -53,7 +53,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator inclusiv return _VSTD::inclusive_scan(__first, __last, __result, _VSTD::plus<>()); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__numeric/inner_product.h b/libcxx/include/__numeric/inner_product.h index e3d68c04c28b..14144257ea9f 100644 --- a/libcxx/include/__numeric/inner_product.h +++ b/libcxx/include/__numeric/inner_product.h @@ -17,6 +17,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _InputIterator1, class _InputIterator2, class _Tp> @@ -25,7 +28,7 @@ _Tp inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _Tp __init) { for (; __first1 != __last1; ++__first1, (void) ++__first2) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __init = _VSTD::move(__init) + *__first1 * *__first2; #else __init = __init + *__first1 * *__first2; @@ -40,7 +43,7 @@ inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 _Tp __init, _BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2) { for (; __first1 != __last1; ++__first1, (void) ++__first2) -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __init = __binary_op1(_VSTD::move(__init), __binary_op2(*__first1, *__first2)); #else __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); @@ -50,4 +53,6 @@ inner_product(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NUMERIC_INNER_PRODUCT_H diff --git a/libcxx/include/__numeric/midpoint.h b/libcxx/include/__numeric/midpoint.h index bac3642cbd2a..5325f5e6b322 100644 --- a/libcxx/include/__numeric/midpoint.h +++ b/libcxx/include/__numeric/midpoint.h @@ -33,7 +33,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp> _LIBCPP_INLINE_VISIBILITY constexpr enable_if_t<is_integral_v<_Tp> && !is_same_v<bool, _Tp> && !is_null_pointer_v<_Tp>, _Tp> @@ -86,7 +86,7 @@ midpoint(_Fp __a, _Fp __b) noexcept __a/2 + __b/2; // otherwise correctly rounded } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__numeric/partial_sum.h b/libcxx/include/__numeric/partial_sum.h index 97cca582c070..76349750b62a 100644 --- a/libcxx/include/__numeric/partial_sum.h +++ b/libcxx/include/__numeric/partial_sum.h @@ -18,6 +18,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _InputIterator, class _OutputIterator> @@ -31,7 +34,7 @@ partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __res *__result = __t; for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __t = _VSTD::move(__t) + *__first; #else __t = __t + *__first; @@ -54,7 +57,7 @@ partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __res *__result = __t; for (++__first, (void) ++__result; __first != __last; ++__first, (void) ++__result) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 __t = __binary_op(_VSTD::move(__t), *__first); #else __t = __binary_op(__t, *__first); @@ -67,4 +70,6 @@ partial_sum(_InputIterator __first, _InputIterator __last, _OutputIterator __res _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___NUMERIC_PARTIAL_SUM_H diff --git a/libcxx/include/__numeric/pstl_reduce.h b/libcxx/include/__numeric/pstl_reduce.h new file mode 100644 index 000000000000..163e0078e10e --- /dev/null +++ b/libcxx/include/__numeric/pstl_reduce.h @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___NUMERIC_PSTL_REDUCE_H +#define _LIBCPP___NUMERIC_PSTL_REDUCE_H + +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__functional/identity.h> +#include <__iterator/iterator_traits.h> +#include <__numeric/pstl_transform_reduce.h> +#include <__type_traits/is_execution_policy.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class> +void __pstl_reduce(); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Tp, + class _BinaryOperation = plus<>, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp +reduce(_ExecutionPolicy&& __policy, + _ForwardIterator __first, + _ForwardIterator __last, + _Tp __init, + _BinaryOperation __op = {}) { + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_reduce), + [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last, _Tp __g_init, _BinaryOperation __g_op) { + return std::transform_reduce( + __policy, std::move(__g_first), std::move(__g_last), std::move(__g_init), std::move(__g_op), __identity{}); + }, + std::move(__first), + std::move(__last), + std::move(__init), + std::move(__op)); +} + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI __iter_value_type<_ForwardIterator> +reduce(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last) { + return std::__pstl_frontend_dispatch( + _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_reduce), + [&__policy](_ForwardIterator __g_first, _ForwardIterator __g_last) { + return std::reduce(__policy, __g_first, __g_last, __iter_value_type<_ForwardIterator>()); + }, + std::move(__first), + std::move(__last)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___NUMERIC_PSTL_REDUCE_H diff --git a/libcxx/include/__numeric/pstl_transform_reduce.h b/libcxx/include/__numeric/pstl_transform_reduce.h new file mode 100644 index 000000000000..b7c9d8d288f9 --- /dev/null +++ b/libcxx/include/__numeric/pstl_transform_reduce.h @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___NUMERIC_PSTL_TRANSFORM_REDUCE_H +#define _LIBCPP___NUMERIC_PSTL_TRANSFORM_REDUCE_H + +#include <__algorithm/pstl_backend.h> +#include <__algorithm/pstl_frontend_dispatch.h> +#include <__config> +#include <__functional/operations.h> +#include <__numeric/transform_reduce.h> +#include <__type_traits/is_execution_policy.h> +#include <__utility/move.h> +#include <__utility/terminate_on_exception.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _Tp, + class _BinaryOperation1, + class _BinaryOperation2, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Tp __init, + _BinaryOperation1 __reduce, + _BinaryOperation2 __transform) { + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_transform_reduce<_RawPolicy>( + _Backend{}, + std::move(__first1), + std::move(__last1), + std::move(__first2), + std::move(__init), + std::move(__reduce), + std::move(__transform)); +} + +// This overload doesn't get a customization point because it's trivial to detect (through e.g. +// __is_trivial_plus_operation) when specializing the more general variant, which should always be preferred +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _Tp, + enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( + _ExecutionPolicy&& __policy, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Tp __init) { + return std::transform_reduce(__policy, __first1, __last1, __first2, __init, plus{}, multiplies{}); +} + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _Tp, + class _BinaryOperation, + class _UnaryOperation, + class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>, + enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0> +_LIBCPP_HIDE_FROM_ABI _Tp transform_reduce( + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _Tp __init, + _BinaryOperation __reduce, + _UnaryOperation __transform) { + using _Backend = typename __select_backend<_RawPolicy>::type; + return std::__pstl_transform_reduce<_RawPolicy>( + _Backend{}, + std::move(__first), + std::move(__last), + std::move(__init), + std::move(__reduce), + std::move(__transform)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___NUMERIC_PSTL_TRANSFORM_REDUCE_H diff --git a/libcxx/include/__numeric/reduce.h b/libcxx/include/__numeric/reduce.h index b64df05bc80e..8daa7cf60e25 100644 --- a/libcxx/include/__numeric/reduce.h +++ b/libcxx/include/__numeric/reduce.h @@ -13,6 +13,7 @@ #include <__config> #include <__functional/operations.h> #include <__iterator/iterator_traits.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,12 +21,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _InputIterator, class _Tp, class _BinaryOp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp reduce(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOp __b) { for (; __first != __last; ++__first) - __init = __b(__init, *__first); + __init = __b(std::move(__init), *__first); return __init; } diff --git a/libcxx/include/__numeric/transform_exclusive_scan.h b/libcxx/include/__numeric/transform_exclusive_scan.h index afbcdb8db836..3d5574c7d0a0 100644 --- a/libcxx/include/__numeric/transform_exclusive_scan.h +++ b/libcxx/include/__numeric/transform_exclusive_scan.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp, class _UnaryOp> @@ -42,7 +42,7 @@ transform_exclusive_scan(_InputIterator __first, _InputIterator __last, return __result; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__numeric/transform_inclusive_scan.h b/libcxx/include/__numeric/transform_inclusive_scan.h index c050041bc153..ee9168928aec 100644 --- a/libcxx/include/__numeric/transform_inclusive_scan.h +++ b/libcxx/include/__numeric/transform_inclusive_scan.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp, class _UnaryOp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -51,7 +51,7 @@ transform_inclusive_scan(_InputIterator __first, _InputIterator __last, return __result; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__numeric/transform_reduce.h b/libcxx/include/__numeric/transform_reduce.h index d997521a95e6..7e47f34d374e 100644 --- a/libcxx/include/__numeric/transform_reduce.h +++ b/libcxx/include/__numeric/transform_reduce.h @@ -20,13 +20,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _InputIterator, class _Tp, class _BinaryOp, class _UnaryOp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp transform_reduce(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOp __b, _UnaryOp __u) { for (; __first != __last; ++__first) - __init = __b(__init, __u(*__first)); + __init = __b(std::move(__init), __u(*__first)); return __init; } @@ -36,7 +36,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp transform_reduce(_In _InputIterator2 __first2, _Tp __init, _BinaryOp1 __b1, _BinaryOp2 __b2) { for (; __first1 != __last1; ++__first1, (void)++__first2) - __init = __b1(__init, __b2(*__first1, *__first2)); + __init = __b1(std::move(__init), __b2(*__first1, *__first2)); return __init; } diff --git a/libcxx/include/__pstl/internal/algorithm_fwd.h b/libcxx/include/__pstl/internal/algorithm_fwd.h new file mode 100644 index 000000000000..ba350392c2ac --- /dev/null +++ b/libcxx/include/__pstl/internal/algorithm_fwd.h @@ -0,0 +1,1768 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_ALGORITHM_FWD_H +#define _PSTL_ALGORITHM_FWD_H + +#include <__config> +#include <iterator> +#include <type_traits> +#include <utility> + +namespace __pstl { +namespace __internal { + +//------------------------------------------------------------------------ +// walk1 (pseudo) +// +// walk1 evaluates f(x) for each dereferenced value x drawn from [first,last) +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _Function> +void __brick_walk1(_ForwardIterator, + _ForwardIterator, + _Function, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _Function> +void __brick_walk1(_RandomAccessIterator, + _RandomAccessIterator, + _Function, + /*vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Function> +void __pattern_walk1(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Function) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Function> +void __pattern_walk1( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Function); + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Brick> +void __pattern_walk_brick(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Brick) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Brick> +void __pattern_walk_brick( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Brick); + +//------------------------------------------------------------------------ +// walk1_n +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _Size, class _Function> +_ForwardIterator __brick_walk1_n( + _ForwardIterator, + _Size, + _Function, + /*_IsVectorTag=*/std::false_type); + +template <class _RandomAccessIterator, class _DifferenceType, class _Function> +_RandomAccessIterator __brick_walk1_n( + _RandomAccessIterator, + _DifferenceType, + _Function, + /*vectorTag=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function> +_ForwardIterator __pattern_walk1_n(_Tag, _ExecutionPolicy&&, _ForwardIterator, _Size, _Function) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function> +_RandomAccessIterator +__pattern_walk1_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, _Function); + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick> +_ForwardIterator __pattern_walk_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator, _Size, _Brick) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick> +_RandomAccessIterator +__pattern_walk_brick_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, _Brick); + +//------------------------------------------------------------------------ +// walk2 (pseudo) +// +// walk2 evaluates f(x,y) for deferenced values (x,y) drawn from [first1,last1) and [first2,...) +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _Function> +_ForwardIterator2 __brick_walk2( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _Function, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Function> +_RandomAccessIterator2 __brick_walk2( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _Function, + /*vector=*/std::true_type) noexcept; + +template <class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function> +_ForwardIterator2 __brick_walk2_n( + _ForwardIterator1, + _Size, + _ForwardIterator2, + _Function, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Function> +_RandomAccessIterator2 __brick_walk2_n( + _RandomAccessIterator1, + _Size, + _RandomAccessIterator2, + _Function, + /*vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function> +_ForwardIterator2 +__pattern_walk2(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Function) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Function> +_RandomAccessIterator2 __pattern_walk2( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _Function); + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _Size, + class _ForwardIterator2, + class _Function> +_ForwardIterator2 +__pattern_walk2_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Function) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _Size, + class _RandomAccessIterator2, + class _Function> +_RandomAccessIterator2 __pattern_walk2_n( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _Size, _RandomAccessIterator2, _Function); + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick> +_ForwardIterator2 __pattern_walk2_brick( + _Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _Brick) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Brick> +_RandomAccessIterator2 __pattern_walk2_brick( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _Brick); + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _Size, + class _ForwardIterator2, + class _Brick> +_ForwardIterator2 +__pattern_walk2_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator1, _Size, _ForwardIterator2, _Brick) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _Size, + class _RandomAccessIterator2, + class _Brick> +_RandomAccessIterator2 __pattern_walk2_brick_n( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator1, _Size, _RandomAccessIterator2, _Brick); + +//------------------------------------------------------------------------ +// walk3 (pseudo) +// +// walk3 evaluates f(x,y,z) for (x,y,z) drawn from [first1,last1), [first2,...), [first3,...) +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3, class _Function> +_ForwardIterator3 __brick_walk3( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator3, + _Function, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Function> +_RandomAccessIterator3 __brick_walk3( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator3, + _Function, + /*vector=*/std::true_type) noexcept; + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator3, + class _Function> +_ForwardIterator3 __pattern_walk3( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator3, + _Function) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _RandomAccessIterator3, + class _Function> +_RandomAccessIterator3 __pattern_walk3( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator3, + _Function); + +//------------------------------------------------------------------------ +// equal +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +bool __brick_equal(_ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _BinaryPredicate, + /* is_vector = */ std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +bool __brick_equal(_RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _BinaryPredicate, + /* is_vector = */ std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +bool __pattern_equal( + _Tag, _ExecutionPolicy&&, _ForwardIterator1, _ForwardIterator1, _ForwardIterator2, _BinaryPredicate) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +bool __pattern_equal( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _BinaryPredicate); + +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +bool __brick_equal(_ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate, + /* is_vector = */ std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +bool __brick_equal(_RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate, + /* is_vector = */ std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +bool __pattern_equal( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +bool __pattern_equal( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate); + +//------------------------------------------------------------------------ +// find_end +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __brick_find_end( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate, + /*__is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 __brick_find_end( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate, + /*__is_vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __pattern_find_end( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 __pattern_find_end( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// find_first_of +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __brick_find_first_of( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate, + /*__is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 __brick_find_first_of( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate, + /*__is_vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __pattern_find_first_of( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 __pattern_find_first_of( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// search +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __brick_search( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 __brick_search( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate, + /*vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __pattern_search( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _BinaryPredicate) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 __pattern_search( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _BinaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// search_n +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> +_ForwardIterator __brick_search_n( + _ForwardIterator, + _ForwardIterator, + _Size, + const _Tp&, + _BinaryPredicate, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate> +_RandomAccessIterator __brick_search_n( + _RandomAccessIterator, + _RandomAccessIterator, + _Size, + const _Tp&, + _BinaryPredicate, + /*vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> +_ForwardIterator __pattern_search_n( + _Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Size, const _Tp&, _BinaryPredicate) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator, + class _Size, + class _Tp, + class _BinaryPredicate> +_RandomAccessIterator __pattern_search_n( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _Size, + const _Tp&, + _BinaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// copy_n +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _Size, class _OutputIterator> +_OutputIterator __brick_copy_n(_ForwardIterator, + _Size, + _OutputIterator, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _Size, class _OutputIterator> +_OutputIterator __brick_copy_n(_RandomAccessIterator, + _Size, + _OutputIterator, + /*vector=*/std::true_type) noexcept; + +//------------------------------------------------------------------------ +// copy +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _OutputIterator> +_OutputIterator __brick_copy(_ForwardIterator, + _ForwardIterator, + _OutputIterator, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator> +_OutputIterator __brick_copy(_RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + /*vector=*/std::true_type) noexcept; + +//------------------------------------------------------------------------ +// move +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _OutputIterator> +_OutputIterator __brick_move(_ForwardIterator, + _ForwardIterator, + _OutputIterator, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator> +_OutputIterator __brick_move(_RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + /*vector=*/std::true_type) noexcept; + +//------------------------------------------------------------------------ +// swap_ranges +//------------------------------------------------------------------------ +template <class _ForwardIterator, class _OutputIterator> +_OutputIterator __brick_swap_ranges( + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator> +_OutputIterator __brick_swap_ranges( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + /*vector=*/std::true_type) noexcept; + +//------------------------------------------------------------------------ +// copy_if +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _OutputIterator, class _UnaryPredicate> +_OutputIterator __brick_copy_if( + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + _UnaryPredicate, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator, class _UnaryPredicate> +_OutputIterator __brick_copy_if( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _UnaryPredicate, + /*vector=*/std::true_type) noexcept; + +template <class _DifferenceType, class _ForwardIterator, class _UnaryPredicate> +std::pair<_DifferenceType, _DifferenceType> __brick_calc_mask_1( + _ForwardIterator, + _ForwardIterator, + bool* __restrict, + _UnaryPredicate, + /*vector=*/std::false_type) noexcept; +template <class _DifferenceType, class _RandomAccessIterator, class _UnaryPredicate> +std::pair<_DifferenceType, _DifferenceType> __brick_calc_mask_1( + _RandomAccessIterator, + _RandomAccessIterator, + bool* __restrict, + _UnaryPredicate, + /*vector=*/std::true_type) noexcept; + +template <class _ForwardIterator, class _OutputIterator> +void __brick_copy_by_mask( + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + bool*, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator> +void __brick_copy_by_mask( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + bool* __restrict, + /*vector=*/std::true_type) noexcept; + +template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2> +void __brick_partition_by_mask( + _ForwardIterator, + _ForwardIterator, + _OutputIterator1, + _OutputIterator2, + bool*, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2> +void __brick_partition_by_mask( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator1, + _OutputIterator2, + bool*, + /*vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate> +_OutputIterator __pattern_copy_if( + _Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _UnaryPredicate) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator, + class _OutputIterator, + class _UnaryPredicate> +_OutputIterator __pattern_copy_if( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _UnaryPredicate); + +//------------------------------------------------------------------------ +// count +//------------------------------------------------------------------------ + +template <class _RandomAccessIterator, class _Predicate> +typename std::iterator_traits<_RandomAccessIterator>::difference_type __brick_count( + _RandomAccessIterator, + _RandomAccessIterator, + _Predicate, + /* is_vector = */ std::true_type) noexcept; + +template <class _ForwardIterator, class _Predicate> +typename std::iterator_traits<_ForwardIterator>::difference_type __brick_count( + _ForwardIterator, + _ForwardIterator, + _Predicate, + /* is_vector = */ std::false_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Predicate> +typename std::iterator_traits<_ForwardIterator>::difference_type +__pattern_count(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Predicate) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Predicate> +typename std::iterator_traits<_RandomAccessIterator>::difference_type __pattern_count( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Predicate); + +//------------------------------------------------------------------------ +// unique +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _BinaryPredicate> +_ForwardIterator __brick_unique( + _ForwardIterator, + _ForwardIterator, + _BinaryPredicate, + /*is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator __brick_unique( + _RandomAccessIterator, + _RandomAccessIterator, + _BinaryPredicate, + /*is_vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> +_ForwardIterator +__pattern_unique(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator __pattern_unique( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _BinaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// unique_copy +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class OutputIterator, class _BinaryPredicate> +OutputIterator __brick_unique_copy( + _ForwardIterator, + _ForwardIterator, + OutputIterator, + _BinaryPredicate, + /*vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator, class _BinaryPredicate> +_OutputIterator __brick_unique_copy( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _BinaryPredicate, + /*vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate> +_OutputIterator __pattern_unique_copy( + _Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryPredicate) noexcept; + +template <class _ExecutionPolicy, class _DifferenceType, class _RandomAccessIterator, class _BinaryPredicate> +_DifferenceType __brick_calc_mask_2( + _RandomAccessIterator, + _RandomAccessIterator, + bool* __restrict, + _BinaryPredicate, + /*vector=*/std::false_type) noexcept; + +template <class _DifferenceType, class _RandomAccessIterator, class _BinaryPredicate> +_DifferenceType __brick_calc_mask_2( + _RandomAccessIterator, + _RandomAccessIterator, + bool* __restrict, + _BinaryPredicate, + /*vector=*/std::true_type) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator, + class _OutputIterator, + class _BinaryPredicate> +_OutputIterator __pattern_unique_copy( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _BinaryPredicate); + +//------------------------------------------------------------------------ +// reverse +//------------------------------------------------------------------------ + +template <class _BidirectionalIterator> +void __brick_reverse(_BidirectionalIterator, + _BidirectionalIterator, + /*__is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator> +void __brick_reverse(_RandomAccessIterator, + _RandomAccessIterator, + /*__is_vector=*/std::true_type) noexcept; + +template <class _BidirectionalIterator> +void __brick_reverse(_BidirectionalIterator, + _BidirectionalIterator, + _BidirectionalIterator, + /*is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator> +void __brick_reverse(_RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + /*is_vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator> +void __pattern_reverse(_Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator> +void __pattern_reverse(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator); + +//------------------------------------------------------------------------ +// reverse_copy +//------------------------------------------------------------------------ + +template <class _BidirectionalIterator, class _OutputIterator> +_OutputIterator __brick_reverse_copy( + _BidirectionalIterator, + _BidirectionalIterator, + _OutputIterator, + /*is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator> +_OutputIterator __brick_reverse_copy( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + /*is_vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator> +_OutputIterator __pattern_reverse_copy( + _Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _OutputIterator) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator> +_OutputIterator __pattern_reverse_copy( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _OutputIterator); + +//------------------------------------------------------------------------ +// rotate +//------------------------------------------------------------------------ + +template <class _ForwardIterator> +_ForwardIterator __brick_rotate( + _ForwardIterator, + _ForwardIterator, + _ForwardIterator, + /*is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator> +_RandomAccessIterator __brick_rotate( + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + /*is_vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator> +_ForwardIterator +__pattern_rotate(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator> +_RandomAccessIterator __pattern_rotate( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator); + +//------------------------------------------------------------------------ +// rotate_copy +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _OutputIterator> +_OutputIterator __brick_rotate_copy( + _ForwardIterator, + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + /*__is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator> +_OutputIterator __brick_rotate_copy( + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + /*__is_vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator> +_OutputIterator __pattern_rotate_copy( + _Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _ForwardIterator, _OutputIterator) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _OutputIterator> +_OutputIterator __pattern_rotate_copy( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator); + +//------------------------------------------------------------------------ +// is_partitioned +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _UnaryPredicate> +bool __brick_is_partitioned(_ForwardIterator, + _ForwardIterator, + _UnaryPredicate, + /*is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _UnaryPredicate> +bool __brick_is_partitioned(_RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate, + /*is_vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +bool __pattern_is_partitioned(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +bool __pattern_is_partitioned( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate); + +//------------------------------------------------------------------------ +// partition +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _UnaryPredicate> +_ForwardIterator __brick_partition( + _ForwardIterator, + _ForwardIterator, + _UnaryPredicate, + /*is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __brick_partition( + _RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate, + /*is_vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +_ForwardIterator +__pattern_partition(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __pattern_partition( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _UnaryPredicate); + +//------------------------------------------------------------------------ +// stable_partition +//------------------------------------------------------------------------ + +template <class _BidirectionalIterator, class _UnaryPredicate> +_BidirectionalIterator __brick_stable_partition( + _BidirectionalIterator, + _BidirectionalIterator, + _UnaryPredicate, + /*__is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __brick_stable_partition( + _RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate, + /*__is_vector=*/std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate> +_BidirectionalIterator __pattern_stable_partition( + _Tag, _ExecutionPolicy&&, _BidirectionalIterator, _BidirectionalIterator, _UnaryPredicate) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __pattern_stable_partition( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// partition_copy +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate> +std::pair<_OutputIterator1, _OutputIterator2> __brick_partition_copy( + _ForwardIterator, + _ForwardIterator, + _OutputIterator1, + _OutputIterator2, + _UnaryPredicate, + /*is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate> +std::pair<_OutputIterator1, _OutputIterator2> __brick_partition_copy( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator1, + _OutputIterator2, + _UnaryPredicate, + /*is_vector=*/std::true_type) noexcept; + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator, + class _OutputIterator1, + class _OutputIterator2, + class _UnaryPredicate> +std::pair<_OutputIterator1, _OutputIterator2> __pattern_partition_copy( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator, + _ForwardIterator, + _OutputIterator1, + _OutputIterator2, + _UnaryPredicate) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator, + class _OutputIterator1, + class _OutputIterator2, + class _UnaryPredicate> +std::pair<_OutputIterator1, _OutputIterator2> __pattern_partition_copy( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator1, + _OutputIterator2, + _UnaryPredicate); + +//------------------------------------------------------------------------ +// sort +//------------------------------------------------------------------------ + +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsMoveConstructible> +void __pattern_sort( + _Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare, _IsMoveConstructible) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_sort(__parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /*is_move_constructible=*/std::true_type); + +//------------------------------------------------------------------------ +// stable_sort +//------------------------------------------------------------------------ + +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_stable_sort(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_stable_sort( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare); + +//------------------------------------------------------------------------ +// partial_sort +//------------------------------------------------------------------------ + +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_partial_sort( + _Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_partial_sort( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _Compare); + +//------------------------------------------------------------------------ +// partial_sort_copy +//------------------------------------------------------------------------ + +template <class _Tag, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Compare> +_RandomAccessIterator2 __pattern_partial_sort_copy( + _Tag, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Compare) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Compare> +_RandomAccessIterator2 __pattern_partial_sort_copy( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Compare); + +//------------------------------------------------------------------------ +// adjacent_find +//------------------------------------------------------------------------ + +template <class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator __brick_adjacent_find( + _RandomAccessIterator, + _RandomAccessIterator, + _BinaryPredicate, + /* IsVector = */ std::true_type, + bool) noexcept; + +template <class _ForwardIterator, class _BinaryPredicate> +_ForwardIterator __brick_adjacent_find( + _ForwardIterator, + _ForwardIterator, + _BinaryPredicate, + /* IsVector = */ std::false_type, + bool) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> +_ForwardIterator +__pattern_adjacent_find(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _BinaryPredicate, bool) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator __pattern_adjacent_find( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _BinaryPredicate, + bool); + +//------------------------------------------------------------------------ +// nth_element +//------------------------------------------------------------------------ +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_nth_element( + _Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_nth_element( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _Compare) noexcept; + +//------------------------------------------------------------------------ +// fill, fill_n +//------------------------------------------------------------------------ +template <class _RandomAccessIterator, class _Tp> +void __brick_fill(_RandomAccessIterator, + _RandomAccessIterator, + const _Tp&, + /* __is_vector = */ std::true_type) noexcept; + +template <class _ForwardIterator, class _Tp> +void __brick_fill(_ForwardIterator, + _ForwardIterator, + const _Tp&, + /* __is_vector = */ std::false_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Tp> +void __pattern_fill(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, const _Tp&) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Tp> +_RandomAccessIterator +__pattern_fill(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, const _Tp&); + +template <class _RandomAccessIterator, class _Size, class _Tp> +_RandomAccessIterator +__brick_fill_n(_RandomAccessIterator, + _Size, + const _Tp&, + /* __is_vector = */ std::true_type) noexcept; + +template <class _OutputIterator, class _Size, class _Tp> +_OutputIterator +__brick_fill_n(_OutputIterator, + _Size, + const _Tp&, + /* __is_vector = */ std::false_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _OutputIterator, class _Size, class _Tp> +_OutputIterator __pattern_fill_n(_Tag, _ExecutionPolicy&&, _OutputIterator, _Size, const _Tp&) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Tp> +_RandomAccessIterator +__pattern_fill_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _Size, const _Tp&); + +//------------------------------------------------------------------------ +// generate, generate_n +//------------------------------------------------------------------------ + +template <class _RandomAccessIterator, class _Generator> +void __brick_generate(_RandomAccessIterator, + _RandomAccessIterator, + _Generator, + /* is_vector = */ std::true_type) noexcept; + +template <class _ForwardIterator, class _Generator> +void __brick_generate(_ForwardIterator, + _ForwardIterator, + _Generator, + /* is_vector = */ std::false_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Generator> +void __pattern_generate(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Generator) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Generator> +_RandomAccessIterator __pattern_generate( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Generator); + +template <class _RandomAccessIterator, class Size, class _Generator> +_RandomAccessIterator __brick_generate_n( + _RandomAccessIterator, + Size, + _Generator, + /* is_vector = */ std::true_type) noexcept; + +template <class OutputIterator, class Size, class _Generator> +OutputIterator __brick_generate_n( + OutputIterator, + Size, + _Generator, + /* is_vector = */ std::false_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class OutputIterator, class Size, class _Generator> +OutputIterator __pattern_generate_n(_Tag, _ExecutionPolicy&&, OutputIterator, Size, _Generator) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class Size, class _Generator> +_RandomAccessIterator +__pattern_generate_n(__parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, Size, _Generator); + +//------------------------------------------------------------------------ +// remove +//------------------------------------------------------------------------ +template <class _ForwardIterator, class _UnaryPredicate> +_ForwardIterator __brick_remove_if( + _ForwardIterator, + _ForwardIterator, + _UnaryPredicate, + /* __is_vector = */ std::false_type) noexcept; + +template <class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __brick_remove_if( + _RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate, + /* __is_vector = */ std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +_ForwardIterator +__pattern_remove_if(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _UnaryPredicate) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __pattern_remove_if( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _UnaryPredicate) noexcept; + +//------------------------------------------------------------------------ +// merge +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_merge( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_merge( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_merge( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_merge( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare); + +//------------------------------------------------------------------------ +// inplace_merge +//------------------------------------------------------------------------ + +template <class _BidirectionalIterator, class _Compare> +void __brick_inplace_merge( + _BidirectionalIterator, + _BidirectionalIterator, + _BidirectionalIterator, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template <class _RandomAccessIterator, class _Compare> +void __brick_inplace_merge( + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _Compare> +void __pattern_inplace_merge( + _Tag, + _ExecutionPolicy&&, + _BidirectionalIterator, + _BidirectionalIterator, + _BidirectionalIterator, + _Compare) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_inplace_merge( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _RandomAccessIterator, + _Compare); + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> +bool __pattern_includes( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _Compare) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Compare> +bool __pattern_includes( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Compare); + +//------------------------------------------------------------------------ +// set_union +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_union( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_union( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::true_type) noexcept; + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_union( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_union( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare); + +//------------------------------------------------------------------------ +// set_intersection +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_intersection( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_intersection( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::true_type) noexcept; + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_intersection( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_intersection( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare); + +//------------------------------------------------------------------------ +// set_difference +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_difference( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_difference( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::true_type) noexcept; + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_difference( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_difference( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare); + +//------------------------------------------------------------------------ +// set_symmetric_difference +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_symmetric_difference( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_symmetric_difference( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare, + /*__is_vector=*/std::true_type) noexcept; + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_symmetric_difference( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _OutputIterator, + _Compare) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_symmetric_difference( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _OutputIterator, + _Compare); + +//------------------------------------------------------------------------ +// is_heap_until +//------------------------------------------------------------------------ + +template <class _RandomAccessIterator, class _Compare> +_RandomAccessIterator __brick_is_heap_until( + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template <class _RandomAccessIterator, class _Compare> +_RandomAccessIterator __brick_is_heap_until( + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +_RandomAccessIterator +__pattern_is_heap_until(_Tag, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +_RandomAccessIterator __pattern_is_heap_until( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare) noexcept; + +//------------------------------------------------------------------------ +// min_element +//------------------------------------------------------------------------ + +template <typename _ForwardIterator, typename _Compare> +_ForwardIterator __brick_min_element( + _ForwardIterator, + _ForwardIterator, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template <typename _RandomAccessIterator, typename _Compare> +_RandomAccessIterator __brick_min_element( + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare> +_ForwardIterator __pattern_min_element(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare) noexcept; + +template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare> +_RandomAccessIterator __pattern_min_element( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare); + +//------------------------------------------------------------------------ +// minmax_element +//------------------------------------------------------------------------ + +template <typename _ForwardIterator, typename _Compare> +std::pair<_ForwardIterator, _ForwardIterator> __brick_minmax_element( + _ForwardIterator, + _ForwardIterator, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template <typename _RandomAccessIterator, typename _Compare> +std::pair<_RandomAccessIterator, _RandomAccessIterator> __brick_minmax_element( + _RandomAccessIterator, + _RandomAccessIterator, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare> +std::pair<_ForwardIterator, _ForwardIterator> +__pattern_minmax_element(_Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Compare) noexcept; + +template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare> +std::pair<_RandomAccessIterator, _RandomAccessIterator> __pattern_minmax_element( + __parallel_tag<_IsVector>, _ExecutionPolicy&&, _RandomAccessIterator, _RandomAccessIterator, _Compare); + +//------------------------------------------------------------------------ +// mismatch +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _Predicate> +std::pair<_ForwardIterator1, _ForwardIterator2> __brick_mismatch( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _Predicate, + /* __is_vector = */ std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate> +std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __brick_mismatch( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Predicate, + /* __is_vector = */ std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> +std::pair<_ForwardIterator1, _ForwardIterator2> __pattern_mismatch( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _Predicate) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Predicate> +std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __pattern_mismatch( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Predicate) noexcept; + +//------------------------------------------------------------------------ +// lexicographical_compare +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _Compare> +bool __brick_lexicographical_compare( + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _Compare, + /* __is_vector = */ std::false_type) noexcept; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Compare> +bool __brick_lexicographical_compare( + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Compare, + /* __is_vector = */ std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> +bool __pattern_lexicographical_compare( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1, + _ForwardIterator1, + _ForwardIterator2, + _ForwardIterator2, + _Compare) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Compare> +bool __pattern_lexicographical_compare( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator1, + _RandomAccessIterator1, + _RandomAccessIterator2, + _RandomAccessIterator2, + _Compare) noexcept; + +} // namespace __internal +} // namespace __pstl + +#endif /* _PSTL_ALGORITHM_FWD_H */ diff --git a/libcxx/include/__pstl/internal/algorithm_impl.h b/libcxx/include/__pstl/internal/algorithm_impl.h new file mode 100644 index 000000000000..72043ebbf762 --- /dev/null +++ b/libcxx/include/__pstl/internal/algorithm_impl.h @@ -0,0 +1,4174 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_ALGORITHM_IMPL_H +#define _PSTL_ALGORITHM_IMPL_H + +#include <__assert> +#include <__config> +#include <algorithm> +#include <functional> +#include <iterator> +#include <type_traits> +#include <utility> + +#include "execution_impl.h" +#include "memory_impl.h" +#include "parallel_backend.h" +#include "parallel_backend_utils.h" +#include "parallel_impl.h" +#include "unseq_backend_simd.h" + +namespace __pstl { +namespace __internal { + +// [alg.foreach] +// for_each_n with no policy + +template <class _ForwardIterator, class _Size, class _Function> +_ForwardIterator __for_each_n_it_serial(_ForwardIterator __first, _Size __n, _Function __f) { + for (; __n > 0; ++__first, --__n) + __f(__first); + return __first; +} + +//------------------------------------------------------------------------ +// walk1 (pseudo) +// +// walk1 evaluates f(x) for each dereferenced value x drawn from [first,last) +//------------------------------------------------------------------------ +template <class _ForwardIterator, class _Function> +void __brick_walk1( + _ForwardIterator __first, _ForwardIterator __last, _Function __f, /*vector=*/std::false_type) noexcept { + std::for_each(__first, __last, __f); +} + +template <class _RandomAccessIterator, class _Function> +void __brick_walk1(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Function __f, + /*vector=*/std::true_type) noexcept { + __unseq_backend::__simd_walk_1(__first, __last - __first, __f); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Function> +void __pattern_walk1( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __f) noexcept { + __internal::__brick_walk1(__first, __last, __f, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Function> +void __pattern_walk1(__parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Function __f) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__f](_RandomAccessIterator __i, _RandomAccessIterator __j) { + __internal::__brick_walk1(__i, __j, __f, _IsVector{}); + }); + }); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Brick> +void __pattern_walk_brick( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Brick __brick) noexcept { + __brick(__first, __last); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Brick> +void __pattern_walk_brick( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Brick __brick) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j) { __brick(__i, __j); }); + }); +} + +//------------------------------------------------------------------------ +// walk1_n +//------------------------------------------------------------------------ +template <class _ForwardIterator, class _Size, class _Function> +_ForwardIterator __brick_walk1_n(_ForwardIterator __first, _Size __n, _Function __f, /*_IsVectorTag=*/std::false_type) { + return __internal::__for_each_n_it_serial(__first, __n, [&__f](_ForwardIterator __it) { + __f(*__it); + }); // calling serial version +} + +template <class _RandomAccessIterator, class _DifferenceType, class _Function> +_RandomAccessIterator +__brick_walk1_n(_RandomAccessIterator __first, + _DifferenceType __n, + _Function __f, + /*vectorTag=*/std::true_type) noexcept { + return __unseq_backend::__simd_walk_1(__first, __n, __f); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Function> +_ForwardIterator +__pattern_walk1_n(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Function __f) noexcept { + return __internal::__brick_walk1_n(__first, __n, __f, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Function> +_RandomAccessIterator __pattern_walk1_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _Size __n, + _Function __f) { + __internal::__pattern_walk1(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __first + __n, __f); + + return __first + __n; +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Brick> +_ForwardIterator +__pattern_walk_brick_n(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _Size __n, _Brick __brick) noexcept { + return __brick(__first, __n); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Brick> +_RandomAccessIterator __pattern_walk_brick_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _Size __n, + _Brick __brick) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __first + __n, + [__brick](_RandomAccessIterator __i, _RandomAccessIterator __j) { __brick(__i, __j - __i); }); + return __first + __n; + }); +} + +//------------------------------------------------------------------------ +// walk2 (pseudo) +// +// walk2 evaluates f(x,y) for deferenced values (x,y) drawn from [first1,last1) and [first2,...) +//------------------------------------------------------------------------ +template <class _ForwardIterator1, class _ForwardIterator2, class _Function> +_ForwardIterator2 +__brick_walk2(_ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Function __f, + /*vector=*/std::false_type) noexcept { + for (; __first1 != __last1; ++__first1, ++__first2) + __f(*__first1, *__first2); + return __first2; +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Function> +_RandomAccessIterator2 +__brick_walk2(_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _Function __f, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_walk_2(__first1, __last1 - __first1, __first2, __f); +} + +template <class _ForwardIterator1, class _Size, class _ForwardIterator2, class _Function> +_ForwardIterator2 __brick_walk2_n( + _ForwardIterator1 __first1, + _Size __n, + _ForwardIterator2 __first2, + _Function __f, + /*vector=*/std::false_type) noexcept { + for (; __n > 0; --__n, ++__first1, ++__first2) + __f(*__first1, *__first2); + return __first2; +} + +template <class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2, class _Function> +_RandomAccessIterator2 __brick_walk2_n( + _RandomAccessIterator1 __first1, + _Size __n, + _RandomAccessIterator2 __first2, + _Function __f, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_walk_2(__first1, __n, __first2, __f); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Function> +_ForwardIterator2 __pattern_walk2( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Function __f) noexcept { + return __internal::__brick_walk2(__first1, __last1, __first2, __f, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Function> +_RandomAccessIterator2 __pattern_walk2( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _Function __f) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + [__f, __first1, __first2](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + __internal::__brick_walk2(__i, __j, __first2 + (__i - __first1), __f, _IsVector{}); + }); + return __first2 + (__last1 - __first1); + }); +} + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _Size, + class _ForwardIterator2, + class _Function> +_ForwardIterator2 __pattern_walk2_n( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _Size __n, + _ForwardIterator2 __first2, + _Function __f) noexcept { + return __internal::__brick_walk2_n(__first1, __n, __first2, __f, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _Size, + class _RandomAccessIterator2, + class _Function> +_RandomAccessIterator2 __pattern_walk2_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _Size __n, + _RandomAccessIterator2 __first2, + _Function __f) { + return __internal::__pattern_walk2( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __first1 + __n, __first2, __f); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Brick> +_ForwardIterator2 __pattern_walk2_brick( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _Brick __brick) noexcept { + return __brick(__first1, __last1, __first2); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Brick> +_RandomAccessIterator2 __pattern_walk2_brick( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _Brick __brick) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + __brick(__i, __j, __first2 + (__i - __first1)); + }); + return __first2 + (__last1 - __first1); + }); +} + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _Size, + class _ForwardIterator2, + class _Brick> +_ForwardIterator2 __pattern_walk2_brick_n( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _Size __n, + _ForwardIterator2 __first2, + _Brick __brick) noexcept { + return __brick(__first1, __n, __first2); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _Size, + class _RandomAccessIterator2, + class _Brick> +_RandomAccessIterator2 __pattern_walk2_brick_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _Size __n, + _RandomAccessIterator2 __first2, + _Brick __brick) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __first1 + __n, + [__first1, __first2, __brick](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + __brick(__i, __j - __i, __first2 + (__i - __first1)); + }); + return __first2 + __n; + }); +} + +//------------------------------------------------------------------------ +// walk3 (pseudo) +// +// walk3 evaluates f(x,y,z) for (x,y,z) drawn from [first1,last1), [first2,...), [first3,...) +//------------------------------------------------------------------------ +template <class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator3, class _Function> +_ForwardIterator3 __brick_walk3( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator3 __first3, + _Function __f, + /*vector=*/std::false_type) noexcept { + for (; __first1 != __last1; ++__first1, ++__first2, ++__first3) + __f(*__first1, *__first2, *__first3); + return __first3; +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Function> +_RandomAccessIterator3 __brick_walk3( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator3 __first3, + _Function __f, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_walk_3(__first1, __last1 - __first1, __first2, __first3, __f); +} + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator3, + class _Function> +_ForwardIterator3 __pattern_walk3( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator3 __first3, + _Function __f) noexcept { + return __internal::__brick_walk3(__first1, __last1, __first2, __first3, __f, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _RandomAccessIterator3, + class _Function> +_RandomAccessIterator3 __pattern_walk3( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator3 __first3, + _Function __f) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + [__f, __first1, __first2, __first3](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + __internal::__brick_walk3( + __i, __j, __first2 + (__i - __first1), __first3 + (__i - __first1), __f, _IsVector{}); + }); + return __first3 + (__last1 - __first1); + }); +} + +//------------------------------------------------------------------------ +// equal +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +bool __brick_equal(_ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __p, + /* IsVector = */ std::false_type) noexcept { + return std::equal(__first1, __last1, __first2, __last2, __p); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +bool __brick_equal(_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _BinaryPredicate __p, + /* is_vector = */ std::true_type) noexcept { + if (__last1 - __first1 != __last2 - __first2) + return false; + + return __unseq_backend::__simd_first(__first1, __last1 - __first1, __first2, std::not_fn(__p)).first == __last1; +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +bool __pattern_equal( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __p) noexcept { + return __internal::__brick_equal(__first1, __last1, __first2, __last2, __p, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +bool __pattern_equal( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _BinaryPredicate __p) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__last1 - __first1 != __last2 - __first2) + return false; + + return __internal::__except_handler([&]() { + return !__internal::__parallel_or( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + [__first1, __first2, __p](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return !__internal::__brick_equal( + __i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1), __p, _IsVector{}); + }); + }); +} + +//------------------------------------------------------------------------ +// equal version for sequences with equal length +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +bool __brick_equal(_ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __p, + /* IsVector = */ std::false_type) noexcept { + return std::equal(__first1, __last1, __first2, __p); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +bool __brick_equal(_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _BinaryPredicate __p, + /* is_vector = */ std::true_type) noexcept { + return __unseq_backend::__simd_first(__first1, __last1 - __first1, __first2, std::not_fn(__p)).first == __last1; +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +bool __pattern_equal( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __p) noexcept { + return __internal::__brick_equal(__first1, __last1, __first2, __p, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +bool __pattern_equal( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _BinaryPredicate __p) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + return !__internal::__parallel_or( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + [__first1, __first2, __p](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return !__internal::__brick_equal(__i, __j, __first2 + (__i - __first1), __p, _IsVector{}); + }); + }); +} + +//------------------------------------------------------------------------ +// find_end +//------------------------------------------------------------------------ + +// find the first occurrence of the subsequence [s_first, s_last) +// or the last occurrence of the subsequence in the range [first, last) +// b_first determines what occurrence we want to find (first or last) +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate, class _IsVector> +_RandomAccessIterator1 __find_subrange( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator1 __global_last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred, + bool __b_first, + _IsVector __is_vector) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator2>::value_type _ValueType; + auto __n2 = __s_last - __s_first; + if (__n2 < 1) { + return __b_first ? __first : __last; + } + + auto __n1 = __global_last - __first; + if (__n1 < __n2) { + return __last; + } + + auto __cur = __last; + while (__first != __last && (__global_last - __first >= __n2)) { + // find position of *s_first in [first, last) (it can be start of subsequence) + __first = __internal::__brick_find_if( + __first, __last, __equal_value_by_pred<_ValueType, _BinaryPredicate>(*__s_first, __pred), __is_vector); + + // if position that was found previously is the start of subsequence + // then we can exit the loop (b_first == true) or keep the position + // (b_first == false) + if (__first != __last && (__global_last - __first >= __n2) && + __internal::__brick_equal(__s_first + 1, __s_last, __first + 1, __pred, __is_vector)) { + if (__b_first) { + return __first; + } else { + __cur = __first; + } + } else if (__first == __last) { + break; + } else { + } + + // in case of b_first == false we try to find new start position + // for the next subsequence + ++__first; + } + return __cur; +} + +template <class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate, class _IsVector> +_RandomAccessIterator __find_subrange( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _RandomAccessIterator __global_last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred, + _IsVector __is_vector) noexcept { + if (static_cast<_Size>(__global_last - __first) < __count || __count < 1) { + return __last; // According to the standard last shall be returned when count < 1 + } + + auto __unary_pred = __equal_value_by_pred<_Tp, _BinaryPredicate>(__value, __pred); + while (__first != __last && (static_cast<_Size>(__global_last - __first) >= __count)) { + __first = __internal::__brick_find_if(__first, __last, __unary_pred, __is_vector); + + // check that all of elements in [first+1, first+count) equal to value + if (__first != __last && (static_cast<_Size>(__global_last - __first) >= __count) && + !__internal::__brick_any_of(__first + 1, __first + __count, std::not_fn(__unary_pred), __is_vector)) { + return __first; + } else if (__first == __last) { + break; + } else { + ++__first; + } + } + return __last; +} + +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __brick_find_end( + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred, + /*__is_vector=*/std::false_type) noexcept { + return std::find_end(__first, __last, __s_first, __s_last, __pred); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 __brick_find_end( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred, + /*__is_vector=*/std::true_type) noexcept { + return __find_subrange(__first, __last, __last, __s_first, __s_last, __pred, false, std::true_type()); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __pattern_find_end( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + return __internal::__brick_find_end(__first, __last, __s_first, __s_last, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 __pattern_find_end( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__last - __first == __s_last - __s_first) { + const bool __res = + __internal::__pattern_equal(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __pred); + return __res ? __first : __last; + } else { + return __internal::__except_handler([&]() { + return __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__last, __s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, false, _IsVector{}); + }, + std::greater<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), + /*is_first=*/false); + }); + } +} + +//------------------------------------------------------------------------ +// find_first_of +//------------------------------------------------------------------------ +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __brick_find_first_of( + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred, + /*__is_vector=*/std::false_type) noexcept { + return std::find_first_of(__first, __last, __s_first, __s_last, __pred); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 __brick_find_first_of( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred, + /*__is_vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_find_first_of(__first, __last, __s_first, __s_last, __pred); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __pattern_find_first_of( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + return __internal::__brick_find_first_of(__first, __last, __s_first, __s_last, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 __pattern_find_first_of( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + return __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__brick_find_first_of(__i, __j, __s_first, __s_last, __pred, _IsVector{}); + }, + std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), + /*is_first=*/true); + }); +} + +//------------------------------------------------------------------------ +// search +//------------------------------------------------------------------------ +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 __brick_search( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + return std::search(__first, __last, __s_first, __s_last, __pred); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator1 __brick_search( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred, + /*vector=*/std::true_type) noexcept { + return __internal::__find_subrange(__first, __last, __last, __s_first, __s_last, __pred, true, std::true_type()); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_ForwardIterator1 __pattern_search( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + return __internal::__brick_search(__first, __last, __s_first, __s_last, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator1 __pattern_search( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __s_first, + _RandomAccessIterator2 __s_last, + _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__last - __first == __s_last - __s_first) { + const bool __res = + __internal::__pattern_equal(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __pred); + return __res ? __first : __last; + } else { + return __internal::__except_handler([&]() { + return __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__last, __s_first, __s_last, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__find_subrange(__i, __j, __last, __s_first, __s_last, __pred, true, _IsVector{}); + }, + std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), + /*is_first=*/true); + }); + } +} + +//------------------------------------------------------------------------ +// search_n +//------------------------------------------------------------------------ +template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> +_ForwardIterator __brick_search_n( + _ForwardIterator __first, + _ForwardIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + return std::search_n(__first, __last, __count, __value, __pred); +} + +template <class _RandomAccessIterator, class _Size, class _Tp, class _BinaryPredicate> +_RandomAccessIterator __brick_search_n( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred, + /*vector=*/std::true_type) noexcept { + return __internal::__find_subrange(__first, __last, __last, __count, __value, __pred, std::true_type()); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> +_ForwardIterator __pattern_search_n( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred) noexcept { + return __internal::__brick_search_n(__first, __last, __count, __value, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator, + class _Size, + class _Tp, + class _BinaryPredicate> +_RandomAccessIterator __pattern_search_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (static_cast<_Size>(__last - __first) == __count) { + const bool __result = !__internal::__pattern_any_of( + __tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [&__value, &__pred](const _Tp& __val) { + return !__pred(__val, __value); + }); + return __result ? __first : __last; + } else { + return __internal::__except_handler([&__exec, __first, __last, __count, &__value, __pred]() { + return __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__last, __count, &__value, __pred](_RandomAccessIterator __i, _RandomAccessIterator __j) { + return __internal::__find_subrange(__i, __j, __last, __count, __value, __pred, _IsVector{}); + }, + std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), + /*is_first=*/true); + }); + } +} + +//------------------------------------------------------------------------ +// copy_n +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _Size, class _OutputIterator> +_OutputIterator +__brick_copy_n(_ForwardIterator __first, _Size __n, _OutputIterator __result, /*vector=*/std::false_type) noexcept { + return std::copy_n(__first, __n, __result); +} + +template <class _RandomAccessIterator1, class _Size, class _RandomAccessIterator2> +_RandomAccessIterator2 +__brick_copy_n(_RandomAccessIterator1 __first, + _Size __n, + _RandomAccessIterator2 __result, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_assign( + __first, __n, __result, [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { + *__result = *__first; + }); +} + +//------------------------------------------------------------------------ +// copy +//------------------------------------------------------------------------ +template <class _ForwardIterator, class _OutputIterator> +_OutputIterator +__brick_copy(_ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + /*vector=*/std::false_type) noexcept { + return std::copy(__first, __last, __result); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 +__brick_copy(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_assign( + __first, __last - __first, __result, [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { + *__result = *__first; + }); +} + +//------------------------------------------------------------------------ +// move +//------------------------------------------------------------------------ +template <class _ForwardIterator, class _OutputIterator> +_OutputIterator +__brick_move(_ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + /*vector=*/std::false_type) noexcept { + return std::move(__first, __last, __result); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 +__brick_move(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_assign( + __first, __last - __first, __result, [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { + *__result = std::move(*__first); + }); +} + +struct __brick_move_destroy { + template <typename _RandomAccessIterator1, typename _RandomAccessIterator2> + _RandomAccessIterator2 + operator()(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*vec*/ std::true_type) const { + using _IteratorValueType = typename std::iterator_traits<_RandomAccessIterator1>::value_type; + + return __unseq_backend::__simd_assign( + __first, __last - __first, __result, [](_RandomAccessIterator1 __first, _RandomAccessIterator2 __result) { + *__result = std::move(*__first); + (*__first).~_IteratorValueType(); + }); + } + + template <typename _RandomAccessIterator1, typename _RandomAccessIterator2> + _RandomAccessIterator2 + operator()(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*vec*/ std::false_type) const { + using _IteratorValueType = typename std::iterator_traits<_RandomAccessIterator1>::value_type; + + for (; __first != __last; ++__first, ++__result) { + *__result = std::move(*__first); + (*__first).~_IteratorValueType(); + } + return __result; + } +}; + +//------------------------------------------------------------------------ +// swap_ranges +//------------------------------------------------------------------------ +template <class _ForwardIterator, class _OutputIterator> +_OutputIterator __brick_swap_ranges( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + /*vector=*/std::false_type) noexcept { + return std::swap_ranges(__first, __last, __result); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 __brick_swap_ranges( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*vector=*/std::true_type) noexcept { + using std::iter_swap; + return __unseq_backend::__simd_assign( + __first, __last - __first, __result, iter_swap<_RandomAccessIterator1, _RandomAccessIterator2>); +} + +//------------------------------------------------------------------------ +// copy_if +//------------------------------------------------------------------------ +template <class _ForwardIterator, class _OutputIterator, class _UnaryPredicate> +_OutputIterator __brick_copy_if( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + _UnaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + return std::copy_if(__first, __last, __result, __pred); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _UnaryPredicate> +_RandomAccessIterator2 __brick_copy_if( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + _UnaryPredicate __pred, + /*vector=*/std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + return __unseq_backend::__simd_copy_if(__first, __last - __first, __result, __pred); +#else + return std::copy_if(__first, __last, __result, __pred); +#endif +} + +// TODO: Try to use transform_reduce for combining __brick_copy_if_phase1 on IsVector. +template <class _DifferenceType, class _ForwardIterator, class _UnaryPredicate> +std::pair<_DifferenceType, _DifferenceType> __brick_calc_mask_1( + _ForwardIterator __first, + _ForwardIterator __last, + bool* __restrict __mask, + _UnaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + auto __count_true = _DifferenceType(0); + auto __size = __last - __first; + + static_assert(__are_random_access_iterators<_ForwardIterator>::value, + "Pattern-brick error. Should be a random access iterator."); + + for (; __first != __last; ++__first, ++__mask) { + *__mask = __pred(*__first); + if (*__mask) { + ++__count_true; + } + } + return std::make_pair(__count_true, __size - __count_true); +} + +template <class _DifferenceType, class _RandomAccessIterator, class _UnaryPredicate> +std::pair<_DifferenceType, _DifferenceType> __brick_calc_mask_1( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + bool* __mask, + _UnaryPredicate __pred, + /*vector=*/std::true_type) noexcept { + auto __result = __unseq_backend::__simd_calc_mask_1(__first, __last - __first, __mask, __pred); + return std::make_pair(__result, (__last - __first) - __result); +} + +template <class _ForwardIterator, class _OutputIterator, class _Assigner> +void __brick_copy_by_mask( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + bool* __mask, + _Assigner __assigner, + /*vector=*/std::false_type) noexcept { + for (; __first != __last; ++__first, ++__mask) { + if (*__mask) { + __assigner(__first, __result); + ++__result; + } + } +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Assigner> +void __brick_copy_by_mask( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + bool* __restrict __mask, + _Assigner __assigner, + /*vector=*/std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + __unseq_backend::__simd_copy_by_mask(__first, __last - __first, __result, __mask, __assigner); +#else + __internal::__brick_copy_by_mask(__first, __last, __result, __mask, __assigner, std::false_type()); +#endif +} + +template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2> +void __brick_partition_by_mask( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator1 __out_true, + _OutputIterator2 __out_false, + bool* __mask, + /*vector=*/std::false_type) noexcept { + for (; __first != __last; ++__first, ++__mask) { + if (*__mask) { + *__out_true = *__first; + ++__out_true; + } else { + *__out_false = *__first; + ++__out_false; + } + } +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3> +void __brick_partition_by_mask( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __out_true, + _RandomAccessIterator3 __out_false, + bool* __mask, + /*vector=*/std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + __unseq_backend::__simd_partition_by_mask(__first, __last - __first, __out_true, __out_false, __mask); +#else + __internal::__brick_partition_by_mask(__first, __last, __out_true, __out_false, __mask, std::false_type()); +#endif +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _UnaryPredicate> +_OutputIterator __pattern_copy_if( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + _UnaryPredicate __pred) noexcept { + return __internal::__brick_copy_if(__first, __last, __result, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _UnaryPredicate> +_RandomAccessIterator2 __pattern_copy_if( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + _UnaryPredicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; + const _DifferenceType __n = __last - __first; + if (_DifferenceType(1) < __n) { + __par_backend::__buffer<bool> __mask_buf(__n); + return __internal::__except_handler([&__exec, __n, __first, __result, __pred, &__mask_buf]() { + bool* __mask = __mask_buf.get(); + _DifferenceType __m{}; + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n, + _DifferenceType(0), + [=](_DifferenceType __i, _DifferenceType __len) { // Reduce + return __internal::__brick_calc_mask_1<_DifferenceType>( + __first + __i, __first + (__i + __len), __mask + __i, __pred, _IsVector{}) + .first; + }, + std::plus<_DifferenceType>(), // Combine + [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan + __internal::__brick_copy_by_mask( + __first + __i, + __first + (__i + __len), + __result + __initial, + __mask + __i, + [](_RandomAccessIterator1 __x, _RandomAccessIterator2 __z) { *__z = *__x; }, + _IsVector{}); + }, + [&__m](_DifferenceType __total) { __m = __total; }); + return __result + __m; + }); + } + // trivial sequence - use serial algorithm + return __internal::__brick_copy_if(__first, __last, __result, __pred, _IsVector{}); +} + +//------------------------------------------------------------------------ +// count +//------------------------------------------------------------------------ +template <class _RandomAccessIterator, class _Predicate> +typename std::iterator_traits<_RandomAccessIterator>::difference_type +__brick_count(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Predicate __pred, + /* is_vector = */ std::true_type) noexcept { + return __unseq_backend::__simd_count(__first, __last - __first, __pred); +} + +template <class _ForwardIterator, class _Predicate> +typename std::iterator_traits<_ForwardIterator>::difference_type +__brick_count(_ForwardIterator __first, + _ForwardIterator __last, + _Predicate __pred, + /* is_vector = */ std::false_type) noexcept { + return std::count_if(__first, __last, __pred); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Predicate> +typename std::iterator_traits<_ForwardIterator>::difference_type __pattern_count( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) noexcept { + return __internal::__brick_count(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Predicate> +typename std::iterator_traits<_RandomAccessIterator>::difference_type __pattern_count( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Predicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType; + return __internal::__except_handler([&]() { + return __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + _SizeType(0), + [__pred](_RandomAccessIterator __begin, _RandomAccessIterator __end, _SizeType __value) -> _SizeType { + return __value + __internal::__brick_count(__begin, __end, __pred, _IsVector{}); + }, + std::plus<_SizeType>()); + }); +} + +//------------------------------------------------------------------------ +// unique +//------------------------------------------------------------------------ + +template <class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator +__brick_unique(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _BinaryPredicate __pred, + /*is_vector=*/std::false_type) noexcept { + return std::unique(__first, __last, __pred); +} + +template <class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator +__brick_unique(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _BinaryPredicate __pred, + /*is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::unique(__first, __last, __pred); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> +_ForwardIterator __pattern_unique( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) noexcept { + return __internal::__brick_unique(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +// That function is shared between two algorithms - remove_if (__pattern_remove_if) and unique (pattern unique). But a +// mask calculation is different. So, a caller passes _CalcMask brick into remove_elements. +template <class _IsVector, class _ExecutionPolicy, class _ForwardIterator, class _CalcMask> +_ForwardIterator __remove_elements( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _CalcMask __calc_mask) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_ForwardIterator>::difference_type _DifferenceType; + typedef typename std::iterator_traits<_ForwardIterator>::value_type _Tp; + _DifferenceType __n = __last - __first; + __par_backend::__buffer<bool> __mask_buf(__n); + // 1. find a first iterator that should be removed + return __internal::__except_handler([&]() { + bool* __mask = __mask_buf.get(); + _DifferenceType __min = __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + _DifferenceType(0), + __n, + __n, + [__first, __mask, &__calc_mask]( + _DifferenceType __i, _DifferenceType __j, _DifferenceType __local_min) -> _DifferenceType { + // Create mask + __calc_mask(__mask + __i, __mask + __j, __first + __i); + + // if minimum was found in a previous range we shouldn't do anymore + if (__local_min < __i) { + return __local_min; + } + // find first iterator that should be removed + bool* __result = __internal::__brick_find_if( + __mask + __i, __mask + __j, [](bool __val) { return !__val; }, _IsVector{}); + if (__result - __mask == __j) { + return __local_min; + } + return std::min(__local_min, _DifferenceType(__result - __mask)); + }, + [](_DifferenceType __local_min1, _DifferenceType __local_min2) -> _DifferenceType { + return std::min(__local_min1, __local_min2); + }); + + // No elements to remove - exit + if (__min == __n) { + return __last; + } + __n -= __min; + __first += __min; + + __par_backend::__buffer<_Tp> __buf(__n); + _Tp* __result = __buf.get(); + __mask += __min; + _DifferenceType __m{}; + // 2. Elements that doesn't satisfy pred are moved to result + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n, + _DifferenceType(0), + [__mask](_DifferenceType __i, _DifferenceType __len) { + return __internal::__brick_count( + __mask + __i, __mask + __i + __len, [](bool __val) { return __val; }, _IsVector{}); + }, + std::plus<_DifferenceType>(), + [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { + __internal::__brick_copy_by_mask( + __first + __i, + __first + __i + __len, + __result + __initial, + __mask + __i, + [](_ForwardIterator __x, _Tp* __z) { + __internal::__invoke_if_else( + std::is_trivial<_Tp>(), + [&]() { *__z = std::move(*__x); }, + [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); }); + }, + _IsVector{}); + }, + [&__m](_DifferenceType __total) { __m = __total; }); + + // 3. Elements from result are moved to [first, last) + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __result, + __result + __m, + [__result, __first](_Tp* __i, _Tp* __j) { + __invoke_if_else( + std::is_trivial<_Tp>(), + [&]() { __brick_move(__i, __j, __first + (__i - __result), _IsVector{}); }, + [&]() { __brick_move_destroy()(__i, __j, __first + (__i - __result), _IsVector{}); }); + }); + return __first + __m; + }); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator __pattern_unique( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _BinaryPredicate __pred) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; + + if (__first == __last) { + return __last; + } + if (__first + 1 == __last || __first + 2 == __last) { + // Trivial sequence - use serial algorithm + return __internal::__brick_unique(__first, __last, __pred, _IsVector{}); + } + return __internal::__remove_elements( + __tag, + std::forward<_ExecutionPolicy>(__exec), + ++__first, + __last, + [&__pred](bool* __b, bool* __e, _RandomAccessIterator __it) { + __internal::__brick_walk3( + __b, + __e, + __it - 1, + __it, + [&__pred](bool& __x, _ReferenceType __y, _ReferenceType __z) { __x = !__pred(__y, __z); }, + _IsVector{}); + }); +} + +//------------------------------------------------------------------------ +// unique_copy +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class OutputIterator, class _BinaryPredicate> +OutputIterator __brick_unique_copy( + _ForwardIterator __first, + _ForwardIterator __last, + OutputIterator __result, + _BinaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + return std::unique_copy(__first, __last, __result, __pred); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _BinaryPredicate> +_RandomAccessIterator2 __brick_unique_copy( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + _BinaryPredicate __pred, + /*vector=*/std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + return __unseq_backend::__simd_unique_copy(__first, __last - __first, __result, __pred); +#else + return std::unique_copy(__first, __last, __result, __pred); +#endif +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryPredicate> +_OutputIterator __pattern_unique_copy( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + _BinaryPredicate __pred) noexcept { + return __internal::__brick_unique_copy(__first, __last, __result, __pred, typename _Tag::__is_vector{}); +} + +template <class _DifferenceType, class _RandomAccessIterator, class _BinaryPredicate> +_DifferenceType __brick_calc_mask_2( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + bool* __restrict __mask, + _BinaryPredicate __pred, + /*vector=*/std::false_type) noexcept { + _DifferenceType __count = 0; + for (; __first != __last; ++__first, ++__mask) { + *__mask = !__pred(*__first, *(__first - 1)); + __count += *__mask; + } + return __count; +} + +template <class _DifferenceType, class _RandomAccessIterator, class _BinaryPredicate> +_DifferenceType __brick_calc_mask_2( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + bool* __restrict __mask, + _BinaryPredicate __pred, + /*vector=*/std::true_type) noexcept { + return __unseq_backend::__simd_calc_mask_2(__first, __last - __first, __mask, __pred); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryPredicate> +_RandomAccessIterator2 __pattern_unique_copy( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + _BinaryPredicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; + const _DifferenceType __n = __last - __first; + if (_DifferenceType(2) < __n) { + __par_backend::__buffer<bool> __mask_buf(__n); + if (_DifferenceType(2) < __n) { + return __internal::__except_handler([&__exec, __n, __first, __result, __pred, &__mask_buf]() { + bool* __mask = __mask_buf.get(); + _DifferenceType __m{}; + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n, + _DifferenceType(0), + [=](_DifferenceType __i, _DifferenceType __len) -> _DifferenceType { // Reduce + _DifferenceType __extra = 0; + if (__i == 0) { + // Special boundary case + __mask[__i] = true; + if (--__len == 0) + return 1; + ++__i; + ++__extra; + } + return __internal::__brick_calc_mask_2<_DifferenceType>( + __first + __i, __first + (__i + __len), __mask + __i, __pred, _IsVector{}) + + __extra; + }, + std::plus<_DifferenceType>(), // Combine + [=](_DifferenceType __i, _DifferenceType __len, _DifferenceType __initial) { // Scan + // Phase 2 is same as for __pattern_copy_if + __internal::__brick_copy_by_mask( + __first + __i, + __first + (__i + __len), + __result + __initial, + __mask + __i, + [](_RandomAccessIterator1 __x, _RandomAccessIterator2 __z) { *__z = *__x; }, + _IsVector{}); + }, + [&__m](_DifferenceType __total) { __m = __total; }); + return __result + __m; + }); + } + } + // trivial sequence - use serial algorithm + return __internal::__brick_unique_copy(__first, __last, __result, __pred, _IsVector{}); +} + +//------------------------------------------------------------------------ +// reverse +//------------------------------------------------------------------------ +template <class _BidirectionalIterator> +void __brick_reverse( + _BidirectionalIterator __first, _BidirectionalIterator __last, /*__is_vector=*/std::false_type) noexcept { + std::reverse(__first, __last); +} + +template <class _RandomAccessIterator> +void __brick_reverse( + _RandomAccessIterator __first, _RandomAccessIterator __last, /*__is_vector=*/std::true_type) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; + + const auto __n = (__last - __first) / 2; + __unseq_backend::__simd_walk_2( + __first, __n, std::reverse_iterator<_RandomAccessIterator>(__last), [](_ReferenceType __x, _ReferenceType __y) { + using std::swap; + swap(__x, __y); + }); +} + +// this brick is called in parallel version, so we can use iterator arithmetic +template <class _BidirectionalIterator> +void __brick_reverse(_BidirectionalIterator __first, + _BidirectionalIterator __last, + _BidirectionalIterator __d_last, + /*is_vector=*/std::false_type) noexcept { + for (--__d_last; __first != __last; ++__first, --__d_last) { + using std::iter_swap; + iter_swap(__first, __d_last); + } +} + +// this brick is called in parallel version, so we can use iterator arithmetic +template <class _RandomAccessIterator> +void __brick_reverse(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _RandomAccessIterator __d_last, + /*is_vector=*/std::true_type) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; + + __unseq_backend::__simd_walk_2( + __first, + __last - __first, + std::reverse_iterator<_RandomAccessIterator>(__d_last), + [](_ReferenceType __x, _ReferenceType __y) { + using std::swap; + swap(__x, __y); + }); +} + +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator> +void __pattern_reverse( + _Tag, _ExecutionPolicy&&, _BidirectionalIterator __first, _BidirectionalIterator __last) noexcept { + __internal::__brick_reverse(__first, __last, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator> +void __pattern_reverse(__parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __first + (__last - __first) / 2, + [__first, __last](_RandomAccessIterator __inner_first, _RandomAccessIterator __inner_last) { + __internal::__brick_reverse(__inner_first, __inner_last, __last - (__inner_first - __first), _IsVector{}); + }); +} + +//------------------------------------------------------------------------ +// reverse_copy +//------------------------------------------------------------------------ + +template <class _BidirectionalIterator, class _OutputIterator> +_OutputIterator __brick_reverse_copy( + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _OutputIterator __d_first, + /*is_vector=*/std::false_type) noexcept { + return std::reverse_copy(__first, __last, __d_first); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 __brick_reverse_copy( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first, + /*is_vector=*/std::true_type) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2; + + return __unseq_backend::__simd_walk_2( + std::reverse_iterator<_RandomAccessIterator1>(__last), + __last - __first, + __d_first, + [](_ReferenceType1 __x, _ReferenceType2 __y) { __y = __x; }); +} + +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _OutputIterator> +_OutputIterator __pattern_reverse_copy( + _Tag, + _ExecutionPolicy&&, + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _OutputIterator __d_first) noexcept { + return __internal::__brick_reverse_copy(__first, __last, __d_first, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 __pattern_reverse_copy( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + auto __len = __last - __first; + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__first, __len, __d_first](_RandomAccessIterator1 __inner_first, _RandomAccessIterator1 __inner_last) { + __internal::__brick_reverse_copy( + __inner_first, __inner_last, __d_first + (__len - (__inner_last - __first)), _IsVector{}); + }); + return __d_first + __len; +} + +//------------------------------------------------------------------------ +// rotate +//------------------------------------------------------------------------ +template <class _ForwardIterator> +_ForwardIterator +__brick_rotate(_ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + /*is_vector=*/std::false_type) noexcept { +#if defined(_PSTL_CPP11_STD_ROTATE_BROKEN) + std::rotate(__first, __middle, __last); + return std::next(__first, std::distance(__middle, __last)); +#else + return std::rotate(__first, __middle, __last); +#endif +} + +template <class _RandomAccessIterator> +_RandomAccessIterator +__brick_rotate(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + /*is_vector=*/std::true_type) noexcept { + auto __n = __last - __first; + auto __m = __middle - __first; + const _RandomAccessIterator __ret = __first + (__last - __middle); + + bool __is_left = (__m <= __n / 2); + if (!__is_left) + __m = __n - __m; + + while (__n > 1 && __m > 0) { + using std::iter_swap; + const auto __m_2 = __m * 2; + if (__is_left) { + for (; __last - __first >= __m_2; __first += __m) { + __unseq_backend::__simd_assign( + __first, __m, __first + __m, iter_swap<_RandomAccessIterator, _RandomAccessIterator>); + } + } else { + for (; __last - __first >= __m_2; __last -= __m) { + __unseq_backend::__simd_assign( + __last - __m, __m, __last - __m_2, iter_swap<_RandomAccessIterator, _RandomAccessIterator>); + } + } + __is_left = !__is_left; + __m = __n % __m; + __n = __last - __first; + } + + return __ret; +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator> +_ForwardIterator __pattern_rotate( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) noexcept { + return __internal::__brick_rotate(__first, __middle, __last, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator> +_RandomAccessIterator __pattern_rotate( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp; + auto __n = __last - __first; + auto __m = __middle - __first; + if (__m <= __n / 2) { + __par_backend::__buffer<_Tp> __buf(__n - __m); + return __internal::__except_handler([&__exec, __n, __m, __first, __middle, __last, &__buf]() { + _Tp* __result = __buf.get(); + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __middle, + __last, + [__middle, __result](_RandomAccessIterator __b, _RandomAccessIterator __e) { + __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __middle), _IsVector{}); + }); + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __middle, + [__last, __middle](_RandomAccessIterator __b, _RandomAccessIterator __e) { + __internal::__brick_move(__b, __e, __b + (__last - __middle), _IsVector{}); + }); + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __result, + __result + (__n - __m), + [__first, __result](_Tp* __b, _Tp* __e) { + __brick_move_destroy()(__b, __e, __first + (__b - __result), _IsVector{}); + }); + + return __first + (__last - __middle); + }); + } else { + __par_backend::__buffer<_Tp> __buf(__m); + return __internal::__except_handler([&__exec, __n, __m, __first, __middle, __last, &__buf]() { + _Tp* __result = __buf.get(); + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __middle, + [__first, __result](_RandomAccessIterator __b, _RandomAccessIterator __e) { + __internal::__brick_uninitialized_move(__b, __e, __result + (__b - __first), _IsVector{}); + }); + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __middle, + __last, + [__first, __middle](_RandomAccessIterator __b, _RandomAccessIterator __e) { + __internal::__brick_move(__b, __e, __first + (__b - __middle), _IsVector{}); + }); + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __result, + __result + __m, + [__n, __m, __first, __result](_Tp* __b, _Tp* __e) { + __brick_move_destroy()(__b, __e, __first + ((__n - __m) + (__b - __result)), _IsVector{}); + }); + + return __first + (__last - __middle); + }); + } +} + +//------------------------------------------------------------------------ +// rotate_copy +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _OutputIterator> +_OutputIterator __brick_rotate_copy( + _ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + _OutputIterator __result, + /*__is_vector=*/std::false_type) noexcept { + return std::rotate_copy(__first, __middle, __last, __result); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 __brick_rotate_copy( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __middle, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, + /*__is_vector=*/std::true_type) noexcept { + _RandomAccessIterator2 __res = __internal::__brick_copy(__middle, __last, __result, std::true_type()); + return __internal::__brick_copy(__first, __middle, __res, std::true_type()); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator> +_OutputIterator __pattern_rotate_copy( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + _OutputIterator __result) noexcept { + return __internal::__brick_rotate_copy(__first, __middle, __last, __result, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator1, class _RandomAccessIterator2> +_RandomAccessIterator2 __pattern_rotate_copy( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __middle, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__first, __last, __middle, __result](_RandomAccessIterator1 __b, _RandomAccessIterator1 __e) { + if (__b > __middle) { + __internal::__brick_copy(__b, __e, __result + (__b - __middle), _IsVector{}); + } else { + _RandomAccessIterator2 __new_result = __result + ((__last - __middle) + (__b - __first)); + if (__e < __middle) { + __internal::__brick_copy(__b, __e, __new_result, _IsVector{}); + } else { + __internal::__brick_copy(__b, __middle, __new_result, _IsVector{}); + __internal::__brick_copy(__middle, __e, __result, _IsVector{}); + } + } + }); + return __result + (__last - __first); +} + +//------------------------------------------------------------------------ +// is_partitioned +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _UnaryPredicate> +bool __brick_is_partitioned(_ForwardIterator __first, + _ForwardIterator __last, + _UnaryPredicate __pred, + /*is_vector=*/std::false_type) noexcept { + return std::is_partitioned(__first, __last, __pred); +} + +template <class _RandomAccessIterator, class _UnaryPredicate> +bool __brick_is_partitioned(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred, + /*is_vector=*/std::true_type) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType; + if (__first == __last) { + return true; + } else { + _RandomAccessIterator __result = __unseq_backend::__simd_first( + __first, _SizeType(0), __last - __first, [&__pred](_RandomAccessIterator __it, _SizeType __i) { + return !__pred(__it[__i]); + }); + if (__result == __last) { + return true; + } else { + ++__result; + return !__unseq_backend::__simd_or(__result, __last - __result, __pred); + } + } +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +bool __pattern_is_partitioned( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) noexcept { + return __internal::__brick_is_partitioned(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +bool __pattern_is_partitioned( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred) { + if (__first == __last) { + return true; + } else { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + // State of current range: + // broken - current range is not partitioned by pred + // all_true - all elements in current range satisfy pred + // all_false - all elements in current range don't satisfy pred + // true_false - elements satisfy pred are placed before elements that don't satisfy pred + enum _ReduceType { __not_init = -1, __broken, __all_true, __all_false, __true_false }; + _ReduceType __init = __not_init; + + // Array with states that we'll have when state from the left branch is merged with state from the right branch. + // State is calculated by formula: new_state = table[left_state * 4 + right_state] + _ReduceType __table[] = { + __broken, + __broken, + __broken, + __broken, + __broken, + __all_true, + __true_false, + __true_false, + __broken, + __broken, + __all_false, + __broken, + __broken, + __broken, + __true_false, + __broken}; + + __init = __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __init, + [&__pred, + &__table](_RandomAccessIterator __i, _RandomAccessIterator __j, _ReduceType __value) -> _ReduceType { + if (__value == __broken) { + return __broken; + } + _ReduceType __res = __not_init; + // if first element satisfy pred + if (__pred(*__i)) { + // find first element that don't satisfy pred + _RandomAccessIterator __x = __internal::__brick_find_if(__i + 1, __j, std::not_fn(__pred), _IsVector{}); + if (__x != __j) { + // find first element after "x" that satisfy pred + _RandomAccessIterator __y = __internal::__brick_find_if(__x + 1, __j, __pred, _IsVector{}); + // if it was found then range isn't partitioned by pred + if (__y != __j) { + return __broken; + } else { + __res = __true_false; + } + } else { + __res = __all_true; + } + } else { // if first element doesn't satisfy pred + // then we should find the first element that satisfy pred. + // If we found it then range isn't partitioned by pred + if (__internal::__brick_find_if(__i + 1, __j, __pred, _IsVector{}) != __j) { + return __broken; + } else { + __res = __all_false; + } + } + // if we have value from left range then we should calculate the result + return (__value == -1) ? __res : __table[__value * 4 + __res]; + }, + + [&__table](_ReduceType __val1, _ReduceType __val2) -> _ReduceType { + if (__val1 == __broken || __val2 == __broken) { + return __broken; + } + // calculate the result for new big range + return __table[__val1 * 4 + __val2]; + }); + return __init != __broken; + }); + } +} + +//------------------------------------------------------------------------ +// partition +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _UnaryPredicate> +_ForwardIterator __brick_partition( + _ForwardIterator __first, + _ForwardIterator __last, + _UnaryPredicate __pred, + /*is_vector=*/std::false_type) noexcept { + return std::partition(__first, __last, __pred); +} + +template <class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __brick_partition( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred, + /*is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::partition(__first, __last, __pred); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +_ForwardIterator __pattern_partition( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) noexcept { + return __internal::__brick_partition(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __pattern_partition( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + // partitioned range: elements before pivot satisfy pred (true part), + // elements after pivot don't satisfy pred (false part) + struct _PartitionRange { + _RandomAccessIterator __begin; + _RandomAccessIterator __pivot; + _RandomAccessIterator __end; + }; + + return __internal::__except_handler([&]() { + _PartitionRange __init{__last, __last, __last}; + + // lambda for merging two partitioned ranges to one partitioned range + auto __reductor = [&__exec](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange { + auto __size1 = __val1.__end - __val1.__pivot; + auto __size2 = __val2.__pivot - __val2.__begin; + auto __new_begin = __val2.__begin - (__val1.__end - __val1.__begin); + + // if all elements in left range satisfy pred then we can move new pivot to pivot of right range + if (__val1.__end == __val1.__pivot) { + return {__new_begin, __val2.__pivot, __val2.__end}; + } + // if true part of right range greater than false part of left range + // then we should swap the false part of left range and last part of true part of right range + else if (__size2 > __size1) { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __val1.__pivot, + __val1.__pivot + __size1, + [__val1, __val2, __size1](_RandomAccessIterator __i, _RandomAccessIterator __j) { + __internal::__brick_swap_ranges( + __i, __j, (__val2.__pivot - __size1) + (__i - __val1.__pivot), _IsVector{}); + }); + return {__new_begin, __val2.__pivot - __size1, __val2.__end}; + } + // else we should swap the first part of false part of left range and true part of right range + else { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __val1.__pivot, + __val1.__pivot + __size2, + [__val1, __val2](_RandomAccessIterator __i, _RandomAccessIterator __j) { + __internal::__brick_swap_ranges(__i, __j, __val2.__begin + (__i - __val1.__pivot), _IsVector{}); + }); + return {__new_begin, __val1.__pivot + __size2, __val2.__end}; + } + }; + + _PartitionRange __result = __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __init, + [__pred, + __reductor](_RandomAccessIterator __i, _RandomAccessIterator __j, _PartitionRange __value) -> _PartitionRange { + // 1. serial partition + _RandomAccessIterator __pivot = __internal::__brick_partition(__i, __j, __pred, _IsVector{}); + + // 2. merging of two ranges (left and right respectively) + return __reductor(__value, {__i, __pivot, __j}); + }, + __reductor); + return __result.__pivot; + }); +} + +//------------------------------------------------------------------------ +// stable_partition +//------------------------------------------------------------------------ + +template <class _BidirectionalIterator, class _UnaryPredicate> +_BidirectionalIterator __brick_stable_partition( + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _UnaryPredicate __pred, + /*__is_vector=*/std::false_type) noexcept { + return std::stable_partition(__first, __last, __pred); +} + +template <class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __brick_stable_partition( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred, + /*__is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::stable_partition(__first, __last, __pred); +} + +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate> +_BidirectionalIterator __pattern_stable_partition( + _Tag, + _ExecutionPolicy&&, + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _UnaryPredicate __pred) noexcept { + return __internal::__brick_stable_partition(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __pattern_stable_partition( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + // partitioned range: elements before pivot satisfy pred (true part), + // elements after pivot don't satisfy pred (false part) + struct _PartitionRange { + _RandomAccessIterator __begin; + _RandomAccessIterator __pivot; + _RandomAccessIterator __end; + }; + + return __internal::__except_handler([&]() { + _PartitionRange __init{__last, __last, __last}; + + // lambda for merging two partitioned ranges to one partitioned range + auto __reductor = [](_PartitionRange __val1, _PartitionRange __val2) -> _PartitionRange { + auto __size1 = __val1.__end - __val1.__pivot; + auto __new_begin = __val2.__begin - (__val1.__end - __val1.__begin); + + // if all elements in left range satisfy pred then we can move new pivot to pivot of right range + if (__val1.__end == __val1.__pivot) { + return {__new_begin, __val2.__pivot, __val2.__end}; + } + // if true part of right range greater than false part of left range + // then we should swap the false part of left range and last part of true part of right range + else { + __internal::__brick_rotate(__val1.__pivot, __val2.__begin, __val2.__pivot, _IsVector{}); + return {__new_begin, __val2.__pivot - __size1, __val2.__end}; + } + }; + + _PartitionRange __result = __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __init, + [&__pred, + __reductor](_RandomAccessIterator __i, _RandomAccessIterator __j, _PartitionRange __value) -> _PartitionRange { + // 1. serial stable_partition + _RandomAccessIterator __pivot = __internal::__brick_stable_partition(__i, __j, __pred, _IsVector{}); + + // 2. merging of two ranges (left and right respectively) + return __reductor(__value, {__i, __pivot, __j}); + }, + __reductor); + return __result.__pivot; + }); +} + +//------------------------------------------------------------------------ +// partition_copy +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _OutputIterator1, class _OutputIterator2, class _UnaryPredicate> +std::pair<_OutputIterator1, _OutputIterator2> __brick_partition_copy( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator1 __out_true, + _OutputIterator2 __out_false, + _UnaryPredicate __pred, + /*is_vector=*/std::false_type) noexcept { + return std::partition_copy(__first, __last, __out_true, __out_false, __pred); +} + +template <class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _RandomAccessIterator3, + class _UnaryPredicate> +std::pair<_RandomAccessIterator2, _RandomAccessIterator3> __brick_partition_copy( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __out_true, + _RandomAccessIterator3 __out_false, + _UnaryPredicate __pred, + /*is_vector=*/std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + return __unseq_backend::__simd_partition_copy(__first, __last - __first, __out_true, __out_false, __pred); +#else + return std::partition_copy(__first, __last, __out_true, __out_false, __pred); +#endif +} + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator, + class _OutputIterator1, + class _OutputIterator2, + class _UnaryPredicate> +std::pair<_OutputIterator1, _OutputIterator2> __pattern_partition_copy( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator1 __out_true, + _OutputIterator2 __out_false, + _UnaryPredicate __pred) noexcept { + return __internal::__brick_partition_copy( + __first, __last, __out_true, __out_false, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _RandomAccessIterator3, + class _UnaryPredicate> +std::pair<_RandomAccessIterator2, _RandomAccessIterator3> __pattern_partition_copy( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __out_true, + _RandomAccessIterator3 __out_false, + _UnaryPredicate __pred) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; + typedef std::pair<_DifferenceType, _DifferenceType> _ReturnType; + const _DifferenceType __n = __last - __first; + if (_DifferenceType(1) < __n) { + __par_backend::__buffer<bool> __mask_buf(__n); + return __internal::__except_handler([&__exec, __n, __first, __out_true, __out_false, __pred, &__mask_buf]() { + bool* __mask = __mask_buf.get(); + _ReturnType __m{}; + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n, + std::make_pair(_DifferenceType(0), _DifferenceType(0)), + [=](_DifferenceType __i, _DifferenceType __len) { // Reduce + return __internal::__brick_calc_mask_1<_DifferenceType>( + __first + __i, __first + (__i + __len), __mask + __i, __pred, _IsVector{}); + }, + [](const _ReturnType& __x, const _ReturnType& __y) -> _ReturnType { + return std::make_pair(__x.first + __y.first, __x.second + __y.second); + }, // Combine + [=](_DifferenceType __i, _DifferenceType __len, _ReturnType __initial) { // Scan + __internal::__brick_partition_by_mask( + __first + __i, + __first + (__i + __len), + __out_true + __initial.first, + __out_false + __initial.second, + __mask + __i, + _IsVector{}); + }, + [&__m](_ReturnType __total) { __m = __total; }); + return std::make_pair(__out_true + __m.first, __out_false + __m.second); + }); + } + // trivial sequence - use serial algorithm + return __internal::__brick_partition_copy(__first, __last, __out_true, __out_false, __pred, _IsVector{}); +} + +//------------------------------------------------------------------------ +// sort +//------------------------------------------------------------------------ + +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare, class _IsMoveConstructible> +void __pattern_sort(_Tag, + _ExecutionPolicy&&, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + _IsMoveConstructible) noexcept { + std::sort(__first, __last, __comp); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_sort(__parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + /*is_move_constructible=*/std::true_type) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler([&]() { + __par_backend::__parallel_stable_sort( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __comp, + [](_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + std::sort(__first, __last, __comp); + }); + }); +} + +//------------------------------------------------------------------------ +// stable_sort +//------------------------------------------------------------------------ + +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_stable_sort( + _Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) noexcept { + std::stable_sort(__first, __last, __comp); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_stable_sort( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + __internal::__except_handler([&]() { + __par_backend::__parallel_stable_sort( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __comp, + [](_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + std::stable_sort(__first, __last, __comp); + }); + }); +} + +//------------------------------------------------------------------------ +// partial_sort +//------------------------------------------------------------------------ + +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_partial_sort( + _Tag, + _ExecutionPolicy&&, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) noexcept { + std::partial_sort(__first, __middle, __last, __comp); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_partial_sort( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + const auto __n = __middle - __first; + if (__n == 0) + return; + + __internal::__except_handler([&]() { + __par_backend::__parallel_stable_sort( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __comp, + [__n](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Compare __comp) { + if (__n < __end - __begin) + std::partial_sort(__begin, __begin + __n, __end, __comp); + else + std::sort(__begin, __end, __comp); + }, + __n); + }); +} + +//------------------------------------------------------------------------ +// partial_sort_copy +//------------------------------------------------------------------------ + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare> +_RandomAccessIterator __pattern_partial_sort_copy( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _RandomAccessIterator __d_first, + _RandomAccessIterator __d_last, + _Compare __comp) noexcept { + return std::partial_sort_copy(__first, __last, __d_first, __d_last, __comp); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Compare> +_RandomAccessIterator2 __pattern_partial_sort_copy( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first, + _RandomAccessIterator2 __d_last, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__last == __first || __d_last == __d_first) { + return __d_first; + } + auto __n1 = __last - __first; + auto __n2 = __d_last - __d_first; + return __internal::__except_handler([&]() { + if (__n2 >= __n1) { + __par_backend::__parallel_stable_sort( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __d_first, + __d_first + __n1, + __comp, + [__first, __d_first](_RandomAccessIterator2 __i, _RandomAccessIterator2 __j, _Compare __comp) { + _RandomAccessIterator1 __i1 = __first + (__i - __d_first); + _RandomAccessIterator1 __j1 = __first + (__j - __d_first); + + // 1. Copy elements from input to output +#if !defined(_PSTL_ICC_18_OMP_SIMD_BROKEN) + __internal::__brick_copy(__i1, __j1, __i, _IsVector{}); +#else + std::copy(__i1, __j1, __i); +#endif + // 2. Sort elements in output sequence + std::sort(__i, __j, __comp); + }, + __n1); + return __d_first + __n1; + } else { + typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type _T1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::value_type _T2; + __par_backend::__buffer<_T1> __buf(__n1); + _T1* __r = __buf.get(); + + __par_backend::__parallel_stable_sort( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __r, + __r + __n1, + __comp, + [__n2, __first, __r](_T1* __i, _T1* __j, _Compare __comp) { + _RandomAccessIterator1 __it = __first + (__i - __r); + + // 1. Copy elements from input to raw memory + for (_T1* __k = __i; __k != __j; ++__k, ++__it) { + ::new (__k) _T2(*__it); + } + + // 2. Sort elements in temporary __buffer + if (__n2 < __j - __i) + std::partial_sort(__i, __i + __n2, __j, __comp); + else + std::sort(__i, __j, __comp); + }, + __n2); + + // 3. Move elements from temporary __buffer to output + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __r, + __r + __n2, + [__r, __d_first](_T1* __i, _T1* __j) { + __brick_move_destroy()(__i, __j, __d_first + (__i - __r), _IsVector{}); + }); + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r + __n2, __r + __n1, [](_T1* __i, _T1* __j) { + __brick_destroy(__i, __j, _IsVector{}); + }); + + return __d_first + __n2; + } + }); +} + +//------------------------------------------------------------------------ +// adjacent_find +//------------------------------------------------------------------------ +template <class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator __brick_adjacent_find( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _BinaryPredicate __pred, + /* IsVector = */ std::true_type, + bool __or_semantic) noexcept { + return __unseq_backend::__simd_adjacent_find(__first, __last, __pred, __or_semantic); +} + +template <class _ForwardIterator, class _BinaryPredicate> +_ForwardIterator __brick_adjacent_find( + _ForwardIterator __first, + _ForwardIterator __last, + _BinaryPredicate __pred, + /* IsVector = */ std::false_type, + bool) noexcept { + return std::adjacent_find(__first, __last, __pred); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> +_ForwardIterator __pattern_adjacent_find( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _BinaryPredicate __pred, + bool __or_semantic) noexcept { + return __internal::__brick_adjacent_find(__first, __last, __pred, typename _Tag::__is_vector{}, __or_semantic); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _BinaryPredicate> +_RandomAccessIterator __pattern_adjacent_find( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _BinaryPredicate __pred, + bool __or_semantic) { + if (__last - __first < 2) + return __last; + + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + return __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __last, + [__last, __pred, __or_semantic]( + _RandomAccessIterator __begin, _RandomAccessIterator __end, _RandomAccessIterator __value) + -> _RandomAccessIterator { + // TODO: investigate performance benefits from the use of shared variable for the result, + // checking (compare_and_swap idiom) its __value at __first. + if (__or_semantic && __value < __last) { // found + __par_backend::__cancel_execution(); + return __value; + } + + if (__value > __begin) { + // modify __end to check the predicate on the boundary __values; + // TODO: to use a custom range with boundaries overlapping + // TODO: investigate what if we remove "if" below and run algorithm on range [__first, __last-1) + // then check the pair [__last-1, __last) + if (__end != __last) + ++__end; + + // correct the global result iterator if the "brick" returns a local "__last" + const _RandomAccessIterator __res = + __internal::__brick_adjacent_find(__begin, __end, __pred, _IsVector{}, __or_semantic); + if (__res < __end) + __value = __res; + } + return __value; + }, + [](_RandomAccessIterator __x, _RandomAccessIterator __y) -> _RandomAccessIterator { + return __x < __y ? __x : __y; + } // reduce a __value + ); + }); +} + +//------------------------------------------------------------------------ +// nth_element +//------------------------------------------------------------------------ + +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_nth_element( + _Tag, + _ExecutionPolicy&&, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last, + _Compare __comp) noexcept { + std::nth_element(__first, __nth, __last, __comp); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_nth_element( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last, + _Compare __comp) noexcept { + if (__first == __last || __nth == __last) { + return; + } + + using std::iter_swap; + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp; + _RandomAccessIterator __x; + do { + __x = __internal::__pattern_partition( + __tag, std::forward<_ExecutionPolicy>(__exec), __first + 1, __last, [&__comp, __first](const _Tp& __x) { + return __comp(__x, *__first); + }); + --__x; + if (__x != __first) { + iter_swap(__first, __x); + } + // if x > nth then our new range for partition is [first, x) + if (__x - __nth > 0) { + __last = __x; + } + // if x < nth then our new range for partition is [x, last) + else if (__x - __nth < 0) { + // if *x == *nth then we can start new partition with x+1 + if (!__comp(*__nth, *__x) && !__comp(*__x, *__nth)) { + ++__x; + } else { + iter_swap(__nth, __x); + } + __first = __x; + } + } while (__x != __nth); +} + +//------------------------------------------------------------------------ +// generate, generate_n +//------------------------------------------------------------------------ +template <class _RandomAccessIterator, class _Generator> +void __brick_generate(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Generator __g, + /* is_vector = */ std::true_type) noexcept { + __unseq_backend::__simd_generate_n(__first, __last - __first, __g); +} + +template <class _ForwardIterator, class _Generator> +void __brick_generate(_ForwardIterator __first, + _ForwardIterator __last, + _Generator __g, + /* is_vector = */ std::false_type) noexcept { + std::generate(__first, __last, __g); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _Generator> +void __pattern_generate( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Generator __g) noexcept { + __internal::__brick_generate(__first, __last, __g, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Generator> +_RandomAccessIterator __pattern_generate( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Generator __g) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__g](_RandomAccessIterator __begin, _RandomAccessIterator __end) { + __internal::__brick_generate(__begin, __end, __g, _IsVector{}); + }); + return __last; + }); +} + +template <class _RandomAccessIterator, class Size, class _Generator> +_RandomAccessIterator __brick_generate_n( + _RandomAccessIterator __first, + Size __count, + _Generator __g, + /* is_vector = */ std::true_type) noexcept { + return __unseq_backend::__simd_generate_n(__first, __count, __g); +} + +template <class OutputIterator, class Size, class _Generator> +OutputIterator +__brick_generate_n(OutputIterator __first, Size __count, _Generator __g, /* is_vector = */ std::false_type) noexcept { + return std::generate_n(__first, __count, __g); +} + +template <class _Tag, class _ExecutionPolicy, class _OutputIterator, class _Size, class _Generator> +_OutputIterator +__pattern_generate_n(_Tag, _ExecutionPolicy&&, _OutputIterator __first, _Size __count, _Generator __g) noexcept { + return __internal::__brick_generate_n(__first, __count, __g, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Size, class _Generator> +_RandomAccessIterator __pattern_generate_n( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _Size __count, + _Generator __g) { + static_assert(__are_random_access_iterators<_RandomAccessIterator>::value, + "Pattern-brick error. Should be a random access iterator."); + return __internal::__pattern_generate(__tag, std::forward<_ExecutionPolicy>(__exec), __first, __first + __count, __g); +} + +//------------------------------------------------------------------------ +// remove +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _UnaryPredicate> +_ForwardIterator __brick_remove_if( + _ForwardIterator __first, + _ForwardIterator __last, + _UnaryPredicate __pred, + /* __is_vector = */ std::false_type) noexcept { + return std::remove_if(__first, __last, __pred); +} + +template <class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __brick_remove_if( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred, + /* __is_vector = */ std::true_type) noexcept { +#if defined(_PSTL_MONOTONIC_PRESENT) + return __unseq_backend::__simd_remove_if(__first, __last - __first, __pred); +#else + return std::remove_if(__first, __last, __pred); +#endif +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +_ForwardIterator __pattern_remove_if( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) noexcept { + return __internal::__brick_remove_if(__first, __last, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryPredicate> +_RandomAccessIterator __pattern_remove_if( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _UnaryPredicate __pred) noexcept { + typedef typename std::iterator_traits<_RandomAccessIterator>::reference _ReferenceType; + + if (__first == __last || __first + 1 == __last) { + // Trivial sequence - use serial algorithm + return __internal::__brick_remove_if(__first, __last, __pred, _IsVector{}); + } + + return __internal::__remove_elements( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [&__pred](bool* __b, bool* __e, _RandomAccessIterator __it) { + __internal::__brick_walk2( + __b, __e, __it, [&__pred](bool& __x, _ReferenceType __y) { __x = !__pred(__y); }, _IsVector{}); + }); +} + +//------------------------------------------------------------------------ +// inplace_merge +//------------------------------------------------------------------------ +template <class _BidirectionalIterator, class _Compare> +void __brick_inplace_merge( + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + std::inplace_merge(__first, __middle, __last, __comp); +} + +template <class _RandomAccessIterator, class _Compare> +void __brick_inplace_merge( + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { + // TODO: vectorize + std::inplace_merge(__first, __middle, __last, __comp); +} + +template <class _Tag, class _ExecutionPolicy, class _BidirectionalIterator, class _Compare> +void __pattern_inplace_merge( + _Tag, + _ExecutionPolicy&&, + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp) noexcept { + __internal::__brick_inplace_merge(__first, __middle, __last, __comp, typename _Tag::__is_vector{}); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +void __pattern_inplace_merge( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__first == __last || __first == __middle || __middle == __last) { + return; + } + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _Tp; + auto __n = __last - __first; + __par_backend::__buffer<_Tp> __buf(__n); + _Tp* __r = __buf.get(); + __internal::__except_handler([&]() { + auto __move_values = [](_RandomAccessIterator __x, _Tp* __z) { + __internal::__invoke_if_else( + std::is_trivial<_Tp>(), + [&]() { *__z = std::move(*__x); }, + [&]() { ::new (std::addressof(*__z)) _Tp(std::move(*__x)); }); + }; + + auto __move_sequences = [](_RandomAccessIterator __first1, _RandomAccessIterator __last1, _Tp* __first2) { + return __internal::__brick_uninitialized_move(__first1, __last1, __first2, _IsVector()); + }; + + __par_backend::__parallel_merge( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __middle, + __middle, + __last, + __r, + __comp, + [__n, __move_values, __move_sequences]( + _RandomAccessIterator __f1, + _RandomAccessIterator __l1, + _RandomAccessIterator __f2, + _RandomAccessIterator __l2, + _Tp* __f3, + _Compare __comp) { + (__utils::__serial_move_merge(__n))( + __f1, __l1, __f2, __l2, __f3, __comp, __move_values, __move_values, __move_sequences, __move_sequences); + return __f3 + (__l1 - __f1) + (__l2 - __f2); + }); + __par_backend::__parallel_for( + __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __r, __r + __n, [__r, __first](_Tp* __i, _Tp* __j) { + __brick_move_destroy()(__i, __j, __first + (__i - __r), _IsVector{}); + }); + }); +} + +//------------------------------------------------------------------------ +// includes +//------------------------------------------------------------------------ + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> +bool __pattern_includes( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp) noexcept { + return std::includes(__first1, __last1, __first2, __last2, __comp); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Compare> +bool __pattern_includes( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Compare __comp) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__first2 >= __last2) + return true; + + if (__first1 >= __last1 || __comp(*__first2, *__first1) || __comp(*(__last1 - 1), *(__last2 - 1))) + return false; + + __first1 = std::lower_bound(__first1, __last1, *__first2, __comp); + if (__first1 == __last1) + return false; + + if (__last2 - __first2 == 1) + return !__comp(*__first1, *__first2) && !__comp(*__first2, *__first1); + + return __internal::__except_handler([&]() { + return !__internal::__parallel_or( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first2, + __last2, + [__first1, __last1, __first2, __last2, &__comp](_RandomAccessIterator2 __i, _RandomAccessIterator2 __j) { + _LIBCPP_ASSERT_UNCATEGORIZED(__j > __i, ""); + //_LIBCPP_ASSERT_UNCATEGORIZED(__j - __i > 1, ""); + + // 1. moving boundaries to "consume" subsequence of equal elements + auto __is_equal = [&__comp](_RandomAccessIterator2 __a, _RandomAccessIterator2 __b) -> bool { + return !__comp(*__a, *__b) && !__comp(*__b, *__a); + }; + + // 1.1 left bound, case "aaa[aaaxyz...]" - searching "x" + if (__i > __first2 && __is_equal(__i, __i - 1)) { + // whole subrange continues to content equal elements - return "no op" + if (__is_equal(__i, __j - 1)) + return false; + + __i = std::upper_bound(__i, __last2, *__i, __comp); + } + + // 1.2 right bound, case "[...aaa]aaaxyz" - searching "x" + if (__j < __last2 && __is_equal(__j - 1, __j)) + __j = std::upper_bound(__j, __last2, *__j, __comp); + + // 2. testing is __a subsequence of the second range included into the first range + auto __b = std::lower_bound(__first1, __last1, *__i, __comp); + + _LIBCPP_ASSERT_UNCATEGORIZED(!__comp(*(__last1 - 1), *__b), ""); + _LIBCPP_ASSERT_UNCATEGORIZED(!__comp(*(__j - 1), *__i), ""); + return !std::includes(__b, __last1, __i, __j, __comp); + }); + }); +} + +constexpr auto __set_algo_cut_off = 1000; + +template <class _IsVector, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare, + class _SizeFunction, + class _SetOP> +_OutputIterator __parallel_set_op( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + _SizeFunction __size_func, + _SetOP __set_op) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType; + typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp; + + struct _SetRange { + _DifferenceType __pos, __len, __buf_pos; + bool empty() const { return __len == 0; } + }; + + const _DifferenceType __n1 = __last1 - __first1; + const _DifferenceType __n2 = __last2 - __first2; + + __par_backend::__buffer<_Tp> __buf(__size_func(__n1, __n2)); + + return __internal::__except_handler( + [&__exec, __n1, __first1, __last1, __first2, __last2, __result, __comp, __size_func, __set_op, &__buf]() { + auto __buffer = __buf.get(); + _DifferenceType __m{}; + auto __scan = [=](_DifferenceType, _DifferenceType, const _SetRange& __s) { // Scan + if (!__s.empty()) + __brick_move_destroy()( + __buffer + __s.__buf_pos, __buffer + (__s.__buf_pos + __s.__len), __result + __s.__pos, _IsVector{}); + }; + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n1, + _SetRange{0, 0, 0}, //-1, 0}, + [=](_DifferenceType __i, _DifferenceType __len) { // Reduce + //[__b; __e) - a subrange of the first sequence, to reduce + _ForwardIterator1 __b = __first1 + __i, __e = __first1 + (__i + __len); + + // try searching for the first element which not equal to *__b + if (__b != __first1) + __b = std::upper_bound(__b, __last1, *__b, __comp); + + // try searching for the first element which not equal to *__e + if (__e != __last1) + __e = std::upper_bound(__e, __last1, *__e, __comp); + + // check is [__b; __e) empty + if (__e - __b < 1) { + _ForwardIterator2 __bb = __last2; + if (__b != __last1) + __bb = std::lower_bound(__first2, __last2, *__b, __comp); + + const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2)); + return _SetRange{0, 0, __buf_pos}; + } + + // try searching for "corresponding" subrange [__bb; __ee) in the second sequence + _ForwardIterator2 __bb = __first2; + if (__b != __first1) + __bb = std::lower_bound(__first2, __last2, *__b, __comp); + + _ForwardIterator2 __ee = __last2; + if (__e != __last1) + __ee = std::lower_bound(__bb, __last2, *__e, __comp); + + const _DifferenceType __buf_pos = __size_func((__b - __first1), (__bb - __first2)); + auto __buffer_b = __buffer + __buf_pos; + auto __res = __set_op(__b, __e, __bb, __ee, __buffer_b, __comp); + + return _SetRange{0, __res - __buffer_b, __buf_pos}; + }, + [](const _SetRange& __a, const _SetRange& __b) { // Combine + if (__b.__buf_pos > __a.__buf_pos || ((__b.__buf_pos == __a.__buf_pos) && !__b.empty())) + return _SetRange{__a.__pos + __a.__len + __b.__pos, __b.__len, __b.__buf_pos}; + return _SetRange{__b.__pos + __b.__len + __a.__pos, __a.__len, __a.__buf_pos}; + }, + __scan, // Scan + [&__m, &__scan](const _SetRange& __total) { // Apex + // final scan + __scan(0, 0, __total); + __m = __total.__pos + __total.__len; + }); + return __result + __m; + }); +} + +// a shared parallel pattern for '__pattern_set_union' and '__pattern_set_symmetric_difference' +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare, + class _SetUnionOp> +_OutputIterator __parallel_set_union_op( + _Tag __tag, + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + _SetUnionOp __set_union_op) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType; + + const auto __n1 = __last1 - __first1; + const auto __n2 = __last2 - __first2; + + auto copy_range1 = [](_ForwardIterator1 __begin, _ForwardIterator1 __end, _OutputIterator __res) { + return __internal::__brick_copy(__begin, __end, __res, typename _Tag::__is_vector{}); + }; + auto copy_range2 = [](_ForwardIterator2 __begin, _ForwardIterator2 __end, _OutputIterator __res) { + return __internal::__brick_copy(__begin, __end, __res, typename _Tag::__is_vector{}); + }; + + // {1} {}: parallel copying just first sequence + if (__n2 == 0) + return __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, copy_range1); + + // {} {2}: parallel copying justmake second sequence + if (__n1 == 0) + return __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result, copy_range2); + + // testing whether the sequences are intersected + _ForwardIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); + + if (__left_bound_seq_1 == __last1) { + //{1} < {2}: seq2 is wholly greater than seq1, so, do parallel copying seq1 and seq2 + __par_backend::__parallel_invoke( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result, copy_range1); + }, + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result + __n1, copy_range2); + }); + return __result + __n1 + __n2; + } + + // testing whether the sequences are intersected + _ForwardIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp); + + if (__left_bound_seq_2 == __last2) { + //{2} < {1}: seq2 is wholly greater than seq1, so, do parallel copying seq1 and seq2 + __par_backend::__parallel_invoke( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first2, __last2, __result, copy_range2); + }, + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __result + __n2, copy_range1); + }); + return __result + __n1 + __n2; + } + + const auto __m1 = __left_bound_seq_1 - __first1; + if (__m1 > __set_algo_cut_off) { + auto __res_or = __result; + __result += __m1; // we know proper offset due to [first1; left_bound_seq_1) < [first2; last2) + __par_backend::__parallel_invoke( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + // do parallel copying of [first1; left_bound_seq_1) + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first1, __left_bound_seq_1, __res_or, copy_range1); + }, + [=, &__result] { + __result = __internal::__parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __left_bound_seq_1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, + __set_union_op); + }); + return __result; + } + + const auto __m2 = __left_bound_seq_2 - __first2; + _LIBCPP_ASSERT_UNCATEGORIZED(__m1 == 0 || __m2 == 0, ""); + if (__m2 > __set_algo_cut_off) { + auto __res_or = __result; + __result += __m2; // we know proper offset due to [first2; left_bound_seq_2) < [first1; last1) + __par_backend::__parallel_invoke( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + // do parallel copying of [first2; left_bound_seq_2) + [=] { + __internal::__pattern_walk2_brick( + __tag, std::forward<_ExecutionPolicy>(__exec), __first2, __left_bound_seq_2, __res_or, copy_range2); + }, + [=, &__result] { + __result = __internal::__parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __left_bound_seq_2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, + __set_union_op); + }); + return __result; + } + + return __internal::__parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType __m) { return __n + __m; }, + __set_union_op); +} + +//------------------------------------------------------------------------ +// set_union +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_union( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + /*__is_vector=*/std::false_type) noexcept { + return std::set_union(__first1, __last1, __first2, __last2, __result, __comp); +} + +template <typename _IsVector> +struct __BrickCopyConstruct { + template <typename _ForwardIterator, typename _OutputIterator> + _OutputIterator operator()(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result) { + return __brick_uninitialized_copy(__first, __last, __result, _IsVector()); + } +}; + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_union( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + /*__is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::set_union(__first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_union( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp) noexcept { + return __internal::__brick_set_union( + __first1, __last1, __first2, __last2, __result, __comp, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_union( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _OutputIterator __result, + _Compare __comp) { + const auto __n1 = __last1 - __first1; + const auto __n2 = __last2 - __first2; + + // use serial algorithm + if (__n1 + __n2 <= __set_algo_cut_off) + return std::set_union(__first1, __last1, __first2, __last2, __result, __comp); + + typedef typename std::iterator_traits<_OutputIterator>::value_type _Tp; + return __parallel_set_union_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Tp* __result, + _Compare __comp) { + return __pstl::__utils::__set_union_construct( + __first1, __last1, __first2, __last2, __result, __comp, __BrickCopyConstruct<_IsVector>()); + }); +} + +//------------------------------------------------------------------------ +// set_intersection +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_intersection( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + /*__is_vector=*/std::false_type) noexcept { + return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 __brick_set_intersection( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp, + /*__is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::set_intersection(__first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_intersection( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp) noexcept { + return __internal::__brick_set_intersection( + __first1, __last1, __first2, __last2, __result, __comp, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _RandomAccessIterator3, + class _Compare> +_RandomAccessIterator3 __pattern_set_intersection( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp) { + typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp; + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; + + const auto __n1 = __last1 - __first1; + const auto __n2 = __last2 - __first2; + + // intersection is empty + if (__n1 == 0 || __n2 == 0) + return __result; + + // testing whether the sequences are intersected + _RandomAccessIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); + //{1} < {2}: seq 2 is wholly greater than seq 1, so, the intersection is empty + if (__left_bound_seq_1 == __last1) + return __result; + + // testing whether the sequences are intersected + _RandomAccessIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp); + //{2} < {1}: seq 1 is wholly greater than seq 2, so, the intersection is empty + if (__left_bound_seq_2 == __last2) + return __result; + + const auto __m1 = __last1 - __left_bound_seq_1 + __n2; + if (__m1 > __set_algo_cut_off) { + // we know proper offset due to [first1; left_bound_seq_1) < [first2; last2) + return __internal::__parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __left_bound_seq_1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); }, + [](_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Tp* __result, + _Compare __comp) { + return __pstl::__utils::__set_intersection_construct(__first1, __last1, __first2, __last2, __result, __comp); + }); + } + + const auto __m2 = __last2 - __left_bound_seq_2 + __n1; + if (__m2 > __set_algo_cut_off) { + // we know proper offset due to [first2; left_bound_seq_2) < [first1; last1) + __result = __internal::__parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __left_bound_seq_2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType __m) { return std::min(__n, __m); }, + [](_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Tp* __result, + _Compare __comp) { + return __pstl::__utils::__set_intersection_construct(__first2, __last2, __first1, __last1, __result, __comp); + }); + return __result; + } + + // [left_bound_seq_1; last1) and [left_bound_seq_2; last2) - use serial algorithm + return std::set_intersection(__left_bound_seq_1, __last1, __left_bound_seq_2, __last2, __result, __comp); +} + +//------------------------------------------------------------------------ +// set_difference +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_difference( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + /*__is_vector=*/std::false_type) noexcept { + return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 __brick_set_difference( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp, + /*__is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_difference( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp) noexcept { + return __internal::__brick_set_difference( + __first1, __last1, __first2, __last2, __result, __comp, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _RandomAccessIterator3, + class _Compare> +_RandomAccessIterator3 __pattern_set_difference( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp) { + typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp; + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType; + + const auto __n1 = __last1 - __first1; + const auto __n2 = __last2 - __first2; + + // {} \ {2}: the difference is empty + if (__n1 == 0) + return __result; + + // {1} \ {}: parallel copying just first sequence + if (__n2 == 0) + return __internal::__pattern_walk2_brick( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __result, + [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res) { + return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); + }); + + // testing whether the sequences are intersected + _RandomAccessIterator1 __left_bound_seq_1 = std::lower_bound(__first1, __last1, *__first2, __comp); + //{1} < {2}: seq 2 is wholly greater than seq 1, so, parallel copying just first sequence + if (__left_bound_seq_1 == __last1) + return __internal::__pattern_walk2_brick( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __result, + [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res) { + return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); + }); + + // testing whether the sequences are intersected + _RandomAccessIterator2 __left_bound_seq_2 = std::lower_bound(__first2, __last2, *__first1, __comp); + //{2} < {1}: seq 1 is wholly greater than seq 2, so, parallel copying just first sequence + if (__left_bound_seq_2 == __last2) + return __internal::__pattern_walk2_brick( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __result, + [](_RandomAccessIterator1 __begin, _RandomAccessIterator1 __end, _RandomAccessIterator3 __res) { + return __internal::__brick_copy(__begin, __end, __res, _IsVector{}); + }); + + if (__n1 + __n2 > __set_algo_cut_off) + return __parallel_set_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_DifferenceType __n, _DifferenceType) { return __n; }, + [](_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Tp* __result, + _Compare __comp) { + return __pstl::__utils::__set_difference_construct( + __first1, __last1, __first2, __last2, __result, __comp, __BrickCopyConstruct<_IsVector>()); + }); + + // use serial algorithm + return std::set_difference(__first1, __last1, __first2, __last2, __result, __comp); +} + +//------------------------------------------------------------------------ +// set_symmetric_difference +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _OutputIterator, class _Compare> +_OutputIterator __brick_set_symmetric_difference( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp, + /*__is_vector=*/std::false_type) noexcept { + return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare> +_RandomAccessIterator3 __brick_set_symmetric_difference( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp, + /*__is_vector=*/std::true_type) noexcept { + // TODO: vectorize + return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _OutputIterator, + class _Compare> +_OutputIterator __pattern_set_symmetric_difference( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _OutputIterator __result, + _Compare __comp) noexcept { + return __internal::__brick_set_symmetric_difference( + __first1, __last1, __first2, __last2, __result, __comp, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _RandomAccessIterator3, + class _Compare> +_RandomAccessIterator3 __pattern_set_symmetric_difference( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _RandomAccessIterator3 __result, + _Compare __comp) { + const auto __n1 = __last1 - __first1; + const auto __n2 = __last2 - __first2; + + // use serial algorithm + if (__n1 + __n2 <= __set_algo_cut_off) + return std::set_symmetric_difference(__first1, __last1, __first2, __last2, __result, __comp); + + typedef typename std::iterator_traits<_RandomAccessIterator3>::value_type _Tp; + return __internal::__parallel_set_union_op( + __tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + __last2, + __result, + __comp, + [](_RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Tp* __result, + _Compare __comp) { + return __pstl::__utils::__set_symmetric_difference_construct( + __first1, __last1, __first2, __last2, __result, __comp, __BrickCopyConstruct<_IsVector>()); + }); +} + +//------------------------------------------------------------------------ +// is_heap_until +//------------------------------------------------------------------------ + +template <class _RandomAccessIterator, class _Compare> +_RandomAccessIterator __brick_is_heap_until( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + return std::is_heap_until(__first, __last, __comp); +} + +template <class _RandomAccessIterator, class _Compare> +_RandomAccessIterator __brick_is_heap_until( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { + if (__last - __first < 2) + return __last; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _SizeType; + return __unseq_backend::__simd_first( + __first, _SizeType(0), __last - __first, [&__comp](_RandomAccessIterator __it, _SizeType __i) { + return __comp(__it[(__i - 1) / 2], __it[__i]); + }); +} + +template <class _Tag, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +_RandomAccessIterator __pattern_is_heap_until( + _Tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) noexcept { + return __internal::__brick_is_heap_until(__first, __last, __comp, typename _Tag::__is_vector{}); +} + +template <class _RandomAccessIterator, class _DifferenceType, class _Compare> +_RandomAccessIterator __is_heap_until_local( + _RandomAccessIterator __first, + _DifferenceType __begin, + _DifferenceType __end, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + _DifferenceType __i = __begin; + for (; __i < __end; ++__i) { + if (__comp(__first[(__i - 1) / 2], __first[__i])) { + break; + } + } + return __first + __i; +} + +template <class _RandomAccessIterator, class _DifferenceType, class _Compare> +_RandomAccessIterator __is_heap_until_local( + _RandomAccessIterator __first, + _DifferenceType __begin, + _DifferenceType __end, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { + return __unseq_backend::__simd_first( + __first, __begin, __end, [&__comp](_RandomAccessIterator __it, _DifferenceType __i) { + return __comp(__it[(__i - 1) / 2], __it[__i]); + }); +} + +template <class _IsVector, class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +_RandomAccessIterator __pattern_is_heap_until( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__last - __first < 2) + return __last; + + return __internal::__except_handler([&]() { + return __parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [__first, __comp](_RandomAccessIterator __i, _RandomAccessIterator __j) { + return __internal::__is_heap_until_local(__first, __i - __first, __j - __first, __comp, _IsVector{}); + }, + std::less<typename std::iterator_traits<_RandomAccessIterator>::difference_type>(), + /*is_first=*/true); + }); +} + +//------------------------------------------------------------------------ +// min_element +//------------------------------------------------------------------------ + +template <typename _ForwardIterator, typename _Compare> +_ForwardIterator __brick_min_element( + _ForwardIterator __first, + _ForwardIterator __last, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + return std::min_element(__first, __last, __comp); +} + +template <typename _RandomAccessIterator, typename _Compare> +_RandomAccessIterator __brick_min_element( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { +#if defined(_PSTL_UDR_PRESENT) + return __unseq_backend::__simd_min_element(__first, __last - __first, __comp); +#else + return std::min_element(__first, __last, __comp); +#endif +} + +template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare> +_ForwardIterator __pattern_min_element( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) noexcept { + return __internal::__brick_min_element(__first, __last, __comp, typename _Tag::__is_vector{}); +} + +template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare> +_RandomAccessIterator __pattern_min_element( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp) { + if (__first == __last) + return __last; + + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + return __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first + 1, + __last, + __first, + [=](_RandomAccessIterator __begin, _RandomAccessIterator __end, _RandomAccessIterator __init) + -> _RandomAccessIterator { + const _RandomAccessIterator subresult = __internal::__brick_min_element(__begin, __end, __comp, _IsVector{}); + return __internal::__cmp_iterators_by_values(__init, subresult, __comp); + }, + [=](_RandomAccessIterator __it1, _RandomAccessIterator __it2) -> _RandomAccessIterator { + return __internal::__cmp_iterators_by_values(__it1, __it2, __comp); + }); + }); +} + +//------------------------------------------------------------------------ +// minmax_element +//------------------------------------------------------------------------ + +template <typename _ForwardIterator, typename _Compare> +std::pair<_ForwardIterator, _ForwardIterator> __brick_minmax_element( + _ForwardIterator __first, + _ForwardIterator __last, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + return std::minmax_element(__first, __last, __comp); +} + +template <typename _RandomAccessIterator, typename _Compare> +std::pair<_RandomAccessIterator, _RandomAccessIterator> __brick_minmax_element( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { +#if defined(_PSTL_UDR_PRESENT) + return __unseq_backend::__simd_minmax_element(__first, __last - __first, __comp); +#else + return std::minmax_element(__first, __last, __comp); +#endif +} + +template <typename _Tag, typename _ExecutionPolicy, typename _ForwardIterator, typename _Compare> +std::pair<_ForwardIterator, _ForwardIterator> __pattern_minmax_element( + _Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) noexcept { + return __internal::__brick_minmax_element(__first, __last, __comp, typename _Tag::__is_vector{}); +} + +template <typename _IsVector, typename _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare> +std::pair<_RandomAccessIterator, _RandomAccessIterator> __pattern_minmax_element( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _Compare __comp) { + if (__first == __last) + return std::make_pair(__first, __first); + + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + typedef std::pair<_RandomAccessIterator, _RandomAccessIterator> _Result; + + return __par_backend::__parallel_reduce( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first + 1, + __last, + std::make_pair(__first, __first), + [=](_RandomAccessIterator __begin, _RandomAccessIterator __end, _Result __init) -> _Result { + const _Result __subresult = __internal::__brick_minmax_element(__begin, __end, __comp, _IsVector{}); + return std::make_pair( + __internal::__cmp_iterators_by_values(__subresult.first, __init.first, __comp), + __internal::__cmp_iterators_by_values(__init.second, __subresult.second, std::not_fn(__comp))); + }, + [=](_Result __p1, _Result __p2) -> _Result { + return std::make_pair(__internal::__cmp_iterators_by_values(__p1.first, __p2.first, __comp), + __internal::__cmp_iterators_by_values(__p2.second, __p1.second, std::not_fn(__comp))); + }); + }); +} + +//------------------------------------------------------------------------ +// mismatch +//------------------------------------------------------------------------ +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +std::pair<_ForwardIterator1, _ForwardIterator2> __mismatch_serial( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __pred) { + return std::mismatch(__first1, __last1, __first2, __last2, __pred); +} + +template <class _ForwardIterator1, class _ForwardIterator2, class _Predicate> +std::pair<_ForwardIterator1, _ForwardIterator2> __brick_mismatch( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Predicate __pred, + /* __is_vector = */ std::false_type) noexcept { + return __mismatch_serial(__first1, __last1, __first2, __last2, __pred); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Predicate> +std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __brick_mismatch( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Predicate __pred, + /* __is_vector = */ std::true_type) noexcept { + auto __n = std::min(__last1 - __first1, __last2 - __first2); + return __unseq_backend::__simd_first(__first1, __n, __first2, std::not_fn(__pred)); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> +std::pair<_ForwardIterator1, _ForwardIterator2> __pattern_mismatch( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Predicate __pred) noexcept { + return __internal::__brick_mismatch(__first1, __last1, __first2, __last2, __pred, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Predicate> +std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __pattern_mismatch( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Predicate __pred) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + return __internal::__except_handler([&]() { + auto __n = std::min(__last1 - __first1, __last2 - __first2); + auto __result = __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __first1 + __n, + [__first1, __first2, __pred](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__brick_mismatch( + __i, __j, __first2 + (__i - __first1), __first2 + (__j - __first1), __pred, _IsVector{}) + .first; + }, + std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), + /*is_first=*/true); + return std::make_pair(__result, __first2 + (__result - __first1)); + }); +} + +//------------------------------------------------------------------------ +// lexicographical_compare +//------------------------------------------------------------------------ + +template <class _ForwardIterator1, class _ForwardIterator2, class _Compare> +bool __brick_lexicographical_compare( + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp, + /* __is_vector = */ std::false_type) noexcept { + return std::lexicographical_compare(__first1, __last1, __first2, __last2, __comp); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Compare> +bool __brick_lexicographical_compare( + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Compare __comp, + /* __is_vector = */ std::true_type) noexcept { + if (__first2 == __last2) { // if second sequence is empty + return false; + } else if (__first1 == __last1) { // if first sequence is empty + return true; + } else { + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference ref_type1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference ref_type2; + --__last1; + --__last2; + auto __n = std::min(__last1 - __first1, __last2 - __first2); + std::pair<_RandomAccessIterator1, _RandomAccessIterator2> __result = __unseq_backend::__simd_first( + __first1, __n, __first2, [__comp](const ref_type1 __x, const ref_type2 __y) mutable { + return __comp(__x, __y) || __comp(__y, __x); + }); + + if (__result.first == __last1 && __result.second != __last2) { // if first sequence shorter than second + return !__comp(*__result.second, *__result.first); + } else { // if second sequence shorter than first or both have the same number of elements + return __comp(*__result.first, *__result.second); + } + } +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> +bool __pattern_lexicographical_compare( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp) noexcept { + return __internal::__brick_lexicographical_compare( + __first1, __last1, __first2, __last2, __comp, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _Compare> +bool __pattern_lexicographical_compare( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first1, + _RandomAccessIterator1 __last1, + _RandomAccessIterator2 __first2, + _RandomAccessIterator2 __last2, + _Compare __comp) noexcept { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + if (__first2 == __last2) { // if second sequence is empty + return false; + } else if (__first1 == __last1) { // if first sequence is empty + return true; + } else { + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _RefType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _RefType2; + --__last1; + --__last2; + auto __n = std::min(__last1 - __first1, __last2 - __first2); + auto __result = __internal::__parallel_find( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __first1 + __n, + [__first1, __first2, &__comp](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j) { + return __internal::__brick_mismatch( + __i, + __j, + __first2 + (__i - __first1), + __first2 + (__j - __first1), + [&__comp](const _RefType1 __x, const _RefType2 __y) { + return !__comp(__x, __y) && !__comp(__y, __x); + }, + _IsVector{}) + .first; + }, + std::less<typename std::iterator_traits<_RandomAccessIterator1>::difference_type>(), + /*is_first=*/true); + + if (__result == __last1 && __first2 + (__result - __first1) != __last2) { // if first sequence shorter than second + return !__comp(*(__first2 + (__result - __first1)), *__result); + } else { // if second sequence shorter than first or both have the same number of elements + return __comp(*__result, *(__first2 + (__result - __first1))); + } + } +} + +} // namespace __internal +} // namespace __pstl + +#endif /* _PSTL_ALGORITHM_IMPL_H */ diff --git a/libcxx/include/__pstl/internal/execution_defs.h b/libcxx/include/__pstl/internal/execution_defs.h new file mode 100644 index 000000000000..5992f0e4a375 --- /dev/null +++ b/libcxx/include/__pstl/internal/execution_defs.h @@ -0,0 +1,76 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_EXECUTION_POLICY_DEFS_H +#define _PSTL_EXECUTION_POLICY_DEFS_H + +#include <__config> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +namespace __pstl { +namespace execution { +inline namespace v1 { + +// 2.4, Sequential execution policy +class sequenced_policy {}; + +// 2.5, Parallel execution policy +class parallel_policy {}; + +// 2.6, Parallel+Vector execution policy +class parallel_unsequenced_policy {}; + +class unsequenced_policy {}; + +// 2.8, Execution policy objects +constexpr sequenced_policy seq{}; +constexpr parallel_policy par{}; +constexpr parallel_unsequenced_policy par_unseq{}; +constexpr unsequenced_policy unseq{}; + +// 2.3, Execution policy type trait +template <class> +struct is_execution_policy : std::false_type {}; + +template <> +struct is_execution_policy<__pstl::execution::sequenced_policy> : std::true_type {}; +template <> +struct is_execution_policy<__pstl::execution::parallel_policy> : std::true_type {}; +template <> +struct is_execution_policy<__pstl::execution::parallel_unsequenced_policy> : std::true_type {}; +template <> +struct is_execution_policy<__pstl::execution::unsequenced_policy> : std::true_type {}; + +template <class _Tp> +constexpr bool is_execution_policy_v = __pstl::execution::is_execution_policy<_Tp>::value; +} // namespace v1 +} // namespace execution + +namespace __internal { +template <class _ExecPolicy, class _Tp> +using __enable_if_execution_policy = + typename std::enable_if<__pstl::execution::is_execution_policy<typename std::decay<_ExecPolicy>::type>::value, + _Tp>::type; + +template <class _IsVector> +struct __serial_tag; +template <class _IsVector> +struct __parallel_tag; + +} // namespace __internal + +} // namespace __pstl + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif /* _PSTL_EXECUTION_POLICY_DEFS_H */ diff --git a/libcxx/include/__pstl/internal/execution_impl.h b/libcxx/include/__pstl/internal/execution_impl.h new file mode 100644 index 000000000000..c3a7405d393f --- /dev/null +++ b/libcxx/include/__pstl/internal/execution_impl.h @@ -0,0 +1,97 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_EXECUTION_IMPL_H +#define _PSTL_EXECUTION_IMPL_H + +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/conditional.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/decay.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_base_of.h> + +#include <__pstl/internal/execution_defs.h> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +namespace __pstl { +namespace __internal { + +template <typename _IteratorTag, typename... _IteratorTypes> +using __are_iterators_of = std::conjunction< + std::is_base_of<_IteratorTag, typename std::iterator_traits<std::decay_t<_IteratorTypes>>::iterator_category>...>; + +template <typename... _IteratorTypes> +using __are_random_access_iterators = __are_iterators_of<std::random_access_iterator_tag, _IteratorTypes...>; + +struct __serial_backend_tag {}; +struct __tbb_backend_tag {}; +struct __openmp_backend_tag {}; + +# if defined(_PSTL_PAR_BACKEND_TBB) +using __par_backend_tag = __tbb_backend_tag; +# elif defined(_PSTL_PAR_BACKEND_OPENMP) +using __par_backend_tag = __openmp_backend_tag; +# elif defined(_PSTL_PAR_BACKEND_SERIAL) +using __par_backend_tag = __serial_backend_tag; +# else +# error "A parallel backend must be specified"; +# endif + +template <class _IsVector> +struct __serial_tag { + using __is_vector = _IsVector; +}; + +template <class _IsVector> +struct __parallel_tag { + using __is_vector = _IsVector; + // backend tag can be change depending on + // TBB availability in the environment + using __backend_tag = __par_backend_tag; +}; + +template <class _IsVector, class... _IteratorTypes> +using __tag_type = + typename std::conditional<__internal::__are_random_access_iterators<_IteratorTypes...>::value, + __parallel_tag<_IsVector>, + __serial_tag<_IsVector>>::type; + +template <class... _IteratorTypes> +_LIBCPP_HIDE_FROM_ABI __serial_tag</*_IsVector = */ std::false_type> +__select_backend(__pstl::execution::sequenced_policy, _IteratorTypes&&...) { + return {}; +} + +template <class... _IteratorTypes> +_LIBCPP_HIDE_FROM_ABI __serial_tag<__internal::__are_random_access_iterators<_IteratorTypes...>> +__select_backend(__pstl::execution::unsequenced_policy, _IteratorTypes&&...) { + return {}; +} + +template <class... _IteratorTypes> +_LIBCPP_HIDE_FROM_ABI __tag_type</*_IsVector = */ std::false_type, _IteratorTypes...> +__select_backend(__pstl::execution::parallel_policy, _IteratorTypes&&...) { + return {}; +} + +template <class... _IteratorTypes> +_LIBCPP_HIDE_FROM_ABI __tag_type<__internal::__are_random_access_iterators<_IteratorTypes...>, _IteratorTypes...> +__select_backend(__pstl::execution::parallel_unsequenced_policy, _IteratorTypes&&...) { + return {}; +} + +} // namespace __internal +} // namespace __pstl + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif /* _PSTL_EXECUTION_IMPL_H */ diff --git a/libcxx/include/__pstl/internal/glue_algorithm_defs.h b/libcxx/include/__pstl/internal/glue_algorithm_defs.h new file mode 100644 index 000000000000..00458d5ffbbd --- /dev/null +++ b/libcxx/include/__pstl/internal/glue_algorithm_defs.h @@ -0,0 +1,655 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_GLUE_ALGORITHM_DEFS_H +#define _PSTL_GLUE_ALGORITHM_DEFS_H + +#include <__config> +#include <functional> +#include <iterator> + +#include "execution_defs.h" + +namespace std { + +// [alg.find.end] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_end(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_end(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last); + +// [alg.find_first_of] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> find_first_of( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_first_of(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last); + +// [alg.adjacent_find] + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred); + +// [alg.count] + +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, + typename iterator_traits<_ForwardIterator>::difference_type> +count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, + typename iterator_traits<_ForwardIterator>::difference_type> +count_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred); + +// [alg.search] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +search(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +search(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +search_n(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> search_n( + _ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value); + +// [alg.copy] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +copy_if(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 result, + _Predicate __pred); + +// [alg.swap] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> swap_ranges( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2); + +// [alg.replace] + +template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +replace_if(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _UnaryPredicate __pred, + const _Tp& __new_value); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +replace(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + const _Tp& __old_value, + const _Tp& __new_value); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _UnaryPredicate, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> replace_copy_if( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _UnaryPredicate __pred, + const _Tp& __new_value); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> replace_copy( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + const _Tp& __old_value, + const _Tp& __new_value); + +// [alg.generate] +template <class _ExecutionPolicy, class _ForwardIterator, class _Generator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +generate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Generator __g); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Generator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +generate_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size count, _Generator __g); + +// [alg.remove] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> remove_copy_if( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Predicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +remove_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + const _Tp& __value); + +template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +remove_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +remove(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value); + +// [alg.unique] + +template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +unique_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryPredicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +unique_copy(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result); + +// [alg.reverse] + +template <class _ExecutionPolicy, class _BidirectionalIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +reverse(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last); + +template <class _ExecutionPolicy, class _BidirectionalIterator, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +reverse_copy(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _ForwardIterator __d_first); + +// [alg.rotate] + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +rotate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +rotate_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __middle, + _ForwardIterator1 __last, + _ForwardIterator2 __result); + +// [alg.partitions] + +template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred); + +template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _BidirectionalIterator> stable_partition( + _ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last, _UnaryPredicate __pred); + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _ForwardIterator1, + class _ForwardIterator2, + class _UnaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +partition_copy(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardIterator1 __out_true, + _ForwardIterator2 __out_false, + _UnaryPredicate __pred); + +// [alg.sort] + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp); + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last); + +// [stable.sort] + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp); + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last); + +// [mismatch] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __pred); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2); + +// [alg.equal] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __p); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __p); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2); + +// [alg.move] +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +move(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first); + +// [partial.sort] + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +partial_sort(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp); + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +partial_sort(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last); + +// [partial.sort.copy] + +template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> partial_sort_copy( + _ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _RandomAccessIterator __d_first, + _RandomAccessIterator __d_last, + _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> partial_sort_copy( + _ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _RandomAccessIterator __d_first, + _RandomAccessIterator __d_last); + +// [is.sorted] +template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +is_sorted_until(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +is_sorted_until(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_sorted(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_sorted(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +// [alg.nth.element] + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +nth_element(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last, + _Compare __comp); + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +nth_element(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last); + +// [alg.merge] +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator, + class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +merge(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __d_first, + _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +merge(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __d_first); + +template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +inplace_merge(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp); + +template <class _ExecutionPolicy, class _BidirectionalIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +inplace_merge(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last); + +// [includes] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +includes(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +includes(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2); + +// [set.union] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator, + class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +set_union(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +set_union(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result); + +// [set.intersection] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator, + class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_intersection( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_intersection( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result); + +// [set.difference] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator, + class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result); + +// [set.symmetric.difference] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator, + class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_symmetric_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator result, + _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_symmetric_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result); + +// [is.heap] +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> +is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp); + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> +is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last); + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_heap(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp); + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_heap(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last); + +// [alg.min.max] + +template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +min_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +min_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +max_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +max_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator, _ForwardIterator>> +minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator, _ForwardIterator>> +minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +// [alg.lex.comparison] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> lexicographical_compare( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> lexicographical_compare( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2); + +} // namespace std + +#endif /* _PSTL_GLUE_ALGORITHM_DEFS_H */ diff --git a/libcxx/include/__pstl/internal/glue_algorithm_impl.h b/libcxx/include/__pstl/internal/glue_algorithm_impl.h new file mode 100644 index 000000000000..8e8f2539f859 --- /dev/null +++ b/libcxx/include/__pstl/internal/glue_algorithm_impl.h @@ -0,0 +1,972 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_GLUE_ALGORITHM_IMPL_H +#define _PSTL_GLUE_ALGORITHM_IMPL_H + +#include <__config> +#include <functional> + +#include "algorithm_fwd.h" +#include "execution_defs.h" +#include "numeric_fwd.h" /* count and count_if use __pattern_transform_reduce */ +#include "utils.h" + +#include "execution_impl.h" + +namespace std { + +// [alg.find.end] +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_end(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first); + + return __pstl::__internal::__pattern_find_end( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_end(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last) { + return std::find_end(std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, std::equal_to<>()); +} + +// [alg.find_first_of] +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> find_first_of( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first); + + return __pstl::__internal::__pattern_find_first_of( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +find_first_of(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last) { + return std::find_first_of( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, std::equal_to<>()); +} + +// [alg.adjacent_find] +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + return __pstl::__internal::__pattern_adjacent_find( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + std::equal_to<_ValueType>(), + /*first_semantic*/ false); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_adjacent_find( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred, /*first_semantic*/ false); +} + +// [alg.count] + +// Implementation note: count and count_if call the pattern directly instead of calling std::transform_reduce +// so that we do not have to include <numeric>. + +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, + typename iterator_traits<_ForwardIterator>::difference_type> +count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + return __pstl::__internal::__pattern_count( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [&__value](const _ValueType& __x) { + return __value == __x; + }); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, + typename iterator_traits<_ForwardIterator>::difference_type> +count_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_count( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +// [alg.search] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +search(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __s_first); + + return __pstl::__internal::__pattern_search( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, __pred); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator1> +search(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last) { + return std::search(std::forward<_ExecutionPolicy>(__exec), __first, __last, __s_first, __s_last, std::equal_to<>()); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +search_n(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _Size __count, + const _Tp& __value, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_search_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __count, __value, __pred); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> search_n( + _ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value) { + return std::search_n( + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __count, + __value, + std::equal_to<typename iterator_traits<_ForwardIterator>::value_type>()); +} + +// [alg.copy] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +copy_if(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Predicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_copy_if( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pred); +} + +// [alg.swap] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> swap_ranges( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + typedef typename iterator_traits<_ForwardIterator1>::reference _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator2>::reference _ReferenceType2; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_walk2( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + [](_ReferenceType1 __x, _ReferenceType2 __y) { + using std::swap; + swap(__x, __y); + }); +} + +// [alg.generate] +template <class _ExecutionPolicy, class _ForwardIterator, class _Generator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +generate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Generator __g) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_generate(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __g); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Generator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +generate_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __count, _Generator __g) { + if (__count <= 0) + return __first; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_generate_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __count, __g); +} + +// [alg.remove] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Predicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> remove_copy_if( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Predicate __pred) { + return std::copy_if(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, std::not_fn(__pred)); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +remove_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + const _Tp& __value) { + return std::copy_if( + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __pstl::__internal::__not_equal_value<_Tp>(__value)); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +remove_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_remove_if( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +remove(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + return std::remove_if( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __pstl::__internal::__equal_value<_Tp>(__value)); +} + +// [alg.unique] + +template <class _ExecutionPolicy, class _ForwardIterator, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_unique( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +unique(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + return std::unique(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::equal_to<>()); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +unique_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_unique_copy( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __pred); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> unique_copy( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result) { + return std::unique_copy(__exec, __first, __last, __result, std::equal_to<>()); +} + +// [alg.reverse] + +template <class _ExecutionPolicy, class _BidirectionalIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +reverse(_ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_reverse(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last); +} + +template <class _ExecutionPolicy, class _BidirectionalIterator, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +reverse_copy(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __last, + _ForwardIterator __d_first) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + return __pstl::__internal::__pattern_reverse_copy( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first); +} + +// [alg.rotate] + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +rotate(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_rotate( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +rotate_copy(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __middle, + _ForwardIterator1 __last, + _ForwardIterator2 __result) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_rotate_copy( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __result); +} + +// [alg.partitions] + +template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_partitioned(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_is_partitioned( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +partition(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_partition( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +template <class _ExecutionPolicy, class _BidirectionalIterator, class _UnaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _BidirectionalIterator> stable_partition( + _ExecutionPolicy&& __exec, _BidirectionalIterator __first, _BidirectionalIterator __last, _UnaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_stable_partition( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __pred); +} + +template <class _ExecutionPolicy, + class _ForwardIterator, + class _ForwardIterator1, + class _ForwardIterator2, + class _UnaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +partition_copy(_ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _ForwardIterator1 __out_true, + _ForwardIterator2 __out_false, + _UnaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __out_true, __out_false); + + return __pstl::__internal::__pattern_partition_copy( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __out_true, __out_false, __pred); +} + +// [alg.sort] + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + typedef typename iterator_traits<_RandomAccessIterator>::value_type _InputType; + return __pstl::__internal::__pattern_sort( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __comp, + typename std::is_move_constructible<_InputType>::type()); +} + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last) { + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _InputType; + std::sort(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +// [stable.sort] + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_stable_sort( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp); +} + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +stable_sort(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last) { + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _InputType; + std::stable_sort(__exec, __first, __last, std::less<_InputType>()); +} + +// [mismatch] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __pred) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_mismatch( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __pred); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __pred) { + return std::mismatch( + __exec, __first1, __last1, __first2, std::next(__first2, std::distance(__first1, __last1)), __pred); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2) { + return std::mismatch(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, std::equal_to<>()); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator1, _ForwardIterator2>> +mismatch(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + // TODO: to get rid of "distance" + return std::mismatch( + std::forward<_ExecutionPolicy>(__exec), + __first1, + __last1, + __first2, + std::next(__first2, std::distance(__first1, __last1))); +} + +// [alg.equal] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _BinaryPredicate __p) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_equal( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __p); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + return std::equal(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, std::equal_to<>()); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _BinaryPredicate __p) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_equal( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __p); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +equal(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2) { + return equal(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, std::equal_to<>()); +} + +// [alg.move] +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> +move(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__pattern_walk2_brick( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __d_first, + [](_ForwardIterator1 __begin, _ForwardIterator1 __end, _ForwardIterator2 __res) { + return __pstl::__internal::__brick_move(__begin, __end, __res, __is_vector{}); + }); +} + +// [partial.sort] + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +partial_sort(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_partial_sort( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __comp); +} + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +partial_sort(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last) { + typedef typename iterator_traits<_RandomAccessIterator>::value_type _InputType; + std::partial_sort(__exec, __first, __middle, __last, std::less<_InputType>()); +} + +// [partial.sort.copy] + +template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> partial_sort_copy( + _ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _RandomAccessIterator __d_first, + _RandomAccessIterator __d_last, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + return __pstl::__internal::__pattern_partial_sort_copy( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __d_last, __comp); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> partial_sort_copy( + _ExecutionPolicy&& __exec, + _ForwardIterator __first, + _ForwardIterator __last, + _RandomAccessIterator __d_first, + _RandomAccessIterator __d_last) { + return std::partial_sort_copy( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __d_last, std::less<>()); +} + +// [is.sorted] +template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +is_sorted_until(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + const _ForwardIterator __res = __pstl::__internal::__pattern_adjacent_find( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __pstl::__internal::__reorder_pred<_Compare>(__comp), + /*first_semantic*/ false); + return __res == __last ? __last : std::next(__res); +} + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +is_sorted_until(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename std::iterator_traits<_ForwardIterator>::value_type _InputType; + return is_sorted_until(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_sorted(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_adjacent_find( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __pstl::__internal::__reorder_pred<_Compare>(__comp), + /*or_semantic*/ true) == __last; +} + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_sorted(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename std::iterator_traits<_ForwardIterator>::value_type _InputType; + return std::is_sorted(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +// [alg.merge] +template <class _ExecutionPolicy, class _BidirectionalIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +inplace_merge(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_inplace_merge( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __middle, __last, __comp); +} + +template <class _ExecutionPolicy, class _BidirectionalIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +inplace_merge(_ExecutionPolicy&& __exec, + _BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last) { + typedef typename std::iterator_traits<_BidirectionalIterator>::value_type _InputType; + std::inplace_merge(__exec, __first, __middle, __last, std::less<_InputType>()); +} + +// [includes] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +includes(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_includes( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __comp); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +includes(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2) { + return std::includes(std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, std::less<>()); +} + +// [set.union] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator, + class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +set_union(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_union( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +set_union(_ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result) { + return std::set_union( + std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, std::less<>()); +} + +// [set.intersection] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator, + class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_intersection( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_intersection( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_intersection( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result) { + return std::set_intersection( + std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, std::less<>()); +} + +// [set.difference] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator, + class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_difference( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result) { + return std::set_difference( + std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, std::less<>()); +} + +// [set.symmetric.difference] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _ForwardIterator, + class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_symmetric_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2, __result); + + return __pstl::__internal::__pattern_set_symmetric_difference( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, __comp); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> set_symmetric_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _ForwardIterator __result) { + return std::set_symmetric_difference( + std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __result, std::less<>()); +} + +// [is.heap] +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> +is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__pattern_is_heap_until( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp); +} + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _RandomAccessIterator> +is_heap_until(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last) { + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _InputType; + return std::is_heap_until(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_heap(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { + return std::is_heap_until(std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp) == __last; +} + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> +is_heap(_ExecutionPolicy&& __exec, _RandomAccessIterator __first, _RandomAccessIterator __last) { + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _InputType; + return std::is_heap(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +// [alg.min.max] + +template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +min_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_min_element( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp); +} + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +min_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename std::iterator_traits<_ForwardIterator>::value_type _InputType; + return std::min_element(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_InputType>()); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +max_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + return min_element( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __pstl::__internal::__reorder_pred<_Compare>(__comp)); +} + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +max_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename std::iterator_traits<_ForwardIterator>::value_type _InputType; + return std::min_element( + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __pstl::__internal::__reorder_pred<std::less<_InputType>>(std::less<_InputType>())); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator, _ForwardIterator>> +minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + return __pstl::__internal::__pattern_minmax_element( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __comp); +} + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, std::pair<_ForwardIterator, _ForwardIterator>> +minmax_element(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + return std::minmax_element(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::less<_ValueType>()); +} + +// [alg.nth.element] + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +nth_element(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__pattern_nth_element( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __nth, __last, __comp); +} + +template <class _ExecutionPolicy, class _RandomAccessIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +nth_element(_ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __nth, + _RandomAccessIterator __last) { + typedef typename iterator_traits<_RandomAccessIterator>::value_type _InputType; + std::nth_element(std::forward<_ExecutionPolicy>(__exec), __first, __nth, __last, std::less<_InputType>()); +} + +// [alg.lex.comparison] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Compare> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> lexicographical_compare( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2, + _Compare __comp) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2); + + return __pstl::__internal::__pattern_lexicographical_compare( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, __comp); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, bool> lexicographical_compare( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first1, + _ForwardIterator1 __last1, + _ForwardIterator2 __first2, + _ForwardIterator2 __last2) { + return std::lexicographical_compare( + std::forward<_ExecutionPolicy>(__exec), __first1, __last1, __first2, __last2, std::less<>()); +} + +} // namespace std + +#endif /* _PSTL_GLUE_ALGORITHM_IMPL_H */ diff --git a/libcxx/include/__pstl/internal/glue_memory_defs.h b/libcxx/include/__pstl/internal/glue_memory_defs.h new file mode 100644 index 000000000000..4e8581cfdb80 --- /dev/null +++ b/libcxx/include/__pstl/internal/glue_memory_defs.h @@ -0,0 +1,81 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_GLUE_MEMORY_DEFS_H +#define _PSTL_GLUE_MEMORY_DEFS_H + +#include <__config> + +#include "execution_defs.h" + +namespace std { + +// [uninitialized.copy] + +template <class _ExecutionPolicy, class _InputIterator, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_copy(_ExecutionPolicy&& __exec, _InputIterator __first, _InputIterator __last, _ForwardIterator __result); + +template <class _ExecutionPolicy, class _InputIterator, class _Size, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_copy_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __n, _ForwardIterator __result); + +// [uninitialized.move] + +template <class _ExecutionPolicy, class _InputIterator, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_move(_ExecutionPolicy&& __exec, _InputIterator __first, _InputIterator __last, _ForwardIterator __result); + +template <class _ExecutionPolicy, class _InputIterator, class _Size, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_move_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __n, _ForwardIterator __result); + +// [uninitialized.fill] + +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_fill_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n, const _Tp& __value); + +// [specialized.destroy] + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +destroy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +destroy_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n); + +// [uninitialized.construct.default] + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_default_construct(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_default_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n); + +// [uninitialized.construct.value] + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_value_construct(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last); + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_value_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n); + +} // namespace std + +#endif /* _PSTL_GLUE_MEMORY_DEFS_H */ diff --git a/libcxx/include/__pstl/internal/glue_memory_impl.h b/libcxx/include/__pstl/internal/glue_memory_impl.h new file mode 100644 index 000000000000..b645ba3fca10 --- /dev/null +++ b/libcxx/include/__pstl/internal/glue_memory_impl.h @@ -0,0 +1,379 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_GLUE_MEMORY_IMPL_H +#define _PSTL_GLUE_MEMORY_IMPL_H + +#include <__config> + +#include "algorithm_fwd.h" +#include "execution_defs.h" +#include "utils.h" + +#include "execution_impl.h" + +namespace std { + +// [uninitialized.copy] + +template <class _ExecutionPolicy, class _InputIterator, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> uninitialized_copy( + _ExecutionPolicy&& __exec, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2; + typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::integral_constant < bool, + std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), + [&]() { + return __pstl::__internal::__pattern_walk2_brick( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + [](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) { + return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk2( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) { ::new (std::addressof(__val2)) _ValueType2(__val1); }); + }); +} + +template <class _ExecutionPolicy, class _InputIterator, class _Size, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_copy_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __n, _ForwardIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2; + typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::integral_constant < bool, + std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), + [&]() { + return __pstl::__internal::__pattern_walk2_brick_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + __result, + [](_InputIterator __begin, _Size __sz, _ForwardIterator __res) { + return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk2_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) { ::new (std::addressof(__val2)) _ValueType2(__val1); }); + }); +} + +// [uninitialized.move] + +template <class _ExecutionPolicy, class _InputIterator, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> uninitialized_move( + _ExecutionPolicy&& __exec, _InputIterator __first, _InputIterator __last, _ForwardIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2; + typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::integral_constant < bool, + std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), + [&]() { + return __pstl::__internal::__pattern_walk2_brick( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + [](_InputIterator __begin, _InputIterator __end, _ForwardIterator __res) { + return __pstl::__internal::__brick_copy(__begin, __end, __res, __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk2( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) { + ::new (std::addressof(__val2)) _ValueType2(std::move(__val1)); + }); + }); +} + +template <class _ExecutionPolicy, class _InputIterator, class _Size, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_move_n(_ExecutionPolicy&& __exec, _InputIterator __first, _Size __n, _ForwardIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType2; + typedef typename iterator_traits<_InputIterator>::reference _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType2; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::integral_constant < bool, + std::is_trivial<_ValueType1>::value&& std::is_trivial<_ValueType2>::value > (), + [&]() { + return __pstl::__internal::__pattern_walk2_brick_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + __result, + [](_InputIterator __begin, _Size __sz, _ForwardIterator __res) { + return __pstl::__internal::__brick_copy_n(__begin, __sz, __res, __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk2_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + __result, + [](_ReferenceType1 __val1, _ReferenceType2 __val2) { + ::new (std::addressof(__val2)) _ValueType2(std::move(__val1)); + }); + }); +} + +// [uninitialized.fill] + +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + __pstl::__internal::__invoke_if_else( + std::is_arithmetic<_ValueType>(), + [&]() { + __pstl::__internal::__pattern_walk_brick( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [&__value](_ForwardIterator __begin, _ForwardIterator __end) { + __pstl::__internal::__brick_fill(__begin, __end, _ValueType(__value), __is_vector{}); + }); + }, + [&]() { + __pstl::__internal::__pattern_walk1( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [&__value](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType(__value); + }); + }); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_fill_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n, const _Tp& __value) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::is_arithmetic<_ValueType>(), + [&]() { + return __pstl::__internal::__pattern_walk_brick_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + [&__value](_ForwardIterator __begin, _Size __count) { + return __pstl::__internal::__brick_fill_n(__begin, __count, _ValueType(__value), __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk1_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, [&__value](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType(__value); + }); + }); +} + +// [specialized.destroy] + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +destroy(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__invoke_if_not(std::is_trivially_destructible<_ValueType>(), [&]() { + __pstl::__internal::__pattern_walk1( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [](_ReferenceType __val) { + __val.~_ValueType(); + }); + }); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +destroy_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__invoke_if_else( + std::is_trivially_destructible<_ValueType>(), + [&]() { return std::next(__first, __n); }, + [&]() { + return __pstl::__internal::__pattern_walk1_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, [](_ReferenceType __val) { + __val.~_ValueType(); + }); + }); +} + +// [uninitialized.construct.default] + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_default_construct(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + __pstl::__internal::__invoke_if_not(std::is_trivial<_ValueType>(), [&]() { + __pstl::__internal::__pattern_walk1( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType; + }); + }); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_default_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + return __pstl::__internal::__invoke_if_else( + std::is_trivial<_ValueType>(), + [&]() { return std::next(__first, __n); }, + [&]() { + return __pstl::__internal::__pattern_walk1_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, [](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType; + }); + }); +} + +// [uninitialized.construct.value] + +template <class _ExecutionPolicy, class _ForwardIterator> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> +uninitialized_value_construct(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + __pstl::__internal::__invoke_if_else( + std::is_trivial<_ValueType>(), + [&]() { + __pstl::__internal::__pattern_walk_brick( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + [](_ForwardIterator __begin, _ForwardIterator __end) { + __pstl::__internal::__brick_fill(__begin, __end, _ValueType(), __is_vector{}); + }); + }, + [&]() { + __pstl::__internal::__pattern_walk1( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, [](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType(); + }); + }); +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Size> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> +uninitialized_value_construct_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __n) { + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; + typedef typename iterator_traits<_ForwardIterator>::reference _ReferenceType; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first); + + using __is_vector = typename decltype(__dispatch_tag)::__is_vector; + + return __pstl::__internal::__invoke_if_else( + std::is_trivial<_ValueType>(), + [&]() { + return __pstl::__internal::__pattern_walk_brick_n( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __n, + [](_ForwardIterator __begin, _Size __count) { + return __pstl::__internal::__brick_fill_n(__begin, __count, _ValueType(), __is_vector{}); + }); + }, + [&]() { + return __pstl::__internal::__pattern_walk1_n( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __n, [](_ReferenceType __val) { + ::new (std::addressof(__val)) _ValueType(); + }); + }); +} + +} // namespace std + +#endif /* _PSTL_GLUE_MEMORY_IMPL_H */ diff --git a/libcxx/include/__pstl/internal/glue_numeric_defs.h b/libcxx/include/__pstl/internal/glue_numeric_defs.h new file mode 100644 index 000000000000..05c71665eb58 --- /dev/null +++ b/libcxx/include/__pstl/internal/glue_numeric_defs.h @@ -0,0 +1,124 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_GLUE_NUMERIC_DEFS_H +#define _PSTL_GLUE_NUMERIC_DEFS_H + +#include <__config> +#include <iterator> + +#include "execution_defs.h" + +namespace std { +// [exclusive.scan] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init, + _BinaryOperation __binary_op); + +// [inclusive.scan] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _Tp __init); + +// [transform.exclusive.scan] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _Tp, + class _BinaryOperation, + class _UnaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op); + +// [transform.inclusive.scan] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _BinaryOperation, + class _UnaryOperation, + class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op, + _Tp __init); + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _UnaryOperation, + class _BinaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op); + +// [adjacent.difference] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> adjacent_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __d_first, + _BinaryOperation op); + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> adjacent_difference( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first); + +} // namespace std + +#endif /* _PSTL_GLUE_NUMERIC_DEFS_H */ diff --git a/libcxx/include/__pstl/internal/glue_numeric_impl.h b/libcxx/include/__pstl/internal/glue_numeric_impl.h new file mode 100644 index 000000000000..4e6516a06cf2 --- /dev/null +++ b/libcxx/include/__pstl/internal/glue_numeric_impl.h @@ -0,0 +1,223 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_GLUE_NUMERIC_IMPL_H +#define _PSTL_GLUE_NUMERIC_IMPL_H + +#include <__config> +#include <functional> + +#include "execution_impl.h" +#include "numeric_fwd.h" +#include "utils.h" + +namespace std { + +// [exclusive.scan] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using namespace __pstl; + return __internal::__pattern_transform_scan( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __pstl::__internal::__no_op(), + __init, + std::plus<_Tp>(), + /*inclusive=*/std::false_type()); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init, + _BinaryOperation __binary_op) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + using namespace __pstl; + return __internal::__pattern_transform_scan( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __pstl::__internal::__no_op(), + __init, + __binary_op, + /*inclusive=*/std::false_type()); +} + +// [inclusive.scan] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result) { + typedef typename iterator_traits<_ForwardIterator1>::value_type _InputType; + return transform_inclusive_scan( + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + std::plus<_InputType>(), + __pstl::__internal::__no_op()); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op) { + return transform_inclusive_scan( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __binary_op, __pstl::__internal::__no_op()); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp, class _BinaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _Tp __init) { + return transform_inclusive_scan( + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __binary_op, + __pstl::__internal::__no_op(), + __init); +} + +// [transform.exclusive.scan] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _Tp, + class _BinaryOperation, + class _UnaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_exclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _Tp __init, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_transform_scan( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __unary_op, + __init, + __binary_op, + /*inclusive=*/std::false_type()); +} + +// [transform.inclusive.scan] + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _BinaryOperation, + class _UnaryOperation, + class _Tp> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op, + _Tp __init) { + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result); + + return __pstl::__internal::__pattern_transform_scan( + __dispatch_tag, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last, + __result, + __unary_op, + __init, + __binary_op, + /*inclusive=*/std::true_type()); +} + +template <class _ExecutionPolicy, + class _ForwardIterator1, + class _ForwardIterator2, + class _UnaryOperation, + class _BinaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> transform_inclusive_scan( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op) { + if (__first != __last) { + auto __tmp = __unary_op(*__first); + *__result = __tmp; + return transform_inclusive_scan( + std::forward<_ExecutionPolicy>(__exec), ++__first, __last, ++__result, __binary_op, __unary_op, __tmp); + } else { + return __result; + } +} + +// [adjacent.difference] + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryOperation> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> adjacent_difference( + _ExecutionPolicy&& __exec, + _ForwardIterator1 __first, + _ForwardIterator1 __last, + _ForwardIterator2 __d_first, + _BinaryOperation __op) { + if (__first == __last) + return __d_first; + + auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __d_first); + + return __pstl::__internal::__pattern_adjacent_difference( + __dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, __op); +} + +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2> +__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> adjacent_difference( + _ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __d_first) { + typedef typename iterator_traits<_ForwardIterator1>::value_type _ValueType; + return adjacent_difference( + std::forward<_ExecutionPolicy>(__exec), __first, __last, __d_first, std::minus<_ValueType>()); +} + +} // namespace std + +#endif /* _PSTL_GLUE_NUMERIC_IMPL_H_ */ diff --git a/libcxx/include/__pstl/internal/memory_impl.h b/libcxx/include/__pstl/internal/memory_impl.h new file mode 100644 index 000000000000..5315ccd9a344 --- /dev/null +++ b/libcxx/include/__pstl/internal/memory_impl.h @@ -0,0 +1,106 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_MEMORY_IMPL_H +#define _PSTL_MEMORY_IMPL_H + +#include <__config> +#include <iterator> + +#include "unseq_backend_simd.h" + +namespace __pstl { +namespace __internal { + +//------------------------------------------------------------------------ +// uninitialized_move +//------------------------------------------------------------------------ + +template <typename _ForwardIterator, typename _OutputIterator> +_OutputIterator __brick_uninitialized_move( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + /*vector=*/std::false_type) noexcept { + using _ValueType = typename std::iterator_traits<_OutputIterator>::value_type; + for (; __first != __last; ++__first, ++__result) { + ::new (std::addressof(*__result)) _ValueType(std::move(*__first)); + } + return __result; +} + +template <typename _RandomAccessIterator, typename _OutputIterator> +_OutputIterator __brick_uninitialized_move( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + /*vector=*/std::true_type) noexcept { + using __ValueType = typename std::iterator_traits<_OutputIterator>::value_type; + using _ReferenceType1 = typename std::iterator_traits<_RandomAccessIterator>::reference; + using _ReferenceType2 = typename std::iterator_traits<_OutputIterator>::reference; + + return __unseq_backend::__simd_walk_2( + __first, __last - __first, __result, [](_ReferenceType1 __x, _ReferenceType2 __y) { + ::new (std::addressof(__y)) __ValueType(std::move(__x)); + }); +} + +template <typename _Iterator> +void __brick_destroy(_Iterator __first, _Iterator __last, /*vector*/ std::false_type) noexcept { + using _ValueType = typename std::iterator_traits<_Iterator>::value_type; + + for (; __first != __last; ++__first) + __first->~_ValueType(); +} + +template <typename _RandomAccessIterator> +void __brick_destroy(_RandomAccessIterator __first, _RandomAccessIterator __last, /*vector*/ std::true_type) noexcept { + using _ValueType = typename std::iterator_traits<_RandomAccessIterator>::value_type; + using _ReferenceType = typename std::iterator_traits<_RandomAccessIterator>::reference; + + __unseq_backend::__simd_walk_1(__first, __last - __first, [](_ReferenceType __x) { __x.~_ValueType(); }); +} + +//------------------------------------------------------------------------ +// uninitialized copy +//------------------------------------------------------------------------ + +template <typename _ForwardIterator, typename _OutputIterator> +_OutputIterator __brick_uninitialized_copy( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + /*vector=*/std::false_type) noexcept { + using _ValueType = typename std::iterator_traits<_OutputIterator>::value_type; + for (; __first != __last; ++__first, ++__result) { + ::new (std::addressof(*__result)) _ValueType(*__first); + } + return __result; +} + +template <typename _RandomAccessIterator, typename _OutputIterator> +_OutputIterator __brick_uninitialized_copy( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + /*vector=*/std::true_type) noexcept { + using __ValueType = typename std::iterator_traits<_OutputIterator>::value_type; + using _ReferenceType1 = typename std::iterator_traits<_RandomAccessIterator>::reference; + using _ReferenceType2 = typename std::iterator_traits<_OutputIterator>::reference; + + return __unseq_backend::__simd_walk_2( + __first, __last - __first, __result, [](_ReferenceType1 __x, _ReferenceType2 __y) { + ::new (std::addressof(__y)) __ValueType(__x); + }); +} + +} // namespace __internal +} // namespace __pstl + +#endif /* _PSTL_MEMORY_IMPL_H */ diff --git a/libcxx/include/__pstl/internal/numeric_fwd.h b/libcxx/include/__pstl/internal/numeric_fwd.h new file mode 100644 index 000000000000..09f9b11d62da --- /dev/null +++ b/libcxx/include/__pstl/internal/numeric_fwd.h @@ -0,0 +1,143 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_NUMERIC_FWD_H +#define _PSTL_NUMERIC_FWD_H + +#include <__config> +#include <type_traits> +#include <utility> + +namespace __pstl { +namespace __internal { + +//------------------------------------------------------------------------ +// transform_exclusive_scan +// +// walk3 evaluates f(x,y,z) for (x,y,z) drawn from [first1,last1), [first2,...), [first3,...) +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation> +std::pair<_OutputIterator, _Tp> __brick_transform_scan( + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + _UnaryOperation, + _Tp, + _BinaryOperation, + /*Inclusive*/ std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation> +std::pair<_OutputIterator, _Tp> __brick_transform_scan( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _UnaryOperation, + _Tp, + _BinaryOperation, + /*Inclusive*/ std::true_type) noexcept; + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator, + class _OutputIterator, + class _UnaryOperation, + class _Tp, + class _BinaryOperation, + class _Inclusive> +_OutputIterator __pattern_transform_scan( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + _UnaryOperation, + _Tp, + _BinaryOperation, + _Inclusive) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator, + class _OutputIterator, + class _UnaryOperation, + class _Tp, + class _BinaryOperation, + class _Inclusive> +typename std::enable_if<!std::is_floating_point<_Tp>::value, _OutputIterator>::type __pattern_transform_scan( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _UnaryOperation, + _Tp, + _BinaryOperation, + _Inclusive); + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator, + class _OutputIterator, + class _UnaryOperation, + class _Tp, + class _BinaryOperation, + class _Inclusive> +typename std::enable_if<std::is_floating_point<_Tp>::value, _OutputIterator>::type __pattern_transform_scan( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _UnaryOperation, + _Tp, + _BinaryOperation, + _Inclusive); + +//------------------------------------------------------------------------ +// adjacent_difference +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _OutputIterator, class _BinaryOperation> +_OutputIterator __brick_adjacent_difference( + _ForwardIterator, + _ForwardIterator, + _OutputIterator, + _BinaryOperation, + /*is_vector*/ std::false_type) noexcept; + +template <class _RandomAccessIterator, class _OutputIterator, class _BinaryOperation> +_OutputIterator __brick_adjacent_difference( + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _BinaryOperation, + /*is_vector*/ std::true_type) noexcept; + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation> +_OutputIterator __pattern_adjacent_difference( + _Tag, _ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _OutputIterator, _BinaryOperation) noexcept; + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator, + class _OutputIterator, + class _BinaryOperation> +_OutputIterator __pattern_adjacent_difference( + __parallel_tag<_IsVector>, + _ExecutionPolicy&&, + _RandomAccessIterator, + _RandomAccessIterator, + _OutputIterator, + _BinaryOperation); + +} // namespace __internal +} // namespace __pstl + +#endif /* _PSTL_NUMERIC_FWD_H */ diff --git a/libcxx/include/__pstl/internal/numeric_impl.h b/libcxx/include/__pstl/internal/numeric_impl.h new file mode 100644 index 000000000000..484f26ade22c --- /dev/null +++ b/libcxx/include/__pstl/internal/numeric_impl.h @@ -0,0 +1,364 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_NUMERIC_IMPL_H +#define _PSTL_NUMERIC_IMPL_H + +#include <__assert> +#include <__config> +#include <iterator> +#include <type_traits> +#include <numeric> + +#include "parallel_backend.h" +#include "execution_impl.h" +#include "unseq_backend_simd.h" +#include "algorithm_fwd.h" + +namespace __pstl { +namespace __internal { + +//------------------------------------------------------------------------ +// transform_exclusive_scan +// +// walk3 evaluates f(x,y,z) for (x,y,z) drawn from [first1,last1), [first2,...), [first3,...) +//------------------------------------------------------------------------ + +// Exclusive form +template <class _ForwardIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation> +std::pair<_OutputIterator, _Tp> __brick_transform_scan( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + /*Inclusive*/ std::false_type, + /*is_vector=*/std::false_type) noexcept { + for (; __first != __last; ++__first, ++__result) { + *__result = __init; + __init = __binary_op(__init, __unary_op(*__first)); + } + return std::make_pair(__result, __init); +} + +// Inclusive form +template <class _RandomAccessIterator, class _OutputIterator, class _UnaryOperation, class _Tp, class _BinaryOperation> +std::pair<_OutputIterator, _Tp> __brick_transform_scan( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + /*Inclusive*/ std::true_type, + /*is_vector=*/std::false_type) noexcept { + for (; __first != __last; ++__first, ++__result) { + __init = __binary_op(__init, __unary_op(*__first)); + *__result = __init; + } + return std::make_pair(__result, __init); +} + +// type is arithmetic and binary operation is a user defined operation. +template <typename _Tp, typename _BinaryOperation> +using is_arithmetic_udop = + std::integral_constant<bool, + std::is_arithmetic<_Tp>::value && !std::is_same<_BinaryOperation, std::plus<_Tp>>::value>; + +// [restriction] - T shall be DefaultConstructible. +// [violation] - default ctor of T shall set the identity value for binary_op. +template <class _RandomAccessIterator, + class _OutputIterator, + class _UnaryOperation, + class _Tp, + class _BinaryOperation, + class _Inclusive> +typename std::enable_if<!is_arithmetic_udop<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type +__brick_transform_scan( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + _Inclusive, + /*is_vector=*/std::true_type) noexcept { +#if defined(_PSTL_UDS_PRESENT) + return __unseq_backend::__simd_scan( + __first, __last - __first, __result, __unary_op, __init, __binary_op, _Inclusive()); +#else + // We need to call serial brick here to call function for inclusive and exclusive scan that depends on _Inclusive() + // value + return __internal::__brick_transform_scan( + __first, + __last, + __result, + __unary_op, + __init, + __binary_op, + _Inclusive(), + /*is_vector=*/std::false_type()); +#endif +} + +template <class _RandomAccessIterator, + class _OutputIterator, + class _UnaryOperation, + class _Tp, + class _BinaryOperation, + class _Inclusive> +typename std::enable_if<is_arithmetic_udop<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type +__brick_transform_scan( + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + _Inclusive, + /*is_vector=*/std::true_type) noexcept { + return __internal::__brick_transform_scan( + __first, + __last, + __result, + __unary_op, + __init, + __binary_op, + _Inclusive(), + /*is_vector=*/std::false_type()); +} + +template <class _Tag, + class _ExecutionPolicy, + class _ForwardIterator, + class _OutputIterator, + class _UnaryOperation, + class _Tp, + class _BinaryOperation, + class _Inclusive> +_OutputIterator __pattern_transform_scan( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + _Inclusive) noexcept { + return __internal::__brick_transform_scan( + __first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(), typename _Tag::__is_vector{}) + .first; +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator, + class _OutputIterator, + class _UnaryOperation, + class _Tp, + class _BinaryOperation, + class _Inclusive> +typename std::enable_if<!std::is_floating_point<_Tp>::value, _OutputIterator>::type __pattern_transform_scan( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + _Inclusive) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; + + return __internal::__except_handler([&]() { + __par_backend::__parallel_transform_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __last - __first, + [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, + __init, + __binary_op, + [__first, __unary_op, __binary_op](_DifferenceType __i, _DifferenceType __j, _Tp __init) { + // Execute serial __brick_transform_reduce, due to the explicit SIMD vectorization (reduction) requires a + // commutative operation for the guarantee of correct scan. + return __internal::__brick_transform_reduce( + __first + __i, + __first + __j, + __init, + __binary_op, + __unary_op, + /*__is_vector*/ std::false_type()); + }, + [__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __j, _Tp __init) { + return __internal::__brick_transform_scan( + __first + __i, + __first + __j, + __result + __i, + __unary_op, + __init, + __binary_op, + _Inclusive(), + _IsVector{}) + .second; + }); + return __result + (__last - __first); + }); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator, + class _OutputIterator, + class _UnaryOperation, + class _Tp, + class _BinaryOperation, + class _Inclusive> +typename std::enable_if<std::is_floating_point<_Tp>::value, _OutputIterator>::type __pattern_transform_scan( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator __first, + _RandomAccessIterator __last, + _OutputIterator __result, + _UnaryOperation __unary_op, + _Tp __init, + _BinaryOperation __binary_op, + _Inclusive) { + using __backend_tag = typename decltype(__tag)::__backend_tag; + + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; + _DifferenceType __n = __last - __first; + + if (__n <= 0) { + return __result; + } + return __internal::__except_handler([&]() { + __par_backend::__parallel_strict_scan( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __n, + __init, + [__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __len) { + return __internal::__brick_transform_scan( + __first + __i, + __first + (__i + __len), + __result + __i, + __unary_op, + _Tp{}, + __binary_op, + _Inclusive(), + _IsVector{}) + .second; + }, + __binary_op, + [__result, &__binary_op](_DifferenceType __i, _DifferenceType __len, _Tp __initial) { + return *(std::transform(__result + __i, + __result + __i + __len, + __result + __i, + [&__initial, &__binary_op](const _Tp& __x) { + return __binary_op(__initial, __x); + }) - + 1); + }, + [](_Tp) {}); + return __result + (__last - __first); + }); +} + +//------------------------------------------------------------------------ +// adjacent_difference +//------------------------------------------------------------------------ + +template <class _ForwardIterator, class _OutputIterator, class _BinaryOperation> +_OutputIterator __brick_adjacent_difference( + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __d_first, + _BinaryOperation __op, + /*is_vector*/ std::false_type) noexcept { + return std::adjacent_difference(__first, __last, __d_first, __op); +} + +template <class _RandomAccessIterator1, class _RandomAccessIterator2, class BinaryOperation> +_RandomAccessIterator2 __brick_adjacent_difference( + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first, + BinaryOperation __op, + /*is_vector=*/std::true_type) noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __last, "Range cannot be empty"); + + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2; + + auto __n = __last - __first; + *__d_first = *__first; + return __unseq_backend::__simd_walk_3( + __first + 1, + __n - 1, + __first, + __d_first + 1, + [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__x, __y); }); +} + +template <class _Tag, class _ExecutionPolicy, class _ForwardIterator, class _OutputIterator, class _BinaryOperation> +_OutputIterator __pattern_adjacent_difference( + _Tag, + _ExecutionPolicy&&, + _ForwardIterator __first, + _ForwardIterator __last, + _OutputIterator __d_first, + _BinaryOperation __op) noexcept { + return __internal::__brick_adjacent_difference(__first, __last, __d_first, __op, typename _Tag::__is_vector{}); +} + +template <class _IsVector, + class _ExecutionPolicy, + class _RandomAccessIterator1, + class _RandomAccessIterator2, + class _BinaryOperation> +_RandomAccessIterator2 __pattern_adjacent_difference( + __parallel_tag<_IsVector> __tag, + _ExecutionPolicy&& __exec, + _RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __d_first, + _BinaryOperation __op) { + _LIBCPP_ASSERT_UNCATEGORIZED(__first != __last, "range cannot be empty"); + typedef typename std::iterator_traits<_RandomAccessIterator1>::reference _ReferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::reference _ReferenceType2; + + using __backend_tag = typename decltype(__tag)::__backend_tag; + + *__d_first = *__first; + __par_backend::__parallel_for( + __backend_tag{}, + std::forward<_ExecutionPolicy>(__exec), + __first, + __last - 1, + [&__op, __d_first, __first](_RandomAccessIterator1 __b, _RandomAccessIterator1 __e) { + _RandomAccessIterator2 __d_b = __d_first + (__b - __first); + __internal::__brick_walk3( + __b, + __e, + __b + 1, + __d_b + 1, + [&__op](_ReferenceType1 __x, _ReferenceType1 __y, _ReferenceType2 __z) { __z = __op(__y, __x); }, + _IsVector{}); + }); + return __d_first + (__last - __first); +} + +} // namespace __internal +} // namespace __pstl + +#endif /* _PSTL_NUMERIC_IMPL_H */ diff --git a/libcxx/include/__pstl/internal/omp/parallel_for.h b/libcxx/include/__pstl/internal/omp/parallel_for.h new file mode 100644 index 000000000000..0f841e531181 --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/parallel_for.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_FOR_H +#define _PSTL_INTERNAL_OMP_PARALLEL_FOR_H + +#include <cstddef> + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template <class _Index, class _Fp> +void +__parallel_for_body(_Index __first, _Index __last, _Fp __f) +{ + // initial partition of the iteration space into chunks + auto __policy = __omp_backend::__chunk_partitioner(__first, __last); + + // To avoid over-subscription we use taskloop for the nested parallelism + _PSTL_PRAGMA(omp taskloop untied mergeable) + for (std::size_t __chunk = 0; __chunk < __policy.__n_chunks; ++__chunk) + { + __pstl::__omp_backend::__process_chunk(__policy, __first, __chunk, __f); + } +} + +//------------------------------------------------------------------------ +// Notation: +// Evaluation of brick f[i,j) for each subrange [i,j) of [first, last) +//------------------------------------------------------------------------ + +template <class _ExecutionPolicy, class _Index, class _Fp> +void +__parallel_for(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f) +{ + if (omp_in_parallel()) + { + // we don't create a nested parallel region in an existing parallel + // region: just create tasks + __pstl::__omp_backend::__parallel_for_body(__first, __last, __f); + } + else + { + // in any case (nested or non-nested) one parallel region is created and + // only one thread creates a set of tasks + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) { __pstl::__omp_backend::__parallel_for_body(__first, __last, __f); } + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_FOR_H diff --git a/libcxx/include/__pstl/internal/omp/parallel_for_each.h b/libcxx/include/__pstl/internal/omp/parallel_for_each.h new file mode 100644 index 000000000000..b9bfb05930a1 --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/parallel_for_each.h @@ -0,0 +1,59 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_FOR_EACH_H +#define _PSTL_INTERNAL_OMP_PARALLEL_FOR_EACH_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template <class _ForwardIterator, class _Fp> +void +__parallel_for_each_body(_ForwardIterator __first, _ForwardIterator __last, _Fp __f) +{ + using DifferenceType = typename std::iterator_traits<_ForwardIterator>::difference_type; + // TODO: Think of an approach to remove the std::distance call + auto __size = std::distance(__first, __last); + + _PSTL_PRAGMA(omp taskloop untied mergeable) + for (DifferenceType __index = 0; __index < __size; ++__index) + { + // TODO: Think of an approach to remove the increment here each time. + auto __iter = std::next(__first, __index); + __f(*__iter); + } +} + +template <class _ExecutionPolicy, class _ForwardIterator, class _Fp> +void +__parallel_for_each(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Fp __f) +{ + if (omp_in_parallel()) + { + // we don't create a nested parallel region in an existing parallel + // region: just create tasks + __pstl::__omp_backend::__parallel_for_each_body(__first, __last, __f); + } + else + { + // in any case (nested or non-nested) one parallel region is created and + // only one thread creates a set of tasks + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) { __pstl::__omp_backend::__parallel_for_each_body(__first, __last, __f); } + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_FOR_EACH_H diff --git a/libcxx/include/__pstl/internal/omp/parallel_invoke.h b/libcxx/include/__pstl/internal/omp/parallel_invoke.h new file mode 100644 index 000000000000..045ccbe9a18c --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/parallel_invoke.h @@ -0,0 +1,50 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_INVOKE_H +#define _PSTL_INTERNAL_OMP_PARALLEL_INVOKE_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template <typename _F1, typename _F2> +void +__parallel_invoke_body(_F1&& __f1, _F2&& __f2) +{ + _PSTL_PRAGMA(omp taskgroup) + { + _PSTL_PRAGMA(omp task untied mergeable) { std::forward<_F1>(__f1)(); } + _PSTL_PRAGMA(omp task untied mergeable) { std::forward<_F2>(__f2)(); } + } +} + +template <class _ExecutionPolicy, typename _F1, typename _F2> +void +__parallel_invoke(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) +{ + if (omp_in_parallel()) + { + __pstl::__omp_backend::__parallel_invoke_body(std::forward<_F1>(__f1), std::forward<_F2>(__f2)); + } + else + { + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) + __pstl::__omp_backend::__parallel_invoke_body(std::forward<_F1>(__f1), std::forward<_F2>(__f2)); + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_INVOKE_H diff --git a/libcxx/include/__pstl/internal/omp/parallel_merge.h b/libcxx/include/__pstl/internal/omp/parallel_merge.h new file mode 100644 index 000000000000..e6f82c5e1866 --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/parallel_merge.h @@ -0,0 +1,98 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_MERGE_H +#define _PSTL_INTERNAL_OMP_PARALLEL_MERGE_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _RandomAccessIterator3, + typename _Compare, typename _LeafMerge> +void +__parallel_merge_body(std::size_t __size_x, std::size_t __size_y, _RandomAccessIterator1 __xs, + _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, _RandomAccessIterator2 __ye, + _RandomAccessIterator3 __zs, _Compare __comp, _LeafMerge __leaf_merge) +{ + + if (__size_x + __size_y <= __omp_backend::__default_chunk_size) + { + __leaf_merge(__xs, __xe, __ys, __ye, __zs, __comp); + return; + } + + _RandomAccessIterator1 __xm; + _RandomAccessIterator2 __ym; + + if (__size_x < __size_y) + { + __ym = __ys + (__size_y / 2); + __xm = std::upper_bound(__xs, __xe, *__ym, __comp); + } + else + { + __xm = __xs + (__size_x / 2); + __ym = std::lower_bound(__ys, __ye, *__xm, __comp); + } + + auto __zm = __zs + (__xm - __xs) + (__ym - __ys); + + _PSTL_PRAGMA(omp task untied mergeable default(none) + firstprivate(__xs, __xm, __ys, __ym, __zs, __comp, __leaf_merge)) + __pstl::__omp_backend::__parallel_merge_body(__xm - __xs, __ym - __ys, __xs, __xm, __ys, __ym, __zs, __comp, + __leaf_merge); + + _PSTL_PRAGMA(omp task untied mergeable default(none) + firstprivate(__xm, __xe, __ym, __ye, __zm, __comp, __leaf_merge)) + __pstl::__omp_backend::__parallel_merge_body(__xe - __xm, __ye - __ym, __xm, __xe, __ym, __ye, __zm, __comp, + __leaf_merge); + + _PSTL_PRAGMA(omp taskwait) +} + +template <class _ExecutionPolicy, typename _RandomAccessIterator1, typename _RandomAccessIterator2, + typename _RandomAccessIterator3, typename _Compare, typename _LeafMerge> +void +__parallel_merge(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&& /*__exec*/, _RandomAccessIterator1 __xs, + _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, _RandomAccessIterator2 __ye, + _RandomAccessIterator3 __zs, _Compare __comp, _LeafMerge __leaf_merge) + +{ + std::size_t __size_x = __xe - __xs; + std::size_t __size_y = __ye - __ys; + + /* + * Run the merge in parallel by chunking it up. Use the smaller range (if any) as the iteration range, and the + * larger range as the search range. + */ + + if (omp_in_parallel()) + { + __pstl::__omp_backend::__parallel_merge_body(__size_x, __size_y, __xs, __xe, __ys, __ye, __zs, __comp, + __leaf_merge); + } + else + { + _PSTL_PRAGMA(omp parallel) + { + _PSTL_PRAGMA(omp single nowait) + __pstl::__omp_backend::__parallel_merge_body(__size_x, __size_y, __xs, __xe, __ys, __ye, __zs, __comp, + __leaf_merge); + } + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_MERGE_H diff --git a/libcxx/include/__pstl/internal/omp/parallel_reduce.h b/libcxx/include/__pstl/internal/omp/parallel_reduce.h new file mode 100644 index 000000000000..841d48fc3051 --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/parallel_reduce.h @@ -0,0 +1,73 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_REDUCE_H +#define _PSTL_INTERNAL_OMP_PARALLEL_REDUCE_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template <class _RandomAccessIterator, class _Value, typename _RealBody, typename _Reduction> +_Value +__parallel_reduce_body(_RandomAccessIterator __first, _RandomAccessIterator __last, _Value __identity, + _RealBody __real_body, _Reduction __reduce) +{ + if (__should_run_serial(__first, __last)) + { + return __real_body(__first, __last, __identity); + } + + auto __middle = __first + ((__last - __first) / 2); + _Value __v1(__identity), __v2(__identity); + __parallel_invoke_body( + [&]() { __v1 = __parallel_reduce_body(__first, __middle, __identity, __real_body, __reduce); }, + [&]() { __v2 = __parallel_reduce_body(__middle, __last, __identity, __real_body, __reduce); }); + + return __reduce(__v1, __v2); +} + +//------------------------------------------------------------------------ +// Notation: +// r(i,j,init) returns reduction of init with reduction over [i,j) +// c(x,y) combines values x and y that were the result of r +//------------------------------------------------------------------------ + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _Value, typename _RealBody, typename _Reduction> +_Value +__parallel_reduce(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Value __identity, _RealBody __real_body, _Reduction __reduction) +{ + // We don't create a nested parallel region in an existing parallel region: + // just create tasks. + if (omp_in_parallel()) + { + return __pstl::__omp_backend::__parallel_reduce_body(__first, __last, __identity, __real_body, __reduction); + } + + // In any case (nested or non-nested) one parallel region is created and only + // one thread creates a set of tasks. + _Value __res = __identity; + + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) + { + __res = __pstl::__omp_backend::__parallel_reduce_body(__first, __last, __identity, __real_body, __reduction); + } + + return __res; +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_REDUCE_H diff --git a/libcxx/include/__pstl/internal/omp/parallel_scan.h b/libcxx/include/__pstl/internal/omp/parallel_scan.h new file mode 100644 index 000000000000..f3eb967ca4fb --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/parallel_scan.h @@ -0,0 +1,136 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_SCAN_H +#define _PSTL_INTERNAL_OMP_PARALLEL_SCAN_H + +#include "parallel_invoke.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template <typename _Index> +_Index +__split(_Index __m) +{ + _Index __k = 1; + while (2 * __k < __m) + __k *= 2; + return __k; +} + +template <typename _Index, typename _Tp, typename _Rp, typename _Cp> +void +__upsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsize, _Rp __reduce, _Cp __combine) +{ + if (__m == 1) + __r[0] = __reduce(__i * __tilesize, __lastsize); + else + { + _Index __k = __split(__m); + __omp_backend::__parallel_invoke_body( + [=] { __omp_backend::__upsweep(__i, __k, __tilesize, __r, __tilesize, __reduce, __combine); }, + [=] { + __omp_backend::__upsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize, __reduce, __combine); + }); + if (__m == 2 * __k) + __r[__m - 1] = __combine(__r[__k - 1], __r[__m - 1]); + } +} + +template <typename _Index, typename _Tp, typename _Cp, typename _Sp> +void +__downsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsize, _Tp __initial, _Cp __combine, + _Sp __scan) +{ + if (__m == 1) + __scan(__i * __tilesize, __lastsize, __initial); + else + { + const _Index __k = __split(__m); + __omp_backend::__parallel_invoke_body( + [=] { __omp_backend::__downsweep(__i, __k, __tilesize, __r, __tilesize, __initial, __combine, __scan); }, + // Assumes that __combine never throws. + // TODO: Consider adding a requirement for user functors to be constant. + [=, &__combine] + { + __omp_backend::__downsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize, + __combine(__initial, __r[__k - 1]), __combine, __scan); + }); + } +} + +template <typename _ExecutionPolicy, typename _Index, typename _Tp, typename _Rp, typename _Cp, typename _Sp, + typename _Ap> +void +__parallel_strict_scan_body(_Index __n, _Tp __initial, _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) +{ + _Index __p = omp_get_num_threads(); + const _Index __slack = 4; + _Index __tilesize = (__n - 1) / (__slack * __p) + 1; + _Index __m = (__n - 1) / __tilesize; + __buffer<_Tp> __buf(__m + 1); + _Tp* __r = __buf.get(); + + __omp_backend::__upsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __reduce, __combine); + + std::size_t __k = __m + 1; + _Tp __t = __r[__k - 1]; + while ((__k &= __k - 1)) + { + __t = __combine(__r[__k - 1], __t); + } + + __apex(__combine(__initial, __t)); + __omp_backend::__downsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __initial, + __combine, __scan); +} + +template <class _ExecutionPolicy, typename _Index, typename _Tp, typename _Rp, typename _Cp, typename _Sp, typename _Ap> +void +__parallel_strict_scan(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _Index __n, _Tp __initial, + _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) +{ + if (__n <= __default_chunk_size) + { + _Tp __sum = __initial; + if (__n) + { + __sum = __combine(__sum, __reduce(_Index(0), __n)); + } + __apex(__sum); + if (__n) + { + __scan(_Index(0), __n, __initial); + } + return; + } + + if (omp_in_parallel()) + { + __pstl::__omp_backend::__parallel_strict_scan_body<_ExecutionPolicy>(__n, __initial, __reduce, __combine, + __scan, __apex); + } + else + { + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) + { + __pstl::__omp_backend::__parallel_strict_scan_body<_ExecutionPolicy>(__n, __initial, __reduce, __combine, + __scan, __apex); + } + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_SCAN_H diff --git a/libcxx/include/__pstl/internal/omp/parallel_stable_partial_sort.h b/libcxx/include/__pstl/internal/omp/parallel_stable_partial_sort.h new file mode 100644 index 000000000000..06cd55bb4899 --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/parallel_stable_partial_sort.h @@ -0,0 +1,33 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_STABLE_PARTIAL_SORT_H +#define _PSTL_INTERNAL_OMP_PARALLEL_STABLE_PARTIAL_SORT_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template <typename _RandomAccessIterator, typename _Compare, typename _LeafSort> +void +__parallel_stable_partial_sort(__pstl::__internal::__openmp_backend_tag, _RandomAccessIterator __xs, + _RandomAccessIterator __xe, _Compare __comp, _LeafSort __leaf_sort, + std::size_t /* __nsort */) +{ + // TODO: "Parallel partial sort needs to be implemented."); + __leaf_sort(__xs, __xe, __comp); +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_STABLE_PARTIAL_SORT_H diff --git a/libcxx/include/__pstl/internal/omp/parallel_stable_sort.h b/libcxx/include/__pstl/internal/omp/parallel_stable_sort.h new file mode 100644 index 000000000000..e4d067662726 --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/parallel_stable_sort.h @@ -0,0 +1,160 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_STABLE_SORT_H +#define _PSTL_INTERNAL_OMP_PARALLEL_STABLE_SORT_H + +#include "util.h" +#include "parallel_merge.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +namespace __sort_details +{ +struct __move_value +{ + template <typename _Iterator, typename _OutputIterator> + void + operator()(_Iterator __x, _OutputIterator __z) const + { + *__z = std::move(*__x); + } +}; + +template <typename _RandomAccessIterator, typename _OutputIterator> +_OutputIterator +__parallel_move_range(_RandomAccessIterator __first1, _RandomAccessIterator __last1, _OutputIterator __d_first) +{ + std::size_t __size = __last1 - __first1; + + // Perform serial moving of small chunks + + if (__size <= __default_chunk_size) + { + return std::move(__first1, __last1, __d_first); + } + + // Perform parallel moving of larger chunks + auto __policy = __pstl::__omp_backend::__chunk_partitioner(__first1, __last1); + + _PSTL_PRAGMA(omp taskloop) + for (std::size_t __chunk = 0; __chunk < __policy.__n_chunks; ++__chunk) + { + __pstl::__omp_backend::__process_chunk(__policy, __first1, __chunk, + [&](auto __chunk_first, auto __chunk_last) + { + auto __chunk_offset = __chunk_first - __first1; + auto __output_it = __d_first + __chunk_offset; + std::move(__chunk_first, __chunk_last, __output_it); + }); + } + + return __d_first + __size; +} + +struct __move_range +{ + template <typename _RandomAccessIterator, typename _OutputIterator> + _OutputIterator + operator()(_RandomAccessIterator __first1, _RandomAccessIterator __last1, _OutputIterator __d_first) const + { + return __pstl::__omp_backend::__sort_details::__parallel_move_range(__first1, __last1, __d_first); + } +}; +} // namespace __sort_details + +template <typename _RandomAccessIterator, typename _Compare, typename _LeafSort> +void +__parallel_stable_sort_body(_RandomAccessIterator __xs, _RandomAccessIterator __xe, _Compare __comp, + _LeafSort __leaf_sort) +{ + using _ValueType = typename std::iterator_traits<_RandomAccessIterator>::value_type; + using _VecType = typename std::vector<_ValueType>; + using _OutputIterator = typename _VecType::iterator; + using _MoveValue = typename __omp_backend::__sort_details::__move_value; + using _MoveRange = __omp_backend::__sort_details::__move_range; + + if (__should_run_serial(__xs, __xe)) + { + __leaf_sort(__xs, __xe, __comp); + } + else + { + std::size_t __size = __xe - __xs; + auto __mid = __xs + (__size / 2); + __pstl::__omp_backend::__parallel_invoke_body( + [&]() { __parallel_stable_sort_body(__xs, __mid, __comp, __leaf_sort); }, + [&]() { __parallel_stable_sort_body(__mid, __xe, __comp, __leaf_sort); }); + + // Perform a parallel merge of the sorted ranges into __output_data. + _VecType __output_data(__size); + _MoveValue __move_value; + _MoveRange __move_range; + __utils::__serial_move_merge __merge(__size); + __pstl::__omp_backend::__parallel_merge_body( + __mid - __xs, __xe - __mid, __xs, __mid, __mid, __xe, __output_data.begin(), __comp, + [&__merge, &__move_value, &__move_range](_RandomAccessIterator __as, _RandomAccessIterator __ae, + _RandomAccessIterator __bs, _RandomAccessIterator __be, + _OutputIterator __cs, _Compare __comp) + { __merge(__as, __ae, __bs, __be, __cs, __comp, __move_value, __move_value, __move_range, __move_range); }); + + // Move the values from __output_data back in the original source range. + __pstl::__omp_backend::__sort_details::__parallel_move_range(__output_data.begin(), __output_data.end(), __xs); + } +} + +template <class _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _LeafSort> +void +__parallel_stable_sort(__pstl::__internal::__openmp_backend_tag __tag, _ExecutionPolicy&& /*__exec*/, + _RandomAccessIterator __xs, _RandomAccessIterator __xe, _Compare __comp, _LeafSort __leaf_sort, + std::size_t __nsort = 0) +{ + auto __count = static_cast<std::size_t>(__xe - __xs); + if (__count <= __default_chunk_size || __nsort < __count) + { + __leaf_sort(__xs, __xe, __comp); + return; + } + + // TODO: the partial sort implementation should + // be shared with the other backends. + + if (omp_in_parallel()) + { + if (__count <= __nsort) + { + __pstl::__omp_backend::__parallel_stable_sort_body(__xs, __xe, __comp, __leaf_sort); + } + else + { + __pstl::__omp_backend::__parallel_stable_partial_sort(__tag, __xs, __xe, __comp, __leaf_sort, __nsort); + } + } + else + { + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) + if (__count <= __nsort) + { + __pstl::__omp_backend::__parallel_stable_sort_body(__xs, __xe, __comp, __leaf_sort); + } + else + { + __pstl::__omp_backend::__parallel_stable_partial_sort(__tag, __xs, __xe, __comp, __leaf_sort, __nsort); + } + } +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_STABLE_SORT_H diff --git a/libcxx/include/__pstl/internal/omp/parallel_transform_reduce.h b/libcxx/include/__pstl/internal/omp/parallel_transform_reduce.h new file mode 100644 index 000000000000..1d4cc0a5974d --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/parallel_transform_reduce.h @@ -0,0 +1,113 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_REDUCE_H +#define _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_REDUCE_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +//------------------------------------------------------------------------ +// parallel_transform_reduce +// +// Notation: +// r(i,j,init) returns reduction of init with reduction over [i,j) +// u(i) returns f(i,i+1,identity) for a hypothetical left identity element +// of r c(x,y) combines values x and y that were the result of r or u +//------------------------------------------------------------------------ + +template <class _RandomAccessIterator, class _UnaryOp, class _Value, class _Combiner, class _Reduction> +auto +__transform_reduce_body(_RandomAccessIterator __first, _RandomAccessIterator __last, _UnaryOp __unary_op, _Value __init, + _Combiner __combiner, _Reduction __reduction) +{ + const std::size_t __num_threads = omp_get_num_threads(); + const std::size_t __size = __last - __first; + + // Initial partition of the iteration space into chunks. If the range is too small, + // this will result in a nonsense policy, so we check on the size as well below. + auto __policy = __omp_backend::__chunk_partitioner(__first + __num_threads, __last); + + if (__size <= __num_threads || __policy.__n_chunks < 2) + { + return __reduction(__first, __last, __init); + } + + // Here, we cannot use OpenMP UDR because we must store the init value in + // the combiner and it will be used several times. Although there should be + // the only one; we manually generate the identity elements for each thread. + std::vector<_Value> __accums; + __accums.reserve(__num_threads); + + // initialize accumulators for all threads + for (std::size_t __i = 0; __i < __num_threads; ++__i) + { + __accums.emplace_back(__unary_op(__first + __i)); + } + + // main loop + _PSTL_PRAGMA(omp taskloop shared(__accums)) + for (std::size_t __chunk = 0; __chunk < __policy.__n_chunks; ++__chunk) + { + __pstl::__omp_backend::__process_chunk(__policy, __first + __num_threads, __chunk, + [&](auto __chunk_first, auto __chunk_last) + { + auto __thread_num = omp_get_thread_num(); + __accums[__thread_num] = + __reduction(__chunk_first, __chunk_last, __accums[__thread_num]); + }); + } + + // combine by accumulators + for (std::size_t __i = 0; __i < __num_threads; ++__i) + { + __init = __combiner(__init, __accums[__i]); + } + + return __init; +} + +template <class _ExecutionPolicy, class _RandomAccessIterator, class _UnaryOp, class _Value, class _Combiner, + class _Reduction> +_Value +__parallel_transform_reduce(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __first, + _RandomAccessIterator __last, _UnaryOp __unary_op, _Value __init, _Combiner __combiner, + _Reduction __reduction) +{ + _Value __result = __init; + if (omp_in_parallel()) + { + // We don't create a nested parallel region in an existing parallel + // region: just create tasks + __result = __pstl::__omp_backend::__transform_reduce_body(__first, __last, __unary_op, __init, __combiner, + __reduction); + } + else + { + // Create a parallel region, and a single thread will create tasks + // for the region. + _PSTL_PRAGMA(omp parallel) + _PSTL_PRAGMA(omp single nowait) + { + __result = __pstl::__omp_backend::__transform_reduce_body(__first, __last, __unary_op, __init, __combiner, + __reduction); + } + } + + return __result; +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_REDUCE_H diff --git a/libcxx/include/__pstl/internal/omp/parallel_transform_scan.h b/libcxx/include/__pstl/internal/omp/parallel_transform_scan.h new file mode 100644 index 000000000000..f83628994bc2 --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/parallel_transform_scan.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_SCAN_H +#define _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_SCAN_H + +#include "util.h" + +namespace __pstl +{ +namespace __omp_backend +{ + +template <class _ExecutionPolicy, class _Index, class _Up, class _Tp, class _Cp, class _Rp, class _Sp> +_Tp +__parallel_transform_scan(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _Index __n, _Up /* __u */, + _Tp __init, _Cp /* __combine */, _Rp /* __brick_reduce */, _Sp __scan) +{ + // TODO: parallelize this function. + return __scan(_Index(0), __n, __init); +} + +} // namespace __omp_backend +} // namespace __pstl +#endif // _PSTL_INTERNAL_OMP_PARALLEL_TRANSFORM_SCAN_H diff --git a/libcxx/include/__pstl/internal/omp/util.h b/libcxx/include/__pstl/internal/omp/util.h new file mode 100644 index 000000000000..3c1a92e03cb9 --- /dev/null +++ b/libcxx/include/__pstl/internal/omp/util.h @@ -0,0 +1,171 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_INTERNAL_OMP_UTIL_H +#define _PSTL_INTERNAL_OMP_UTIL_H + +#include <algorithm> +#include <atomic> +#include <iterator> +#include <cstddef> +#include <cstdio> +#include <memory> +#include <vector> +#include <omp.h> + +#include "../parallel_backend_utils.h" +#include "../unseq_backend_simd.h" +#include "../utils.h" + +// Portability "#pragma" definition +#ifdef _MSC_VER +# define _PSTL_PRAGMA(x) __pragma(x) +#else +# define _PSTL_PRAGMA(x) _Pragma(# x) +#endif + +namespace __pstl +{ +namespace __omp_backend +{ + +//------------------------------------------------------------------------ +// use to cancel execution +//------------------------------------------------------------------------ +inline void +__cancel_execution() +{ + // TODO: Figure out how to make cancelation work. +} + +//------------------------------------------------------------------------ +// raw buffer +//------------------------------------------------------------------------ + +template <typename _Tp> +class __buffer +{ + std::allocator<_Tp> __allocator_; + _Tp* __ptr_; + const std::size_t __buf_size_; + __buffer(const __buffer&) = delete; + void + operator=(const __buffer&) = delete; + + public: + __buffer(std::size_t __n) : __allocator_(), __ptr_(__allocator_.allocate(__n)), __buf_size_(__n) {} + + operator bool() const { return __ptr_ != nullptr; } + + _Tp* + get() const + { + return __ptr_; + } + ~__buffer() { __allocator_.deallocate(__ptr_, __buf_size_); } +}; + +// Preliminary size of each chunk: requires further discussion +inline constexpr std::size_t __default_chunk_size = 2048; + +// Convenience function to determine when we should run serial. +template <typename _Iterator, std::enable_if_t<!std::is_integral<_Iterator>::value, bool> = true> +constexpr auto +__should_run_serial(_Iterator __first, _Iterator __last) -> bool +{ + using _difference_type = typename std::iterator_traits<_Iterator>::difference_type; + auto __size = std::distance(__first, __last); + return __size <= static_cast<_difference_type>(__default_chunk_size); +} + +template <typename _Index, std::enable_if_t<std::is_integral<_Index>::value, bool> = true> +constexpr auto +__should_run_serial(_Index __first, _Index __last) -> bool +{ + using _difference_type = _Index; + auto __size = __last - __first; + return __size <= static_cast<_difference_type>(__default_chunk_size); +} + +struct __chunk_metrics +{ + std::size_t __n_chunks; + std::size_t __chunk_size; + std::size_t __first_chunk_size; +}; + +// The iteration space partitioner according to __requested_chunk_size +template <class _RandomAccessIterator, class _Size = std::size_t> +auto +__chunk_partitioner(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Size __requested_chunk_size = __default_chunk_size) -> __chunk_metrics +{ + /* + * This algorithm improves distribution of elements in chunks by avoiding + * small tail chunks. The leftover elements that do not fit neatly into + * the chunk size are redistributed to early chunks. This improves + * utilization of the processor's prefetch and reduces the number of + * tasks needed by 1. + */ + + const _Size __n = __last - __first; + _Size __n_chunks = 0; + _Size __chunk_size = 0; + _Size __first_chunk_size = 0; + if (__n < __requested_chunk_size) + { + __chunk_size = __n; + __first_chunk_size = __n; + __n_chunks = 1; + return __chunk_metrics{__n_chunks, __chunk_size, __first_chunk_size}; + } + + __n_chunks = (__n / __requested_chunk_size) + 1; + __chunk_size = __n / __n_chunks; + __first_chunk_size = __chunk_size; + const _Size __n_leftover_items = __n - (__n_chunks * __chunk_size); + + if (__n_leftover_items == __chunk_size) + { + __n_chunks += 1; + return __chunk_metrics{__n_chunks, __chunk_size, __first_chunk_size}; + } + else if (__n_leftover_items == 0) + { + __first_chunk_size = __chunk_size; + return __chunk_metrics{__n_chunks, __chunk_size, __first_chunk_size}; + } + + const _Size __n_extra_items_per_chunk = __n_leftover_items / __n_chunks; + const _Size __n_final_leftover_items = __n_leftover_items - (__n_extra_items_per_chunk * __n_chunks); + + __chunk_size += __n_extra_items_per_chunk; + __first_chunk_size = __chunk_size + __n_final_leftover_items; + + return __chunk_metrics{__n_chunks, __chunk_size, __first_chunk_size}; +} + +template <typename _Iterator, typename _Index, typename _Func> +void +__process_chunk(const __chunk_metrics& __metrics, _Iterator __base, _Index __chunk_index, _Func __f) +{ + auto __this_chunk_size = __chunk_index == 0 ? __metrics.__first_chunk_size : __metrics.__chunk_size; + auto __index = __chunk_index == 0 ? 0 + : (__chunk_index * __metrics.__chunk_size) + + (__metrics.__first_chunk_size - __metrics.__chunk_size); + auto __first = __base + __index; + auto __last = __first + __this_chunk_size; + __f(__first, __last); +} + +} // namespace __omp_backend +} // namespace __pstl + +#endif // _PSTL_INTERNAL_OMP_UTIL_H diff --git a/libcxx/include/__pstl/internal/parallel_backend.h b/libcxx/include/__pstl/internal/parallel_backend.h new file mode 100644 index 000000000000..9c30ee142746 --- /dev/null +++ b/libcxx/include/__pstl/internal/parallel_backend.h @@ -0,0 +1,39 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_PARALLEL_BACKEND_H +#define _PSTL_PARALLEL_BACKEND_H + +#include <__config> + +#if defined(_PSTL_PAR_BACKEND_SERIAL) +# include "parallel_backend_serial.h" +# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 +namespace __pstl +{ +namespace __par_backend = __serial_backend; +} // namespace __pstl +# endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 +#elif defined(_PSTL_PAR_BACKEND_TBB) +# include "parallel_backend_tbb.h" +namespace __pstl +{ +namespace __par_backend = __tbb_backend; +} +#elif defined(_PSTL_PAR_BACKEND_OPENMP) +# include "parallel_backend_omp.h" +namespace __pstl +{ +namespace __par_backend = __omp_backend; +} +#else +# error "No backend set" +#endif + +#endif /* _PSTL_PARALLEL_BACKEND_H */ diff --git a/libcxx/include/__pstl/internal/parallel_backend_omp.h b/libcxx/include/__pstl/internal/parallel_backend_omp.h new file mode 100644 index 000000000000..7398cfe55929 --- /dev/null +++ b/libcxx/include/__pstl/internal/parallel_backend_omp.h @@ -0,0 +1,58 @@ +// -*- C++ -*- +// -*-===----------------------------------------------------------------------===// +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_PARALLEL_BACKEND_OMP_H +#define _PSTL_PARALLEL_BACKEND_OMP_H + +//------------------------------------------------------------------------ +// parallel_invoke +//------------------------------------------------------------------------ + +#include "./omp/parallel_invoke.h" + +//------------------------------------------------------------------------ +// parallel_for +//------------------------------------------------------------------------ + +#include "./omp/parallel_for.h" + +//------------------------------------------------------------------------ +// parallel_for_each +//------------------------------------------------------------------------ + +#include "./omp/parallel_for_each.h" + +//------------------------------------------------------------------------ +// parallel_reduce +//------------------------------------------------------------------------ + +#include "./omp/parallel_reduce.h" +#include "./omp/parallel_transform_reduce.h" + +//------------------------------------------------------------------------ +// parallel_scan +//------------------------------------------------------------------------ + +#include "./omp/parallel_scan.h" +#include "./omp/parallel_transform_scan.h" + +//------------------------------------------------------------------------ +// parallel_stable_sort +//------------------------------------------------------------------------ + +#include "./omp/parallel_stable_partial_sort.h" +#include "./omp/parallel_stable_sort.h" + +//------------------------------------------------------------------------ +// parallel_merge +//------------------------------------------------------------------------ +#include "./omp/parallel_merge.h" + +#endif //_PSTL_PARALLEL_BACKEND_OMP_H diff --git a/libcxx/include/__pstl/internal/parallel_backend_serial.h b/libcxx/include/__pstl/internal/parallel_backend_serial.h new file mode 100644 index 000000000000..dd72222f20ae --- /dev/null +++ b/libcxx/include/__pstl/internal/parallel_backend_serial.h @@ -0,0 +1,106 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_PARALLEL_BACKEND_SERIAL_H +#define _PSTL_PARALLEL_BACKEND_SERIAL_H + +#include <__config> +#include <__memory/allocator.h> +#include <__pstl/internal/execution_impl.h> +#include <__utility/forward.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +namespace __pstl +{ +namespace __serial_backend +{ + +template <typename _Tp> +class __buffer +{ + std::allocator<_Tp> __allocator_; + _Tp* __ptr_; + const std::size_t __buf_size_; + __buffer(const __buffer&) = delete; + void + operator=(const __buffer&) = delete; + + public: + _LIBCPP_HIDE_FROM_ABI + __buffer(std::size_t __n) : __allocator_(), __ptr_(__allocator_.allocate(__n)), __buf_size_(__n) {} + + _LIBCPP_HIDE_FROM_ABI operator bool() const { return __ptr_ != nullptr; } + _LIBCPP_HIDE_FROM_ABI _Tp* + get() const + { + return __ptr_; + } + _LIBCPP_HIDE_FROM_ABI ~__buffer() { __allocator_.deallocate(__ptr_, __buf_size_); } +}; + +template <class _ExecutionPolicy, class _Value, class _Index, typename _RealBody, typename _Reduction> +_LIBCPP_HIDE_FROM_ABI _Value +__parallel_reduce(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, + const _Value& __identity, const _RealBody& __real_body, const _Reduction&) +{ + if (__first == __last) + { + return __identity; + } + else + { + return __real_body(__first, __last, __identity); + } +} + +template <class _ExecutionPolicy, typename _Index, typename _Tp, typename _Rp, typename _Cp, typename _Sp, typename _Ap> +_LIBCPP_HIDE_FROM_ABI void +__parallel_strict_scan(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __n, _Tp __initial, + _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) +{ + _Tp __sum = __initial; + if (__n) + __sum = __combine(__sum, __reduce(_Index(0), __n)); + __apex(__sum); + if (__n) + __scan(_Index(0), __n, __initial); +} + +template <class _ExecutionPolicy, class _Index, class _UnaryOp, class _Tp, class _BinaryOp, class _Reduce, class _Scan> +_LIBCPP_HIDE_FROM_ABI _Tp +__parallel_transform_scan(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _Index __n, _UnaryOp, + _Tp __init, _BinaryOp, _Reduce, _Scan __scan) +{ + return __scan(_Index(0), __n, __init); +} + +template <class _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _LeafSort> +_LIBCPP_HIDE_FROM_ABI void +__parallel_stable_sort(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp, _LeafSort __leaf_sort, std::size_t = 0) +{ + __leaf_sort(__first, __last, __comp); +} + +template <class _ExecutionPolicy, typename _F1, typename _F2> +_LIBCPP_HIDE_FROM_ABI void +__parallel_invoke(__pstl::__internal::__serial_backend_tag, _ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) +{ + std::forward<_F1>(__f1)(); + std::forward<_F2>(__f2)(); +} + +} // namespace __serial_backend +} // namespace __pstl + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif /* _PSTL_PARALLEL_BACKEND_SERIAL_H */ diff --git a/libcxx/include/__pstl/internal/parallel_backend_tbb.h b/libcxx/include/__pstl/internal/parallel_backend_tbb.h new file mode 100644 index 000000000000..6a9a05ddd61f --- /dev/null +++ b/libcxx/include/__pstl/internal/parallel_backend_tbb.h @@ -0,0 +1,1295 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_PARALLEL_BACKEND_TBB_H +#define _PSTL_PARALLEL_BACKEND_TBB_H + +#include <__assert> +#include <__config> +#include <algorithm> +#include <type_traits> + +#include "parallel_backend_utils.h" + +// Bring in minimal required subset of Intel TBB +#include <tbb/blocked_range.h> +#include <tbb/parallel_for.h> +#include <tbb/parallel_reduce.h> +#include <tbb/parallel_scan.h> +#include <tbb/parallel_invoke.h> +#include <tbb/task_arena.h> +#include <tbb/tbb_allocator.h> +#include <tbb/task.h> + +#if TBB_INTERFACE_VERSION < 10000 +# error Intel(R) Threading Building Blocks 2018 is required; older versions are not supported. +#endif + +namespace __pstl +{ +namespace __tbb_backend +{ + +//! Raw memory buffer with automatic freeing and no exceptions. +/** Some of our algorithms need to start with raw memory buffer, +not an initialize array, because initialization/destruction +would make the span be at least O(N). */ +// tbb::allocator can improve performance in some cases. +template <typename _Tp> +class __buffer +{ + tbb::tbb_allocator<_Tp> _M_allocator; + _Tp* _M_ptr; + const std::size_t _M_buf_size; + __buffer(const __buffer&) = delete; + void + operator=(const __buffer&) = delete; + + public: + //! Try to obtain buffer of given size to store objects of _Tp type + __buffer(std::size_t n) : _M_allocator(), _M_ptr(_M_allocator.allocate(n)), _M_buf_size(n) {} + //! True if buffer was successfully obtained, zero otherwise. + operator bool() const { return _M_ptr != NULL; } + //! Return pointer to buffer, or NULL if buffer could not be obtained. + _Tp* + get() const + { + return _M_ptr; + } + //! Destroy buffer + ~__buffer() { _M_allocator.deallocate(_M_ptr, _M_buf_size); } +}; + +// Wrapper for tbb::task +inline void +__cancel_execution() +{ +#if TBB_INTERFACE_VERSION <= 12000 + tbb::task::self().group()->cancel_group_execution(); +#else + tbb::task::current_context()->cancel_group_execution(); +#endif +} + +//------------------------------------------------------------------------ +// parallel_for +//------------------------------------------------------------------------ + +template <class _Index, class _RealBody> +class __parallel_for_body +{ + public: + __parallel_for_body(const _RealBody& __body) : _M_body(__body) {} + __parallel_for_body(const __parallel_for_body& __body) : _M_body(__body._M_body) {} + void + operator()(const tbb::blocked_range<_Index>& __range) const + { + _M_body(__range.begin(), __range.end()); + } + + private: + _RealBody _M_body; +}; + +//! Evaluation of brick f[i,j) for each subrange [i,j) of [first,last) +// wrapper over tbb::parallel_for +template <class _ExecutionPolicy, class _Index, class _Fp> +void +__parallel_for(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f) +{ + tbb::this_task_arena::isolate([=]() { + tbb::parallel_for(tbb::blocked_range<_Index>(__first, __last), __parallel_for_body<_Index, _Fp>(__f)); + }); +} + +//! Evaluation of brick f[i,j) for each subrange [i,j) of [first,last) +// wrapper over tbb::parallel_reduce +template <class _ExecutionPolicy, class _Value, class _Index, typename _RealBody, typename _Reduction> +_Value +__parallel_reduce(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, + const _Value& __identity, const _RealBody& __real_body, const _Reduction& __reduction) +{ + return tbb::this_task_arena::isolate([__first, __last, &__identity, &__real_body, &__reduction]() -> _Value { + return tbb::parallel_reduce( + tbb::blocked_range<_Index>(__first, __last), __identity, + [__real_body](const tbb::blocked_range<_Index>& __r, const _Value& __value) -> _Value { + return __real_body(__r.begin(), __r.end(), __value); + }, + __reduction); + }); +} + +//------------------------------------------------------------------------ +// parallel_transform_reduce +// +// Notation: +// r(i,j,init) returns reduction of init with reduction over [i,j) +// u(i) returns f(i,i+1,identity) for a hypothetical left identity element of r +// c(x,y) combines values x and y that were the result of r or u +//------------------------------------------------------------------------ + +template <class _Index, class _Up, class _Tp, class _Cp, class _Rp> +struct __par_trans_red_body +{ + alignas(_Tp) char _M_sum_storage[sizeof(_Tp)]; // Holds generalized non-commutative sum when has_sum==true + _Rp _M_brick_reduce; // Most likely to have non-empty layout + _Up _M_u; + _Cp _M_combine; + bool _M_has_sum; // Put last to minimize size of class + _Tp& + sum() + { + __TBB_ASSERT(_M_has_sum, "sum expected"); + return *(_Tp*)_M_sum_storage; + } + __par_trans_red_body(_Up __u, _Tp __init, _Cp __c, _Rp __r) + : _M_brick_reduce(__r), _M_u(__u), _M_combine(__c), _M_has_sum(true) + { + new (_M_sum_storage) _Tp(__init); + } + + __par_trans_red_body(__par_trans_red_body& __left, tbb::split) + : _M_brick_reduce(__left._M_brick_reduce), _M_u(__left._M_u), _M_combine(__left._M_combine), _M_has_sum(false) + { + } + + ~__par_trans_red_body() + { + // 17.6.5.12 tells us to not worry about catching exceptions from destructors. + if (_M_has_sum) + sum().~_Tp(); + } + + void + join(__par_trans_red_body& __rhs) + { + sum() = _M_combine(sum(), __rhs.sum()); + } + + void + operator()(const tbb::blocked_range<_Index>& __range) + { + _Index __i = __range.begin(); + _Index __j = __range.end(); + if (!_M_has_sum) + { + __TBB_ASSERT(__range.size() > 1, "there should be at least 2 elements"); + new (&_M_sum_storage) + _Tp(_M_combine(_M_u(__i), _M_u(__i + 1))); // The condition i+1 < j is provided by the grain size of 3 + _M_has_sum = true; + std::advance(__i, 2); + if (__i == __j) + return; + } + sum() = _M_brick_reduce(__i, __j, sum()); + } +}; + +template <class _ExecutionPolicy, class _Index, class _Up, class _Tp, class _Cp, class _Rp> +_Tp +__parallel_transform_reduce(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, + _Up __u, _Tp __init, _Cp __combine, _Rp __brick_reduce) +{ + __tbb_backend::__par_trans_red_body<_Index, _Up, _Tp, _Cp, _Rp> __body(__u, __init, __combine, __brick_reduce); + // The grain size of 3 is used in order to provide mininum 2 elements for each body + tbb::this_task_arena::isolate( + [__first, __last, &__body]() { tbb::parallel_reduce(tbb::blocked_range<_Index>(__first, __last, 3), __body); }); + return __body.sum(); +} + +//------------------------------------------------------------------------ +// parallel_scan +//------------------------------------------------------------------------ + +template <class _Index, class _Up, class _Tp, class _Cp, class _Rp, class _Sp> +class __trans_scan_body +{ + alignas(_Tp) char _M_sum_storage[sizeof(_Tp)]; // Holds generalized non-commutative sum when has_sum==true + _Rp _M_brick_reduce; // Most likely to have non-empty layout + _Up _M_u; + _Cp _M_combine; + _Sp _M_scan; + bool _M_has_sum; // Put last to minimize size of class + public: + __trans_scan_body(_Up __u, _Tp __init, _Cp __combine, _Rp __reduce, _Sp __scan) + : _M_brick_reduce(__reduce), _M_u(__u), _M_combine(__combine), _M_scan(__scan), _M_has_sum(true) + { + new (_M_sum_storage) _Tp(__init); + } + + __trans_scan_body(__trans_scan_body& __b, tbb::split) + : _M_brick_reduce(__b._M_brick_reduce), _M_u(__b._M_u), _M_combine(__b._M_combine), _M_scan(__b._M_scan), + _M_has_sum(false) + { + } + + ~__trans_scan_body() + { + // 17.6.5.12 tells us to not worry about catching exceptions from destructors. + if (_M_has_sum) + sum().~_Tp(); + } + + _Tp& + sum() const + { + __TBB_ASSERT(_M_has_sum, "sum expected"); + return *const_cast<_Tp*>(reinterpret_cast<_Tp const*>(_M_sum_storage)); + } + + void + operator()(const tbb::blocked_range<_Index>& __range, tbb::pre_scan_tag) + { + _Index __i = __range.begin(); + _Index __j = __range.end(); + if (!_M_has_sum) + { + new (&_M_sum_storage) _Tp(_M_u(__i)); + _M_has_sum = true; + ++__i; + if (__i == __j) + return; + } + sum() = _M_brick_reduce(__i, __j, sum()); + } + + void + operator()(const tbb::blocked_range<_Index>& __range, tbb::final_scan_tag) + { + sum() = _M_scan(__range.begin(), __range.end(), sum()); + } + + void + reverse_join(__trans_scan_body& __a) + { + if (_M_has_sum) + { + sum() = _M_combine(__a.sum(), sum()); + } + else + { + new (&_M_sum_storage) _Tp(__a.sum()); + _M_has_sum = true; + } + } + + void + assign(__trans_scan_body& __b) + { + sum() = __b.sum(); + } +}; + +template <typename _Index> +_Index +__split(_Index __m) +{ + _Index __k = 1; + while (2 * __k < __m) + __k *= 2; + return __k; +} + +//------------------------------------------------------------------------ +// __parallel_strict_scan +//------------------------------------------------------------------------ + +template <typename _Index, typename _Tp, typename _Rp, typename _Cp> +void +__upsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsize, _Rp __reduce, _Cp __combine) +{ + if (__m == 1) + __r[0] = __reduce(__i * __tilesize, __lastsize); + else + { + _Index __k = __split(__m); + tbb::parallel_invoke( + [=] { __tbb_backend::__upsweep(__i, __k, __tilesize, __r, __tilesize, __reduce, __combine); }, + [=] { + __tbb_backend::__upsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize, __reduce, __combine); + }); + if (__m == 2 * __k) + __r[__m - 1] = __combine(__r[__k - 1], __r[__m - 1]); + } +} + +template <typename _Index, typename _Tp, typename _Cp, typename _Sp> +void +__downsweep(_Index __i, _Index __m, _Index __tilesize, _Tp* __r, _Index __lastsize, _Tp __initial, _Cp __combine, + _Sp __scan) +{ + if (__m == 1) + __scan(__i * __tilesize, __lastsize, __initial); + else + { + const _Index __k = __split(__m); + tbb::parallel_invoke( + [=] { __tbb_backend::__downsweep(__i, __k, __tilesize, __r, __tilesize, __initial, __combine, __scan); }, + // Assumes that __combine never throws. + //TODO: Consider adding a requirement for user functors to be constant. + [=, &__combine] { + __tbb_backend::__downsweep(__i + __k, __m - __k, __tilesize, __r + __k, __lastsize, + __combine(__initial, __r[__k - 1]), __combine, __scan); + }); + } +} + +// Adapted from Intel(R) Cilk(TM) version from cilkpub. +// Let i:len denote a counted interval of length n starting at i. s denotes a generalized-sum value. +// Expected actions of the functors are: +// reduce(i,len) -> s -- return reduction value of i:len. +// combine(s1,s2) -> s -- return merged sum +// apex(s) -- do any processing necessary between reduce and scan. +// scan(i,len,initial) -- perform scan over i:len starting with initial. +// The initial range 0:n is partitioned into consecutive subranges. +// reduce and scan are each called exactly once per subrange. +// Thus callers can rely upon side effects in reduce. +// combine must not throw an exception. +// apex is called exactly once, after all calls to reduce and before all calls to scan. +// For example, it's useful for allocating a __buffer used by scan but whose size is the sum of all reduction values. +// T must have a trivial constructor and destructor. +template <class _ExecutionPolicy, typename _Index, typename _Tp, typename _Rp, typename _Cp, typename _Sp, typename _Ap> +void +__parallel_strict_scan(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __n, _Tp __initial, + _Rp __reduce, _Cp __combine, _Sp __scan, _Ap __apex) +{ + tbb::this_task_arena::isolate([=, &__combine]() { + if (__n > 1) + { + _Index __p = tbb::this_task_arena::max_concurrency(); + const _Index __slack = 4; + _Index __tilesize = (__n - 1) / (__slack * __p) + 1; + _Index __m = (__n - 1) / __tilesize; + __buffer<_Tp> __buf(__m + 1); + _Tp* __r = __buf.get(); + __tbb_backend::__upsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __reduce, + __combine); + + // When __apex is a no-op and __combine has no side effects, a good optimizer + // should be able to eliminate all code between here and __apex. + // Alternatively, provide a default value for __apex that can be + // recognized by metaprogramming that conditionlly executes the following. + size_t __k = __m + 1; + _Tp __t = __r[__k - 1]; + while ((__k &= __k - 1)) + __t = __combine(__r[__k - 1], __t); + __apex(__combine(__initial, __t)); + __tbb_backend::__downsweep(_Index(0), _Index(__m + 1), __tilesize, __r, __n - __m * __tilesize, __initial, + __combine, __scan); + return; + } + // Fewer than 2 elements in sequence, or out of memory. Handle has single block. + _Tp __sum = __initial; + if (__n) + __sum = __combine(__sum, __reduce(_Index(0), __n)); + __apex(__sum); + if (__n) + __scan(_Index(0), __n, __initial); + }); +} + +template <class _ExecutionPolicy, class _Index, class _Up, class _Tp, class _Cp, class _Rp, class _Sp> +_Tp +__parallel_transform_scan(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _Index __n, _Up __u, _Tp __init, + _Cp __combine, _Rp __brick_reduce, _Sp __scan) +{ + __trans_scan_body<_Index, _Up, _Tp, _Cp, _Rp, _Sp> __body(__u, __init, __combine, __brick_reduce, __scan); + auto __range = tbb::blocked_range<_Index>(0, __n); + tbb::this_task_arena::isolate([__range, &__body]() { tbb::parallel_scan(__range, __body); }); + return __body.sum(); +} + +//------------------------------------------------------------------------ +// parallel_stable_sort +//------------------------------------------------------------------------ + +//------------------------------------------------------------------------ +// stable_sort utilities +// +// These are used by parallel implementations but do not depend on them. +//------------------------------------------------------------------------ +#define _PSTL_MERGE_CUT_OFF 2000 + +template <typename _Func> +class __func_task; +template <typename _Func> +class __root_task; + +#if TBB_INTERFACE_VERSION <= 12000 +class __task : public tbb::task +{ + public: + template <typename _Fn> + __task* + make_continuation(_Fn&& __f) + { + return new (allocate_continuation()) __func_task<typename std::decay<_Fn>::type>(std::forward<_Fn>(__f)); + } + + template <typename _Fn> + __task* + make_child_of(__task* parent, _Fn&& __f) + { + return new (parent->allocate_child()) __func_task<typename std::decay<_Fn>::type>(std::forward<_Fn>(__f)); + } + + template <typename _Fn> + __task* + make_additional_child_of(tbb::task* parent, _Fn&& __f) + { + return new (tbb::task::allocate_additional_child_of(*parent)) + __func_task<typename std::decay<_Fn>::type>(std::forward<_Fn>(__f)); + } + + inline void + recycle_as_continuation() + { + tbb::task::recycle_as_continuation(); + } + + inline void + recycle_as_child_of(__task* parent) + { + tbb::task::recycle_as_child_of(*parent); + } + + inline void + spawn(__task* __t) + { + tbb::task::spawn(*__t); + } + + template <typename _Fn> + static inline void + spawn_root_and_wait(__root_task<_Fn>& __root) + { + tbb::task::spawn_root_and_wait(*__root._M_task); + } +}; + +template <typename _Func> +class __func_task : public __task +{ + _Func _M_func; + + tbb::task* + execute() + { + return _M_func(this); + }; + + public: + template <typename _Fn> + __func_task(_Fn&& __f) : _M_func{std::forward<_Fn>(__f)} + { + } + + _Func& + body() + { + return _M_func; + } +}; + +template <typename _Func> +class __root_task +{ + tbb::task* _M_task; + + public: + template <typename... Args> + __root_task(Args&&... args) + : _M_task{new (tbb::task::allocate_root()) __func_task<_Func>{_Func(std::forward<Args>(args)...)}} + { + } + + friend class __task; + friend class __func_task<_Func>; +}; + +#else // TBB_INTERFACE_VERSION <= 12000 +class __task : public tbb::detail::d1::task +{ + protected: + tbb::detail::d1::small_object_allocator _M_allocator{}; + tbb::detail::d1::execution_data* _M_execute_data{}; + __task* _M_parent{}; + std::atomic<int> _M_refcount{}; + bool _M_recycle{}; + + template <typename _Fn> + __task* + allocate_func_task(_Fn&& __f) + { + _LIBCPP_ASSERT_UNCATEGORIZED(_M_execute_data != nullptr, ""); + tbb::detail::d1::small_object_allocator __alloc{}; + auto __t = + __alloc.new_object<__func_task<typename std::decay<_Fn>::type>>(*_M_execute_data, std::forward<_Fn>(__f)); + __t->_M_allocator = __alloc; + return __t; + } + + public: + __task* + parent() + { + return _M_parent; + } + + void + set_ref_count(int __n) + { + _M_refcount.store(__n, std::memory_order_release); + } + + template <typename _Fn> + __task* + make_continuation(_Fn&& __f) + { + auto __t = allocate_func_task(std::forward<_Fn&&>(__f)); + __t->_M_parent = _M_parent; + _M_parent = nullptr; + return __t; + } + + template <typename _Fn> + __task* + make_child_of(__task* __parent, _Fn&& __f) + { + auto __t = allocate_func_task(std::forward<_Fn&&>(__f)); + __t->_M_parent = __parent; + return __t; + } + + template <typename _Fn> + __task* + make_additional_child_of(__task* __parent, _Fn&& __f) + { + auto __t = make_child_of(__parent, std::forward<_Fn>(__f)); + _LIBCPP_ASSERT_UNCATEGORIZED(__parent->_M_refcount.load(std::memory_order_relaxed) > 0, ""); + ++__parent->_M_refcount; + return __t; + } + + inline void + recycle_as_continuation() + { + _M_recycle = true; + } + + inline void + recycle_as_child_of(__task* parent) + { + _M_recycle = true; + _M_parent = parent; + } + + inline void + spawn(__task* __t) + { + _LIBCPP_ASSERT_UNCATEGORIZED(_M_execute_data != nullptr, ""); + tbb::detail::d1::spawn(*__t, *_M_execute_data->context); + } + + template <typename _Fn> + static inline void + spawn_root_and_wait(__root_task<_Fn>& __root) + { + tbb::detail::d1::execute_and_wait(*__root._M_func_task, __root._M_context, __root._M_wait_object, + __root._M_context); + } + + template <typename _Func> + friend class __func_task; +}; + +template <typename _Func> +class __func_task : public __task +{ + _Func _M_func; + + __task* + execute(tbb::detail::d1::execution_data& __ed) override + { + _M_execute_data = &__ed; + _M_recycle = false; + __task* __next = _M_func(this); + return finalize(__next); + }; + + __task* + cancel(tbb::detail::d1::execution_data& __ed) override + { + return finalize(nullptr); + } + + __task* + finalize(__task* __next) + { + bool __recycle = _M_recycle; + _M_recycle = false; + + if (__recycle) + { + return __next; + } + + auto __parent = _M_parent; + auto __alloc = _M_allocator; + auto __ed = _M_execute_data; + + this->~__func_task(); + + _LIBCPP_ASSERT_UNCATEGORIZED(__parent != nullptr, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__parent->_M_refcount.load(std::memory_order_relaxed) > 0, ""); + if (--__parent->_M_refcount == 0) + { + _LIBCPP_ASSERT_UNCATEGORIZED(__next == nullptr, ""); + __alloc.deallocate(this, *__ed); + return __parent; + } + + return __next; + } + + friend class __root_task<_Func>; + + public: + template <typename _Fn> + __func_task(_Fn&& __f) : _M_func(std::forward<_Fn>(__f)) + { + } + + _Func& + body() + { + return _M_func; + } +}; + +template <typename _Func> +class __root_task : public __task +{ + __task* + execute(tbb::detail::d1::execution_data& __ed) override + { + _M_wait_object.release(); + return nullptr; + }; + + __task* + cancel(tbb::detail::d1::execution_data& __ed) override + { + _M_wait_object.release(); + return nullptr; + } + + __func_task<_Func>* _M_func_task{}; + tbb::detail::d1::wait_context _M_wait_object{0}; + tbb::task_group_context _M_context{}; + + public: + template <typename... Args> + __root_task(Args&&... args) : _M_wait_object{1} + { + tbb::detail::d1::small_object_allocator __alloc{}; + _M_func_task = __alloc.new_object<__func_task<_Func>>(_Func(std::forward<Args>(args)...)); + _M_func_task->_M_allocator = __alloc; + _M_func_task->_M_parent = this; + _M_refcount.store(1, std::memory_order_relaxed); + } + + friend class __task; +}; +#endif // TBB_INTERFACE_VERSION <= 12000 + +template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Compare, typename _Cleanup, + typename _LeafMerge> +class __merge_func +{ + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _DifferenceType2; + typedef typename std::common_type<_DifferenceType1, _DifferenceType2>::type _SizeType; + typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type _ValueType; + + _RandomAccessIterator1 _M_x_beg; + _RandomAccessIterator2 _M_z_beg; + + _SizeType _M_xs, _M_xe; + _SizeType _M_ys, _M_ye; + _SizeType _M_zs; + _Compare _M_comp; + _LeafMerge _M_leaf_merge; + _SizeType _M_nsort; //number of elements to be sorted for partial_sort alforithm + + static const _SizeType __merge_cut_off = _PSTL_MERGE_CUT_OFF; + + bool _root; //means a task is merging root task + bool _x_orig; //"true" means X(or left ) subrange is in the original container; false - in the buffer + bool _y_orig; //"true" means Y(or right) subrange is in the original container; false - in the buffer + bool _split; //"true" means a merge task is a split task for parallel merging, the execution logic differs + + bool + is_partial() const + { + return _M_nsort > 0; + } + + struct __move_value + { + template <typename Iterator1, typename Iterator2> + void + operator()(Iterator1 __x, Iterator2 __z) + { + *__z = std::move(*__x); + } + }; + + struct __move_value_construct + { + template <typename Iterator1, typename Iterator2> + void + operator()(Iterator1 __x, Iterator2 __z) + { + ::new (std::addressof(*__z)) _ValueType(std::move(*__x)); + } + }; + + struct __move_range + { + template <typename Iterator1, typename Iterator2> + Iterator2 + operator()(Iterator1 __first1, Iterator1 __last1, Iterator2 __first2) + { + if (__last1 - __first1 < __merge_cut_off) + return std::move(__first1, __last1, __first2); + + auto __n = __last1 - __first1; + tbb::parallel_for(tbb::blocked_range<_SizeType>(0, __n, __merge_cut_off), + [__first1, __first2](const tbb::blocked_range<_SizeType>& __range) { + std::move(__first1 + __range.begin(), __first1 + __range.end(), + __first2 + __range.begin()); + }); + return __first2 + __n; + } + }; + + struct __move_range_construct + { + template <typename Iterator1, typename Iterator2> + Iterator2 + operator()(Iterator1 __first1, Iterator1 __last1, Iterator2 __first2) + { + if (__last1 - __first1 < __merge_cut_off) + { + for (; __first1 != __last1; ++__first1, ++__first2) + __move_value_construct()(__first1, __first2); + return __first2; + } + + auto __n = __last1 - __first1; + tbb::parallel_for(tbb::blocked_range<_SizeType>(0, __n, __merge_cut_off), + [__first1, __first2](const tbb::blocked_range<_SizeType>& __range) { + for (auto i = __range.begin(); i != __range.end(); ++i) + __move_value_construct()(__first1 + i, __first2 + i); + }); + return __first2 + __n; + } + }; + + struct __cleanup_range + { + template <typename Iterator> + void + operator()(Iterator __first, Iterator __last) + { + if (__last - __first < __merge_cut_off) + _Cleanup()(__first, __last); + else + { + auto __n = __last - __first; + tbb::parallel_for(tbb::blocked_range<_SizeType>(0, __n, __merge_cut_off), + [__first](const tbb::blocked_range<_SizeType>& __range) { + _Cleanup()(__first + __range.begin(), __first + __range.end()); + }); + } + } + }; + + public: + __merge_func(_SizeType __xs, _SizeType __xe, _SizeType __ys, _SizeType __ye, _SizeType __zs, _Compare __comp, + _Cleanup, _LeafMerge __leaf_merge, _SizeType __nsort, _RandomAccessIterator1 __x_beg, + _RandomAccessIterator2 __z_beg, bool __x_orig, bool __y_orig, bool __root) + : _M_xs(__xs), _M_xe(__xe), _M_ys(__ys), _M_ye(__ye), _M_zs(__zs), _M_x_beg(__x_beg), _M_z_beg(__z_beg), + _M_comp(__comp), _M_leaf_merge(__leaf_merge), _M_nsort(__nsort), _root(__root), + _x_orig(__x_orig), _y_orig(__y_orig), _split(false) + { + } + + bool + is_left(_SizeType __idx) const + { + return _M_xs == __idx; + } + + template <typename IndexType> + void + set_odd(IndexType __idx, bool __on_off) + { + if (is_left(__idx)) + _x_orig = __on_off; + else + _y_orig = __on_off; + } + + __task* + operator()(__task* __self); + + private: + __merge_func* + parent_merge(__task* __self) const + { + return _root ? nullptr : &static_cast<__func_task<__merge_func>*>(__self->parent())->body(); + } + bool + x_less_y() + { + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + _LIBCPP_ASSERT_UNCATEGORIZED(__nx > 0 && __ny > 0, ""); + + _LIBCPP_ASSERT_UNCATEGORIZED(_x_orig == _y_orig, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(!is_partial(), ""); + + if (_x_orig) + { + _LIBCPP_ASSERT_UNCATEGORIZED(std::is_sorted(_M_x_beg + _M_xs, _M_x_beg + _M_xe, _M_comp), ""); + _LIBCPP_ASSERT_UNCATEGORIZED(std::is_sorted(_M_x_beg + _M_ys, _M_x_beg + _M_ye, _M_comp), ""); + return !_M_comp(*(_M_x_beg + _M_ys), *(_M_x_beg + _M_xe - 1)); + } + + _LIBCPP_ASSERT_UNCATEGORIZED(std::is_sorted(_M_z_beg + _M_xs, _M_z_beg + _M_xe, _M_comp), ""); + _LIBCPP_ASSERT_UNCATEGORIZED(std::is_sorted(_M_z_beg + _M_ys, _M_z_beg + _M_ye, _M_comp), ""); + return !_M_comp(*(_M_z_beg + _M_zs + __nx), *(_M_z_beg + _M_zs + __nx - 1)); + } + void + move_x_range() + { + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + _LIBCPP_ASSERT_UNCATEGORIZED(__nx > 0 && __ny > 0, ""); + + if (_x_orig) + __move_range_construct()(_M_x_beg + _M_xs, _M_x_beg + _M_xe, _M_z_beg + _M_zs); + else + { + __move_range()(_M_z_beg + _M_zs, _M_z_beg + _M_zs + __nx, _M_x_beg + _M_xs); + __cleanup_range()(_M_z_beg + _M_zs, _M_z_beg + _M_zs + __nx); + } + + _x_orig = !_x_orig; + } + void + move_y_range() + { + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + + if (_y_orig) + __move_range_construct()(_M_x_beg + _M_ys, _M_x_beg + _M_ye, _M_z_beg + _M_zs + __nx); + else + { + __move_range()(_M_z_beg + _M_zs + __nx, _M_z_beg + _M_zs + __nx + __ny, _M_x_beg + _M_ys); + __cleanup_range()(_M_z_beg + _M_zs + __nx, _M_z_beg + _M_zs + __nx + __ny); + } + + _y_orig = !_y_orig; + } + __task* + merge_ranges(__task* __self) + { + _LIBCPP_ASSERT_UNCATEGORIZED(_x_orig == _y_orig, ""); // two merged subrange must be lie into the same buffer + + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + const auto __n = __nx + __ny; + + // need to merge {x} and {y} + if (__n > __merge_cut_off) + return split_merging(__self); + + //merge to buffer + if (_x_orig) + { + _M_leaf_merge(_M_x_beg + _M_xs, _M_x_beg + _M_xe, _M_x_beg + _M_ys, _M_x_beg + _M_ye, _M_z_beg + _M_zs, + _M_comp, __move_value_construct(), __move_value_construct(), __move_range_construct(), + __move_range_construct()); + _LIBCPP_ASSERT_UNCATEGORIZED(parent_merge(__self), ""); //not root merging task + } + //merge to "origin" + else + { + _LIBCPP_ASSERT_UNCATEGORIZED(_x_orig == _y_orig, ""); + + _LIBCPP_ASSERT_UNCATEGORIZED( + is_partial() || std::is_sorted(_M_z_beg + _M_xs, _M_z_beg + _M_xe, _M_comp), ""); + _LIBCPP_ASSERT_UNCATEGORIZED( + is_partial() || std::is_sorted(_M_z_beg + _M_ys, _M_z_beg + _M_ye, _M_comp), ""); + + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + + _M_leaf_merge(_M_z_beg + _M_xs, _M_z_beg + _M_xe, _M_z_beg + _M_ys, _M_z_beg + _M_ye, _M_x_beg + _M_zs, + _M_comp, __move_value(), __move_value(), __move_range(), __move_range()); + + __cleanup_range()(_M_z_beg + _M_xs, _M_z_beg + _M_xe); + __cleanup_range()(_M_z_beg + _M_ys, _M_z_beg + _M_ye); + } + return nullptr; + } + + __task* + process_ranges(__task* __self) + { + _LIBCPP_ASSERT_UNCATEGORIZED(_x_orig == _y_orig, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(!_split, ""); + + auto p = parent_merge(__self); + + if (!p) + { //root merging task + + //optimization, just for sort algorithm, //{x} <= {y} + if (!is_partial() && x_less_y()) //we have a solution + { + if (!_x_orig) + { //we have to move the solution to the origin + move_x_range(); //parallel moving + move_y_range(); //parallel moving + } + return nullptr; + } + //else: if we have data in the origin, + //we have to move data to the buffer for final merging into the origin. + if (_x_orig) + { + move_x_range(); //parallel moving + move_y_range(); //parallel moving + } + // need to merge {x} and {y}. + return merge_ranges(__self); + } + //else: not root merging task (parent_merge() == NULL) + //optimization, just for sort algorithm, //{x} <= {y} + if (!is_partial() && x_less_y()) + { + const auto id_range = _M_zs; + p->set_odd(id_range, _x_orig); + return nullptr; + } + //else: we have to revert "_x(y)_orig" flag of the parent merging task + const auto id_range = _M_zs; + p->set_odd(id_range, !_x_orig); + + return merge_ranges(__self); + } + + //splitting as merge task into 2 of the same level + __task* + split_merging(__task* __self) + { + _LIBCPP_ASSERT_UNCATEGORIZED(_x_orig == _y_orig, ""); + const auto __nx = (_M_xe - _M_xs); + const auto __ny = (_M_ye - _M_ys); + + _SizeType __xm{}; + _SizeType __ym{}; + if (__nx < __ny) + { + __ym = _M_ys + __ny / 2; + + if (_x_orig) + __xm = std::upper_bound(_M_x_beg + _M_xs, _M_x_beg + _M_xe, *(_M_x_beg + __ym), _M_comp) - _M_x_beg; + else + __xm = std::upper_bound(_M_z_beg + _M_xs, _M_z_beg + _M_xe, *(_M_z_beg + __ym), _M_comp) - _M_z_beg; + } + else + { + __xm = _M_xs + __nx / 2; + + if (_y_orig) + __ym = std::lower_bound(_M_x_beg + _M_ys, _M_x_beg + _M_ye, *(_M_x_beg + __xm), _M_comp) - _M_x_beg; + else + __ym = std::lower_bound(_M_z_beg + _M_ys, _M_z_beg + _M_ye, *(_M_z_beg + __xm), _M_comp) - _M_z_beg; + } + + auto __zm = _M_zs + ((__xm - _M_xs) + (__ym - _M_ys)); + __merge_func __right_func(__xm, _M_xe, __ym, _M_ye, __zm, _M_comp, _Cleanup(), _M_leaf_merge, _M_nsort, + _M_x_beg, _M_z_beg, _x_orig, _y_orig, _root); + __right_func._split = true; + auto __merge_task = __self->make_additional_child_of(__self->parent(), std::move(__right_func)); + __self->spawn(__merge_task); + __self->recycle_as_continuation(); + + _M_xe = __xm; + _M_ye = __ym; + _split = true; + + return __self; + } +}; + +template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename __M_Compare, typename _Cleanup, + typename _LeafMerge> +__task* +__merge_func<_RandomAccessIterator1, _RandomAccessIterator2, __M_Compare, _Cleanup, _LeafMerge>:: +operator()(__task* __self) +{ + //a. split merge task into 2 of the same level; the special logic, + //without processing(process_ranges) adjacent sub-ranges x and y + if (_split) + return merge_ranges(__self); + + //b. General merging of adjacent sub-ranges x and y (with optimization in case of {x} <= {y} ) + + //1. x and y are in the even buffer + //2. x and y are in the odd buffer + if (_x_orig == _y_orig) + return process_ranges(__self); + + //3. x is in even buffer, y is in the odd buffer + //4. x is in odd buffer, y is in the even buffer + if (!parent_merge(__self)) + { //root merge task + if (_x_orig) + move_x_range(); + else + move_y_range(); + } + else + { + const _SizeType __nx = (_M_xe - _M_xs); + const _SizeType __ny = (_M_ye - _M_ys); + _LIBCPP_ASSERT_UNCATEGORIZED(__nx > 0, ""); + _LIBCPP_ASSERT_UNCATEGORIZED(__nx > 0, ""); + + if (__nx < __ny) + move_x_range(); + else + move_y_range(); + } + + return process_ranges(__self); +} + +template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Compare, typename _LeafSort> +class __stable_sort_func +{ + public: + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _DifferenceType2; + typedef typename std::common_type<_DifferenceType1, _DifferenceType2>::type _SizeType; + + private: + _RandomAccessIterator1 _M_xs, _M_xe, _M_x_beg; + _RandomAccessIterator2 _M_zs, _M_z_beg; + _Compare _M_comp; + _LeafSort _M_leaf_sort; + bool _M_root; + _SizeType _M_nsort; //zero or number of elements to be sorted for partial_sort alforithm + + public: + __stable_sort_func(_RandomAccessIterator1 __xs, _RandomAccessIterator1 __xe, _RandomAccessIterator2 __zs, + bool __root, _Compare __comp, _LeafSort __leaf_sort, _SizeType __nsort, + _RandomAccessIterator1 __x_beg, _RandomAccessIterator2 __z_beg) + : _M_xs(__xs), _M_xe(__xe), _M_x_beg(__x_beg), _M_zs(__zs), _M_z_beg(__z_beg), _M_comp(__comp), + _M_leaf_sort(__leaf_sort), _M_root(__root), _M_nsort(__nsort) + { + } + + __task* + operator()(__task* __self); +}; + +#define _PSTL_STABLE_SORT_CUT_OFF 500 + +template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Compare, typename _LeafSort> +__task* +__stable_sort_func<_RandomAccessIterator1, _RandomAccessIterator2, _Compare, _LeafSort>::operator()(__task* __self) +{ + typedef __merge_func<_RandomAccessIterator1, _RandomAccessIterator2, _Compare, __utils::__serial_destroy, + __utils::__serial_move_merge> + _MergeTaskType; + + const _SizeType __n = _M_xe - _M_xs; + const _SizeType __nmerge = _M_nsort > 0 ? _M_nsort : __n; + const _SizeType __sort_cut_off = _PSTL_STABLE_SORT_CUT_OFF; + if (__n <= __sort_cut_off) + { + _M_leaf_sort(_M_xs, _M_xe, _M_comp); + _LIBCPP_ASSERT_UNCATEGORIZED(!_M_root, ""); + return nullptr; + } + + const _RandomAccessIterator1 __xm = _M_xs + __n / 2; + const _RandomAccessIterator2 __zm = _M_zs + (__xm - _M_xs); + const _RandomAccessIterator2 __ze = _M_zs + __n; + _MergeTaskType __m(_MergeTaskType(_M_xs - _M_x_beg, __xm - _M_x_beg, __xm - _M_x_beg, _M_xe - _M_x_beg, + _M_zs - _M_z_beg, _M_comp, __utils::__serial_destroy(), + __utils::__serial_move_merge(__nmerge), _M_nsort, _M_x_beg, _M_z_beg, + /*x_orig*/ true, /*y_orig*/ true, /*root*/ _M_root)); + auto __parent = __self->make_continuation(std::move(__m)); + __parent->set_ref_count(2); + auto __right = __self->make_child_of( + __parent, __stable_sort_func(__xm, _M_xe, __zm, false, _M_comp, _M_leaf_sort, _M_nsort, _M_x_beg, _M_z_beg)); + __self->spawn(__right); + __self->recycle_as_child_of(__parent); + _M_root = false; + _M_xe = __xm; + + return __self; +} + +template <class _ExecutionPolicy, typename _RandomAccessIterator, typename _Compare, typename _LeafSort> +void +__parallel_stable_sort(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __xs, + _RandomAccessIterator __xe, _Compare __comp, _LeafSort __leaf_sort, std::size_t __nsort = 0) +{ + tbb::this_task_arena::isolate([=, &__nsort]() { + //sorting based on task tree and parallel merge + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _ValueType; + typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType; + const _DifferenceType __n = __xe - __xs; + if (__nsort == __n) + __nsort = 0; // 'partial_sort' becames 'sort' + + const _DifferenceType __sort_cut_off = _PSTL_STABLE_SORT_CUT_OFF; + if (__n > __sort_cut_off) + { + __buffer<_ValueType> __buf(__n); + __root_task<__stable_sort_func<_RandomAccessIterator, _ValueType*, _Compare, _LeafSort>> __root{ + __xs, __xe, __buf.get(), true, __comp, __leaf_sort, __nsort, __xs, __buf.get()}; + __task::spawn_root_and_wait(__root); + return; + } + //serial sort + __leaf_sort(__xs, __xe, __comp); + }); +} + +//------------------------------------------------------------------------ +// parallel_merge +//------------------------------------------------------------------------ +template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _RandomAccessIterator3, + typename _Compare, typename _LeafMerge> +class __merge_func_static +{ + _RandomAccessIterator1 _M_xs, _M_xe; + _RandomAccessIterator2 _M_ys, _M_ye; + _RandomAccessIterator3 _M_zs; + _Compare _M_comp; + _LeafMerge _M_leaf_merge; + + public: + __merge_func_static(_RandomAccessIterator1 __xs, _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, + _RandomAccessIterator2 __ye, _RandomAccessIterator3 __zs, _Compare __comp, + _LeafMerge __leaf_merge) + : _M_xs(__xs), _M_xe(__xe), _M_ys(__ys), _M_ye(__ye), _M_zs(__zs), _M_comp(__comp), _M_leaf_merge(__leaf_merge) + { + } + + __task* + operator()(__task* __self); +}; + +//TODO: consider usage of parallel_for with a custom blocked_range +template <typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _RandomAccessIterator3, + typename __M_Compare, typename _LeafMerge> +__task* +__merge_func_static<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3, __M_Compare, _LeafMerge>:: +operator()(__task* __self) +{ + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _DifferenceType2; + typedef typename std::common_type<_DifferenceType1, _DifferenceType2>::type _SizeType; + const _SizeType __n = (_M_xe - _M_xs) + (_M_ye - _M_ys); + const _SizeType __merge_cut_off = _PSTL_MERGE_CUT_OFF; + if (__n <= __merge_cut_off) + { + _M_leaf_merge(_M_xs, _M_xe, _M_ys, _M_ye, _M_zs, _M_comp); + return nullptr; + } + + _RandomAccessIterator1 __xm; + _RandomAccessIterator2 __ym; + if (_M_xe - _M_xs < _M_ye - _M_ys) + { + __ym = _M_ys + (_M_ye - _M_ys) / 2; + __xm = std::upper_bound(_M_xs, _M_xe, *__ym, _M_comp); + } + else + { + __xm = _M_xs + (_M_xe - _M_xs) / 2; + __ym = std::lower_bound(_M_ys, _M_ye, *__xm, _M_comp); + } + const _RandomAccessIterator3 __zm = _M_zs + ((__xm - _M_xs) + (__ym - _M_ys)); + auto __right = __self->make_additional_child_of( + __self->parent(), __merge_func_static(__xm, _M_xe, __ym, _M_ye, __zm, _M_comp, _M_leaf_merge)); + __self->spawn(__right); + __self->recycle_as_continuation(); + _M_xe = __xm; + _M_ye = __ym; + + return __self; +} + +template <class _ExecutionPolicy, typename _RandomAccessIterator1, typename _RandomAccessIterator2, + typename _RandomAccessIterator3, typename _Compare, typename _LeafMerge> +void +__parallel_merge(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator1 __xs, + _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, _RandomAccessIterator2 __ye, + _RandomAccessIterator3 __zs, _Compare __comp, _LeafMerge __leaf_merge) +{ + typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType1; + typedef typename std::iterator_traits<_RandomAccessIterator2>::difference_type _DifferenceType2; + typedef typename std::common_type<_DifferenceType1, _DifferenceType2>::type _SizeType; + const _SizeType __n = (__xe - __xs) + (__ye - __ys); + const _SizeType __merge_cut_off = _PSTL_MERGE_CUT_OFF; + if (__n <= __merge_cut_off) + { + // Fall back on serial merge + __leaf_merge(__xs, __xe, __ys, __ye, __zs, __comp); + } + else + { + tbb::this_task_arena::isolate([=]() { + typedef __merge_func_static<_RandomAccessIterator1, _RandomAccessIterator2, _RandomAccessIterator3, + _Compare, _LeafMerge> + _TaskType; + __root_task<_TaskType> __root{__xs, __xe, __ys, __ye, __zs, __comp, __leaf_merge}; + __task::spawn_root_and_wait(__root); + }); + } +} + +//------------------------------------------------------------------------ +// parallel_invoke +//------------------------------------------------------------------------ +template <class _ExecutionPolicy, typename _F1, typename _F2> +void +__parallel_invoke(__pstl::__internal::__tbb_backend_tag, _ExecutionPolicy&&, _F1&& __f1, _F2&& __f2) +{ + //TODO: a version of tbb::this_task_arena::isolate with variadic arguments pack should be added in the future + tbb::this_task_arena::isolate([&]() { tbb::parallel_invoke(std::forward<_F1>(__f1), std::forward<_F2>(__f2)); }); +} + +} // namespace __tbb_backend +} // namespace __pstl + +#endif /* _PSTL_PARALLEL_BACKEND_TBB_H */ diff --git a/libcxx/include/__pstl/internal/parallel_backend_utils.h b/libcxx/include/__pstl/internal/parallel_backend_utils.h new file mode 100644 index 000000000000..8adcdb71f867 --- /dev/null +++ b/libcxx/include/__pstl/internal/parallel_backend_utils.h @@ -0,0 +1,260 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_PARALLEL_BACKEND_UTILS_H +#define _PSTL_PARALLEL_BACKEND_UTILS_H + +#include <__assert> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> + +#include "utils.h" + +namespace __pstl +{ + +namespace __utils +{ + +//! Destroy sequence [xs,xe) +struct __serial_destroy +{ + template <typename _RandomAccessIterator> + void + operator()(_RandomAccessIterator __zs, _RandomAccessIterator __ze) + { + typedef typename std::iterator_traits<_RandomAccessIterator>::value_type _ValueType; + while (__zs != __ze) + { + --__ze; + (*__ze).~_ValueType(); + } + } +}; + +//! Merge sequences [__xs,__xe) and [__ys,__ye) to output sequence [__zs,(__xe-__xs)+(__ye-__ys)), using std::move +struct __serial_move_merge +{ + const std::size_t _M_nmerge; + + explicit __serial_move_merge(std::size_t __nmerge) : _M_nmerge(__nmerge) {} + template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _RandomAccessIterator3, class _Compare, + class _MoveValueX, class _MoveValueY, class _MoveSequenceX, class _MoveSequenceY> + void + operator()(_RandomAccessIterator1 __xs, _RandomAccessIterator1 __xe, _RandomAccessIterator2 __ys, + _RandomAccessIterator2 __ye, _RandomAccessIterator3 __zs, _Compare __comp, _MoveValueX __move_value_x, + _MoveValueY __move_value_y, _MoveSequenceX __move_sequence_x, _MoveSequenceY __move_sequence_y) + { + constexpr bool __same_move_val = std::is_same<_MoveValueX, _MoveValueY>::value; + constexpr bool __same_move_seq = std::is_same<_MoveSequenceX, _MoveSequenceY>::value; + + auto __n = _M_nmerge; + _LIBCPP_ASSERT_UNCATEGORIZED(__n > 0, ""); + + auto __nx = __xe - __xs; + //auto __ny = __ye - __ys; + _RandomAccessIterator3 __zs_beg = __zs; + + if (__xs != __xe) + { + if (__ys != __ye) + { + for (;;) + { + if (__comp(*__ys, *__xs)) + { + const auto __i = __zs - __zs_beg; + if (__i < __nx) + __move_value_x(__ys, __zs); + else + __move_value_y(__ys, __zs); + ++__zs, --__n; + if (++__ys == __ye) + { + break; + } + else if (__n == 0) + { + const auto __j = __zs - __zs_beg; + if (__same_move_seq || __j < __nx) + __zs = __move_sequence_x(__ys, __ye, __zs); + else + __zs = __move_sequence_y(__ys, __ye, __zs); + break; + } + } + else + { + const auto __i = __zs - __zs_beg; + if (__same_move_val || __i < __nx) + __move_value_x(__xs, __zs); + else + __move_value_y(__xs, __zs); + ++__zs, --__n; + if (++__xs == __xe) + { + const auto __j = __zs - __zs_beg; + if (__same_move_seq || __j < __nx) + __move_sequence_x(__ys, __ye, __zs); + else + __move_sequence_y(__ys, __ye, __zs); + return; + } + else if (__n == 0) + { + const auto __j = __zs - __zs_beg; + if (__same_move_seq || __j < __nx) + { + __zs = __move_sequence_x(__xs, __xe, __zs); + __move_sequence_x(__ys, __ye, __zs); + } + else + { + __zs = __move_sequence_y(__xs, __xe, __zs); + __move_sequence_y(__ys, __ye, __zs); + } + return; + } + } + } + } + __ys = __xs; + __ye = __xe; + } + const auto __i = __zs - __zs_beg; + if (__same_move_seq || __i < __nx) + __move_sequence_x(__ys, __ye, __zs); + else + __move_sequence_y(__ys, __ye, __zs); + } +}; + +template <typename _ForwardIterator1, typename _ForwardIterator2, typename _OutputIterator, typename _Compare, + typename _CopyConstructRange> +_OutputIterator +__set_union_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, + _CopyConstructRange __cc_range) +{ + using _Tp = typename std::iterator_traits<_OutputIterator>::value_type; + + for (; __first1 != __last1; ++__result) + { + if (__first2 == __last2) + return __cc_range(__first1, __last1, __result); + if (__comp(*__first2, *__first1)) + { + ::new (std::addressof(*__result)) _Tp(*__first2); + ++__first2; + } + else + { + ::new (std::addressof(*__result)) _Tp(*__first1); + if (!__comp(*__first1, *__first2)) + ++__first2; + ++__first1; + } + } + return __cc_range(__first2, __last2, __result); +} + +template <typename _ForwardIterator1, typename _ForwardIterator2, typename _OutputIterator, typename _Compare> +_OutputIterator +__set_intersection_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp) +{ + using _Tp = typename std::iterator_traits<_OutputIterator>::value_type; + + for (; __first1 != __last1 && __first2 != __last2;) + { + if (__comp(*__first1, *__first2)) + ++__first1; + else + { + if (!__comp(*__first2, *__first1)) + { + ::new (std::addressof(*__result)) _Tp(*__first1); + ++__result; + ++__first1; + } + ++__first2; + } + } + return __result; +} + +template <typename _ForwardIterator1, typename _ForwardIterator2, typename _OutputIterator, typename _Compare, + typename _CopyConstructRange> +_OutputIterator +__set_difference_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, + _CopyConstructRange __cc_range) +{ + using _Tp = typename std::iterator_traits<_OutputIterator>::value_type; + + for (; __first1 != __last1;) + { + if (__first2 == __last2) + return __cc_range(__first1, __last1, __result); + + if (__comp(*__first1, *__first2)) + { + ::new (std::addressof(*__result)) _Tp(*__first1); + ++__result; + ++__first1; + } + else + { + if (!__comp(*__first2, *__first1)) + ++__first1; + ++__first2; + } + } + return __result; +} +template <typename _ForwardIterator1, typename _ForwardIterator2, typename _OutputIterator, typename _Compare, + typename _CopyConstructRange> +_OutputIterator +__set_symmetric_difference_construct(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _OutputIterator __result, _Compare __comp, + _CopyConstructRange __cc_range) +{ + using _Tp = typename std::iterator_traits<_OutputIterator>::value_type; + + for (; __first1 != __last1;) + { + if (__first2 == __last2) + return __cc_range(__first1, __last1, __result); + + if (__comp(*__first1, *__first2)) + { + ::new (std::addressof(*__result)) _Tp(*__first1); + ++__result; + ++__first1; + } + else + { + if (__comp(*__first2, *__first1)) + { + ::new (std::addressof(*__result)) _Tp(*__first2); + ++__result; + } + else + ++__first1; + ++__first2; + } + } + return __cc_range(__first2, __last2, __result); +} + +} // namespace __utils +} // namespace __pstl + +#endif /* _PSTL_PARALLEL_BACKEND_UTILS_H */ diff --git a/libcxx/include/__pstl/internal/unseq_backend_simd.h b/libcxx/include/__pstl/internal/unseq_backend_simd.h new file mode 100644 index 000000000000..c64c178471ce --- /dev/null +++ b/libcxx/include/__pstl/internal/unseq_backend_simd.h @@ -0,0 +1,697 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_UNSEQ_BACKEND_SIMD_H +#define _PSTL_UNSEQ_BACKEND_SIMD_H + +#include <__config> +#include <__functional/operations.h> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_same.h> +#include <__utility/move.h> +#include <__utility/pair.h> +#include <cstddef> +#include <cstdint> + +#include <__pstl/internal/utils.h> + +// This header defines the minimum set of vector routines required +// to support parallel STL. + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +namespace __pstl +{ +namespace __unseq_backend +{ + +// Expect vector width up to 64 (or 512 bit) +const std::size_t __lane_size = 64; + +template <class _Iterator, class _DifferenceType, class _Function> +_LIBCPP_HIDE_FROM_ABI _Iterator +__simd_walk_1(_Iterator __first, _DifferenceType __n, _Function __f) noexcept +{ + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first[__i]); + + return __first + __n; +} + +template <class _Iterator1, class _DifferenceType, class _Iterator2, class _Function> +_LIBCPP_HIDE_FROM_ABI _Iterator2 +__simd_walk_2(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Function __f) noexcept +{ + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first1[__i], __first2[__i]); + return __first2 + __n; +} + +template <class _Iterator1, class _DifferenceType, class _Iterator2, class _Iterator3, class _Function> +_LIBCPP_HIDE_FROM_ABI _Iterator3 +__simd_walk_3(_Iterator1 __first1, _DifferenceType __n, _Iterator2 __first2, _Iterator3 __first3, + _Function __f) noexcept +{ + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __f(__first1[__i], __first2[__i], __first3[__i]); + return __first3 + __n; +} + +// TODO: check whether __simd_first() can be used here +template <class _Index, class _DifferenceType, class _Pred> +_LIBCPP_HIDE_FROM_ABI bool +__simd_or(_Index __first, _DifferenceType __n, _Pred __pred) noexcept +{ + _DifferenceType __block_size = 4 < __n ? 4 : __n; + const _Index __last = __first + __n; + while (__last != __first) + { + int32_t __flag = 1; + _PSTL_PRAGMA_SIMD_REDUCTION(& : __flag) + for (_DifferenceType __i = 0; __i < __block_size; ++__i) + if (__pred(*(__first + __i))) + __flag = 0; + if (!__flag) + return true; + + __first += __block_size; + if (__last - __first >= __block_size << 1) + { + // Double the block _Size. Any unnecessary iterations can be amortized against work done so far. + __block_size <<= 1; + } + else + { + __block_size = __last - __first; + } + } + return false; +} + +template <class _Index1, class _DifferenceType, class _Index2, class _Pred> +_LIBCPP_HIDE_FROM_ABI std::pair<_Index1, _Index2> +__simd_first(_Index1 __first1, _DifferenceType __n, _Index2 __first2, _Pred __pred) noexcept +{ + const _Index1 __last1 = __first1 + __n; + const _Index2 __last2 = __first2 + __n; + // Experiments show good block sizes like this + const _DifferenceType __block_size = 8; + alignas(__lane_size) _DifferenceType __lane[__block_size] = {0}; + while (__last1 - __first1 >= __block_size) + { + _DifferenceType __found = 0; + _DifferenceType __i; + _PSTL_PRAGMA_SIMD_REDUCTION(| + : __found) for (__i = 0; __i < __block_size; ++__i) + { + const _DifferenceType __t = __pred(__first1[__i], __first2[__i]); + __lane[__i] = __t; + __found |= __t; + } + if (__found) + { + _DifferenceType __i2; + // This will vectorize + for (__i2 = 0; __i2 < __block_size; ++__i2) + { + if (__lane[__i2]) + break; + } + return std::make_pair(__first1 + __i2, __first2 + __i2); + } + __first1 += __block_size; + __first2 += __block_size; + } + + //Keep remainder scalar + for (; __last1 != __first1; ++__first1, ++__first2) + if (__pred(*(__first1), *(__first2))) + return std::make_pair(__first1, __first2); + + return std::make_pair(__last1, __last2); +} + +template <class _Index, class _DifferenceType, class _Pred> +_LIBCPP_HIDE_FROM_ABI _DifferenceType +__simd_count(_Index __index, _DifferenceType __n, _Pred __pred) noexcept +{ + _DifferenceType __count = 0; + _PSTL_PRAGMA_SIMD_REDUCTION(+ : __count) + for (_DifferenceType __i = 0; __i < __n; ++__i) + if (__pred(*(__index + __i))) + ++__count; + + return __count; +} + +template <class _InputIterator, class _DifferenceType, class _OutputIterator, class _BinaryPredicate> +_LIBCPP_HIDE_FROM_ABI _OutputIterator +__simd_unique_copy(_InputIterator __first, _DifferenceType __n, _OutputIterator __result, + _BinaryPredicate __pred) noexcept +{ + if (__n == 0) + return __result; + + _DifferenceType __cnt = 1; + __result[0] = __first[0]; + + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 1; __i < __n; ++__i) + { + if (!__pred(__first[__i], __first[__i - 1])) + { + __result[__cnt] = __first[__i]; + ++__cnt; + } + } + return __result + __cnt; +} + +template <class _InputIterator, class _DifferenceType, class _OutputIterator, class _Assigner> +_LIBCPP_HIDE_FROM_ABI _OutputIterator +__simd_assign(_InputIterator __first, _DifferenceType __n, _OutputIterator __result, _Assigner __assigner) noexcept +{ + _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + __assigner(__first + __i, __result + __i); + return __result + __n; +} + +template <class _InputIterator, class _DifferenceType, class _OutputIterator, class _UnaryPredicate> +_LIBCPP_HIDE_FROM_ABI _OutputIterator +__simd_copy_if(_InputIterator __first, _DifferenceType __n, _OutputIterator __result, _UnaryPredicate __pred) noexcept +{ + _DifferenceType __cnt = 0; + + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + if (__pred(__first[__i])) + { + __result[__cnt] = __first[__i]; + ++__cnt; + } + } + return __result + __cnt; +} + +template <class _InputIterator, class _DifferenceType, class _BinaryPredicate> +_LIBCPP_HIDE_FROM_ABI _DifferenceType +__simd_calc_mask_2(_InputIterator __first, _DifferenceType __n, bool* __mask, _BinaryPredicate __pred) noexcept +{ + _DifferenceType __count = 0; + + _PSTL_PRAGMA_SIMD_REDUCTION(+ : __count) + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + __mask[__i] = !__pred(__first[__i], __first[__i - 1]); + __count += __mask[__i]; + } + return __count; +} + +template <class _InputIterator, class _DifferenceType, class _UnaryPredicate> +_LIBCPP_HIDE_FROM_ABI _DifferenceType +__simd_calc_mask_1(_InputIterator __first, _DifferenceType __n, bool* __mask, _UnaryPredicate __pred) noexcept +{ + _DifferenceType __count = 0; + + _PSTL_PRAGMA_SIMD_REDUCTION(+ : __count) + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + __mask[__i] = __pred(__first[__i]); + __count += __mask[__i]; + } + return __count; +} + +template <class _InputIterator, class _DifferenceType, class _OutputIterator, class _Assigner> +_LIBCPP_HIDE_FROM_ABI void +__simd_copy_by_mask(_InputIterator __first, _DifferenceType __n, _OutputIterator __result, bool* __mask, + _Assigner __assigner) noexcept +{ + _DifferenceType __cnt = 0; + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + if (__mask[__i]) + { + { + __assigner(__first + __i, __result + __cnt); + ++__cnt; + } + } + } +} + +template <class _InputIterator, class _DifferenceType, class _OutputIterator1, class _OutputIterator2> +_LIBCPP_HIDE_FROM_ABI void +__simd_partition_by_mask(_InputIterator __first, _DifferenceType __n, _OutputIterator1 __out_true, + _OutputIterator2 __out_false, bool* __mask) noexcept +{ + _DifferenceType __cnt_true = 0, __cnt_false = 0; + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + if (__mask[__i]) + { + __out_true[__cnt_true] = __first[__i]; + ++__cnt_true; + } + else + { + __out_false[__cnt_false] = __first[__i]; + ++__cnt_false; + } + } +} + +template <class _Index, class _DifferenceType, class _Generator> +_LIBCPP_HIDE_FROM_ABI _Index +__simd_generate_n(_Index __first, _DifferenceType __size, _Generator __g) noexcept +{ + _PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __size; ++__i) + __first[__i] = __g(); + return __first + __size; +} + +template <class _Index, class _BinaryPredicate> +_LIBCPP_HIDE_FROM_ABI _Index +__simd_adjacent_find(_Index __first, _Index __last, _BinaryPredicate __pred, bool __or_semantic) noexcept +{ + if (__last - __first < 2) + return __last; + + typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType; + _DifferenceType __i = 0; + + // Experiments show good block sizes like this + //TODO: to consider tuning block_size for various data types + const _DifferenceType __block_size = 8; + alignas(__lane_size) _DifferenceType __lane[__block_size] = {0}; + while (__last - __first >= __block_size) + { + _DifferenceType __found = 0; + _PSTL_PRAGMA_SIMD_REDUCTION(| + : __found) for (__i = 0; __i < __block_size - 1; ++__i) + { + //TODO: to improve SIMD vectorization + const _DifferenceType __t = __pred(*(__first + __i), *(__first + __i + 1)); + __lane[__i] = __t; + __found |= __t; + } + + //Process a pair of elements on a boundary of a data block + if (__first + __block_size < __last && __pred(*(__first + __i), *(__first + __i + 1))) + __lane[__i] = __found = 1; + + if (__found) + { + if (__or_semantic) + return __first; + + // This will vectorize + for (__i = 0; __i < __block_size; ++__i) + if (__lane[__i]) + break; + return __first + __i; //As far as found is true a __result (__lane[__i] is true) is guaranteed + } + __first += __block_size; + } + //Process the rest elements + for (; __last - __first > 1; ++__first) + if (__pred(*__first, *(__first + 1))) + return __first; + + return __last; +} + +// It was created to reduce the code inside std::enable_if +template <typename _Tp, typename _BinaryOperation> +using is_arithmetic_plus = std::integral_constant<bool, std::is_arithmetic<_Tp>::value && + std::is_same<_BinaryOperation, std::plus<_Tp>>::value>; + +// Exclusive scan for "+" and arithmetic types +template <class _InputIterator, class _Size, class _OutputIterator, class _UnaryOperation, class _Tp, + class _BinaryOperation> +_LIBCPP_HIDE_FROM_ABI +typename std::enable_if<is_arithmetic_plus<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type +__simd_scan(_InputIterator __first, _Size __n, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, + _BinaryOperation, /*Inclusive*/ std::false_type) +{ + _PSTL_PRAGMA_SIMD_SCAN(+ : __init) + for (_Size __i = 0; __i < __n; ++__i) + { + __result[__i] = __init; + _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(__init) + __init += __unary_op(__first[__i]); + } + return std::make_pair(__result + __n, __init); +} + +// As soon as we cannot call __binary_op in "combiner" we create a wrapper over _Tp to encapsulate __binary_op +template <typename _Tp, typename _BinaryOp> +struct _Combiner +{ + _Tp __value_; + _BinaryOp* __bin_op_; // Here is a pointer to function because of default ctor + + _LIBCPP_HIDE_FROM_ABI _Combiner() : __value_{}, __bin_op_(nullptr) {} + _LIBCPP_HIDE_FROM_ABI + _Combiner(const _Tp& __value, const _BinaryOp* __bin_op) + : __value_(__value), __bin_op_(const_cast<_BinaryOp*>(__bin_op)) {} + _LIBCPP_HIDE_FROM_ABI _Combiner(const _Combiner& __obj) : __value_{}, __bin_op_(__obj.__bin_op) {} + + _LIBCPP_HIDE_FROM_ABI void + operator()(const _Combiner& __obj) + { + __value_ = (*__bin_op_)(__value_, __obj.__value_); + } +}; + +// Exclusive scan for other binary operations and types +template <class _InputIterator, class _Size, class _OutputIterator, class _UnaryOperation, class _Tp, + class _BinaryOperation> +_LIBCPP_HIDE_FROM_ABI +typename std::enable_if<!is_arithmetic_plus<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type +__simd_scan(_InputIterator __first, _Size __n, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, + _BinaryOperation __binary_op, /*Inclusive*/ std::false_type) +{ + typedef _Combiner<_Tp, _BinaryOperation> _CombinerType; + _CombinerType __combined_init{__init, &__binary_op}; + + _PSTL_PRAGMA_DECLARE_REDUCTION(__bin_op, _CombinerType) + _PSTL_PRAGMA_SIMD_SCAN(__bin_op : __combined_init) + for (_Size __i = 0; __i < __n; ++__i) + { + __result[__i] = __combined_init.__value_; + _PSTL_PRAGMA_SIMD_EXCLUSIVE_SCAN(__combined_init) + __combined_init.__value_ = __binary_op(__combined_init.__value_, __unary_op(__first[__i])); + } + return std::make_pair(__result + __n, __combined_init.__value_); +} + +// Inclusive scan for "+" and arithmetic types +template <class _InputIterator, class _Size, class _OutputIterator, class _UnaryOperation, class _Tp, + class _BinaryOperation> +_LIBCPP_HIDE_FROM_ABI +typename std::enable_if<is_arithmetic_plus<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type +__simd_scan(_InputIterator __first, _Size __n, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, + _BinaryOperation, /*Inclusive*/ std::true_type) +{ + _PSTL_PRAGMA_SIMD_SCAN(+ : __init) + for (_Size __i = 0; __i < __n; ++__i) + { + __init += __unary_op(__first[__i]); + _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(__init) + __result[__i] = __init; + } + return std::make_pair(__result + __n, __init); +} + +// Inclusive scan for other binary operations and types +template <class _InputIterator, class _Size, class _OutputIterator, class _UnaryOperation, class _Tp, + class _BinaryOperation> +_LIBCPP_HIDE_FROM_ABI +typename std::enable_if<!is_arithmetic_plus<_Tp, _BinaryOperation>::value, std::pair<_OutputIterator, _Tp>>::type +__simd_scan(_InputIterator __first, _Size __n, _OutputIterator __result, _UnaryOperation __unary_op, _Tp __init, + _BinaryOperation __binary_op, std::true_type) +{ + typedef _Combiner<_Tp, _BinaryOperation> _CombinerType; + _CombinerType __combined_init{__init, &__binary_op}; + + _PSTL_PRAGMA_DECLARE_REDUCTION(__bin_op, _CombinerType) + _PSTL_PRAGMA_SIMD_SCAN(__bin_op : __combined_init) + for (_Size __i = 0; __i < __n; ++__i) + { + __combined_init.__value_ = __binary_op(__combined_init.__value_, __unary_op(__first[__i])); + _PSTL_PRAGMA_SIMD_INCLUSIVE_SCAN(__combined_init) + __result[__i] = __combined_init.__value_; + } + return std::make_pair(__result + __n, __combined_init.__value_); +} + +// [restriction] - std::iterator_traits<_ForwardIterator>::value_type should be DefaultConstructible. +// complexity [violation] - We will have at most (__n-1 + number_of_lanes) comparisons instead of at most __n-1. +template <typename _ForwardIterator, typename _Size, typename _Compare> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +__simd_min_element(_ForwardIterator __first, _Size __n, _Compare __comp) noexcept +{ + if (__n == 0) + { + return __first; + } + + typedef typename std::iterator_traits<_ForwardIterator>::value_type _ValueType; + struct _ComplexType + { + _ValueType __min_val_; + _Size __min_ind_; + _Compare* __min_comp_; + + _LIBCPP_HIDE_FROM_ABI _ComplexType() : __min_val_{}, __min_ind_{}, __min_comp_(nullptr) {} + _LIBCPP_HIDE_FROM_ABI _ComplexType(const _ValueType& __val, const _Compare* __comp) + : __min_val_(__val), __min_ind_(0), __min_comp_(const_cast<_Compare*>(__comp)) + { + } + _LIBCPP_HIDE_FROM_ABI _ComplexType(const _ComplexType& __obj) + : __min_val_(__obj.__min_val_), __min_ind_(__obj.__min_ind_), __min_comp_(__obj.__min_comp_) + { + } + + _PSTL_PRAGMA_DECLARE_SIMD + _LIBCPP_HIDE_FROM_ABI void + operator()(const _ComplexType& __obj) + { + if (!(*__min_comp_)(__min_val_, __obj.__min_val_) && + ((*__min_comp_)(__obj.__min_val_, __min_val_) || __obj.__min_ind_ - __min_ind_ < 0)) + { + __min_val_ = __obj.__min_val_; + __min_ind_ = __obj.__min_ind_; + } + } + }; + + _ComplexType __init{*__first, &__comp}; + + _PSTL_PRAGMA_DECLARE_REDUCTION(__min_func, _ComplexType) + + _PSTL_PRAGMA_SIMD_REDUCTION(__min_func : __init) + for (_Size __i = 1; __i < __n; ++__i) + { + const _ValueType __min_val = __init.__min_val_; + const _ValueType __current = __first[__i]; + if (__comp(__current, __min_val)) + { + __init.__min_val_ = __current; + __init.__min_ind_ = __i; + } + } + return __first + __init.__min_ind_; +} + +// [restriction] - std::iterator_traits<_ForwardIterator>::value_type should be DefaultConstructible. +// complexity [violation] - We will have at most (2*(__n-1) + 4*number_of_lanes) comparisons instead of at most [1.5*(__n-1)]. +template <typename _ForwardIterator, typename _Size, typename _Compare> +_LIBCPP_HIDE_FROM_ABI std::pair<_ForwardIterator, _ForwardIterator> +__simd_minmax_element(_ForwardIterator __first, _Size __n, _Compare __comp) noexcept +{ + if (__n == 0) + { + return std::make_pair(__first, __first); + } + typedef typename std::iterator_traits<_ForwardIterator>::value_type _ValueType; + + struct _ComplexType + { + _ValueType __min_val_; + _ValueType __max_val_; + _Size __min_ind_; + _Size __max_ind_; + _Compare* __minmax_comp; + + _LIBCPP_HIDE_FROM_ABI _ComplexType() + : __min_val_{}, __max_val_{}, __min_ind_{}, __max_ind_{}, __minmax_comp(nullptr) {} + _LIBCPP_HIDE_FROM_ABI _ComplexType( + const _ValueType& __min_val, const _ValueType& __max_val, const _Compare* __comp) + : __min_val_(__min_val), __max_val_(__max_val), __min_ind_(0), __max_ind_(0), + __minmax_comp(const_cast<_Compare*>(__comp)) + { + } + _LIBCPP_HIDE_FROM_ABI _ComplexType(const _ComplexType& __obj) + : __min_val_(__obj.__min_val_), __max_val_(__obj.__max_val_), __min_ind_(__obj.__min_ind_), + __max_ind_(__obj.__max_ind_), __minmax_comp(__obj.__minmax_comp) + { + } + + _LIBCPP_HIDE_FROM_ABI void + operator()(const _ComplexType& __obj) + { + // min + if ((*__minmax_comp)(__obj.__min_val_, __min_val_)) + { + __min_val_ = __obj.__min_val_; + __min_ind_ = __obj.__min_ind_; + } + else if (!(*__minmax_comp)(__min_val_, __obj.__min_val_)) + { + __min_val_ = __obj.__min_val_; + __min_ind_ = (__min_ind_ - __obj.__min_ind_ < 0) ? __min_ind_ : __obj.__min_ind_; + } + + // max + if ((*__minmax_comp)(__max_val_, __obj.__max_val_)) + { + __max_val_ = __obj.__max_val_; + __max_ind_ = __obj.__max_ind_; + } + else if (!(*__minmax_comp)(__obj.__max_val_, __max_val_)) + { + __max_val_ = __obj.__max_val_; + __max_ind_ = (__max_ind_ - __obj.__max_ind_ < 0) ? __obj.__max_ind_ : __max_ind_; + } + } + }; + + _ComplexType __init{*__first, *__first, &__comp}; + + _PSTL_PRAGMA_DECLARE_REDUCTION(__min_func, _ComplexType); + + _PSTL_PRAGMA_SIMD_REDUCTION(__min_func : __init) + for (_Size __i = 1; __i < __n; ++__i) + { + auto __min_val = __init.__min_val_; + auto __max_val = __init.__max_val_; + auto __current = __first + __i; + if (__comp(*__current, __min_val)) + { + __init.__min_val_ = *__current; + __init.__min_ind_ = __i; + } + else if (!__comp(*__current, __max_val)) + { + __init.__max_val_ = *__current; + __init.__max_ind_ = __i; + } + } + return std::make_pair(__first + __init.__min_ind_, __first + __init.__max_ind_); +} + +template <class _InputIterator, class _DifferenceType, class _OutputIterator1, class _OutputIterator2, + class _UnaryPredicate> +_LIBCPP_HIDE_FROM_ABI std::pair<_OutputIterator1, _OutputIterator2> +__simd_partition_copy(_InputIterator __first, _DifferenceType __n, _OutputIterator1 __out_true, + _OutputIterator2 __out_false, _UnaryPredicate __pred) noexcept +{ + _DifferenceType __cnt_true = 0, __cnt_false = 0; + + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 0; __i < __n; ++__i) + { + if (__pred(__first[__i])) + { + __out_true[__cnt_true] = __first[__i]; + ++__cnt_true; + } + else + { + __out_false[__cnt_false] = __first[__i]; + ++__cnt_false; + } + } + return std::make_pair(__out_true + __cnt_true, __out_false + __cnt_false); +} + +template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator1 +__simd_find_first_of(_ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, + _ForwardIterator2 __s_last, _BinaryPredicate __pred) noexcept +{ + typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferencType; + + const _DifferencType __n1 = __last - __first; + const _DifferencType __n2 = __s_last - __s_first; + if (__n1 == 0 || __n2 == 0) + { + return __last; // according to the standard + } + + // Common case + // If first sequence larger than second then we'll run simd_first with parameters of first sequence. + // Otherwise, vice versa. + if (__n1 < __n2) + { + for (; __first != __last; ++__first) + { + if (__unseq_backend::__simd_or( + __s_first, __n2, + __internal::__equal_value_by_pred<decltype(*__first), _BinaryPredicate>(*__first, __pred))) + { + return __first; + } + } + } + else + { + for (; __s_first != __s_last; ++__s_first) + { + const auto __result = __unseq_backend::__simd_first( + __first, _DifferencType(0), __n1, [__s_first, &__pred](_ForwardIterator1 __it, _DifferencType __i) { + return __pred(__it[__i], *__s_first); + }); + if (__result != __last) + { + return __result; + } + } + } + return __last; +} + +template <class _RandomAccessIterator, class _DifferenceType, class _UnaryPredicate> +_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator +__simd_remove_if(_RandomAccessIterator __first, _DifferenceType __n, _UnaryPredicate __pred) noexcept +{ + // find first element we need to remove + auto __current = __unseq_backend::__simd_first( + __first, _DifferenceType(0), __n, + [&__pred](_RandomAccessIterator __it, _DifferenceType __i) { return __pred(__it[__i]); }); + __n -= __current - __first; + + // if we have in sequence only one element that pred(__current[1]) != false we can exit the function + if (__n < 2) + { + return __current; + } + + _DifferenceType __cnt = 0; + _PSTL_PRAGMA_SIMD + for (_DifferenceType __i = 1; __i < __n; ++__i) + { + if (!__pred(__current[__i])) + { + __current[__cnt] = std::move(__current[__i]); + ++__cnt; + } + } + return __current + __cnt; +} +} // namespace __unseq_backend +} // namespace __pstl + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif /* _PSTL_UNSEQ_BACKEND_SIMD_H */ diff --git a/libcxx/include/__pstl/internal/utils.h b/libcxx/include/__pstl/internal/utils.h new file mode 100644 index 000000000000..92c8d48db5b1 --- /dev/null +++ b/libcxx/include/__pstl/internal/utils.h @@ -0,0 +1,144 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _PSTL_UTILS_H +#define _PSTL_UTILS_H + +#include <__config> +#include <__exception/terminate.h> +#include <__utility/forward.h> +#include <new> + +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +namespace __pstl { +namespace __internal { + +template <typename _Fp> +_LIBCPP_HIDE_FROM_ABI auto __except_handler(_Fp __f) -> decltype(__f()) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + return __f(); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (const std::bad_alloc&) { + throw; // re-throw bad_alloc according to the standard [algorithms.parallel.exceptions] + } catch (...) { + std::terminate(); // Good bye according to the standard [algorithms.parallel.exceptions] + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS +} + +template <typename _Fp> +_LIBCPP_HIDE_FROM_ABI void __invoke_if(std::true_type, _Fp __f) { + __f(); +} + +template <typename _Fp> +_LIBCPP_HIDE_FROM_ABI void __invoke_if(std::false_type, _Fp) {} + +template <typename _Fp> +_LIBCPP_HIDE_FROM_ABI void __invoke_if_not(std::false_type, _Fp __f) { + __f(); +} + +template <typename _Fp> +_LIBCPP_HIDE_FROM_ABI void __invoke_if_not(std::true_type, _Fp) {} + +template <typename _F1, typename _F2> +_LIBCPP_HIDE_FROM_ABI auto __invoke_if_else(std::true_type, _F1 __f1, _F2) -> decltype(__f1()) { + return __f1(); +} + +template <typename _F1, typename _F2> +_LIBCPP_HIDE_FROM_ABI auto __invoke_if_else(std::false_type, _F1, _F2 __f2) -> decltype(__f2()) { + return __f2(); +} + +//! Unary operator that returns reference to its argument. +struct __no_op { + template <typename _Tp> + _LIBCPP_HIDE_FROM_ABI _Tp&& operator()(_Tp&& __a) const { + return std::forward<_Tp>(__a); + } +}; + +template <typename _Pred> +class __reorder_pred { + _Pred __pred_; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __reorder_pred(_Pred __pred) : __pred_(__pred) {} + + template <typename _FTp, typename _STp> + _LIBCPP_HIDE_FROM_ABI bool operator()(_FTp&& __a, _STp&& __b) { + return __pred_(std::forward<_STp>(__b), std::forward<_FTp>(__a)); + } +}; + +//! Like a polymorphic lambda for pred(...,value) +template <typename _Tp, typename _Predicate> +class __equal_value_by_pred { + const _Tp& __value_; + _Predicate __pred_; + +public: + _LIBCPP_HIDE_FROM_ABI __equal_value_by_pred(const _Tp& __value, _Predicate __pred) + : __value_(__value), __pred_(__pred) {} + + template <typename _Arg> + _LIBCPP_HIDE_FROM_ABI bool operator()(_Arg&& __arg) { + return __pred_(std::forward<_Arg>(__arg), __value_); + } +}; + +//! Like a polymorphic lambda for ==value +template <typename _Tp> +class __equal_value { + const _Tp& __value_; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __equal_value(const _Tp& __value) : __value_(__value) {} + + template <typename _Arg> + _LIBCPP_HIDE_FROM_ABI bool operator()(_Arg&& __arg) const { + return std::forward<_Arg>(__arg) == __value_; + } +}; + +//! Logical negation of ==value +template <typename _Tp> +class __not_equal_value { + const _Tp& __value_; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __not_equal_value(const _Tp& __value) : __value_(__value) {} + + template <typename _Arg> + _LIBCPP_HIDE_FROM_ABI bool operator()(_Arg&& __arg) const { + return !(std::forward<_Arg>(__arg) == __value_); + } +}; + +template <typename _ForwardIterator, typename _Compare> +_LIBCPP_HIDE_FROM_ABI _ForwardIterator +__cmp_iterators_by_values(_ForwardIterator __a, _ForwardIterator __b, _Compare __comp) { + if (__a < __b) { // we should return closer iterator + return __comp(*__b, *__a) ? __b : __a; + } else { + return __comp(*__a, *__b) ? __a : __b; + } +} + +} // namespace __internal +} // namespace __pstl + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +#endif /* _PSTL_UTILS_H */ diff --git a/libcxx/include/__pstl_algorithm b/libcxx/include/__pstl_algorithm new file mode 100644 index 000000000000..79c18385c5a5 --- /dev/null +++ b/libcxx/include/__pstl_algorithm @@ -0,0 +1,15 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef __PSTL_ALGORITHM +#define __PSTL_ALGORITHM + +#include <pstl/internal/glue_algorithm_impl.h> + +#endif /* __PSTL_ALGORITHM */ diff --git a/libcxx/include/__pstl_config_site.in b/libcxx/include/__pstl_config_site.in new file mode 100644 index 000000000000..a41a1c383a45 --- /dev/null +++ b/libcxx/include/__pstl_config_site.in @@ -0,0 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef __PSTL_CONFIG_SITE +#define __PSTL_CONFIG_SITE + +#cmakedefine _PSTL_PAR_BACKEND_SERIAL +#cmakedefine _PSTL_PAR_BACKEND_TBB +#cmakedefine _PSTL_PAR_BACKEND_OPENMP +#cmakedefine _PSTL_HIDE_FROM_ABI_PER_TU + +#endif // __PSTL_CONFIG_SITE diff --git a/libcxx/include/__pstl_memory b/libcxx/include/__pstl_memory new file mode 100644 index 000000000000..12b7f5aa3c04 --- /dev/null +++ b/libcxx/include/__pstl_memory @@ -0,0 +1,15 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef __PSTL_MEMORY +#define __PSTL_MEMORY + +#include <pstl/internal/glue_memory_impl.h> + +#endif /* __PSTL_MEMORY */ diff --git a/libcxx/include/__pstl_numeric b/libcxx/include/__pstl_numeric new file mode 100644 index 000000000000..cf168ef7053b --- /dev/null +++ b/libcxx/include/__pstl_numeric @@ -0,0 +1,15 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef __PSTL_NUMERIC +#define __PSTL_NUMERIC + +#include <pstl/internal/glue_numeric_impl.h> + +#endif /* __PSTL_NUMERIC */ diff --git a/libcxx/include/__random/binomial_distribution.h b/libcxx/include/__random/binomial_distribution.h index 7b0f055d5068..18053c7d13d1 100644 --- a/libcxx/include/__random/binomial_distribution.h +++ b/libcxx/include/__random/binomial_distribution.h @@ -42,7 +42,7 @@ public: public: typedef binomial_distribution distribution_type; - explicit param_type(result_type __t = 1, double __p = 0.5); + _LIBCPP_HIDE_FROM_ABI explicit param_type(result_type __t = 1, double __p = 0.5); _LIBCPP_INLINE_VISIBILITY result_type t() const {return __t_;} @@ -85,7 +85,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__random/clamp_to_integral.h b/libcxx/include/__random/clamp_to_integral.h index 7d44ff9cfcad..c67d76d6e9ba 100644 --- a/libcxx/include/__random/clamp_to_integral.h +++ b/libcxx/include/__random/clamp_to_integral.h @@ -12,7 +12,6 @@ #include <__config> #include <cmath> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -44,8 +43,8 @@ template <class _IntT, class _RealT> _LIBCPP_INLINE_VISIBILITY _IntT __clamp_to_integral(_RealT __r) _NOEXCEPT { using _Lim = numeric_limits<_IntT>; - const _IntT _MaxVal = __max_representable_int_for_float<_IntT, _RealT>(); - if (__r >= ::nextafter(static_cast<_RealT>(_MaxVal), INFINITY)) { + const _IntT __max_val = __max_representable_int_for_float<_IntT, _RealT>(); + if (__r >= ::nextafter(static_cast<_RealT>(__max_val), INFINITY)) { return _Lim::max(); } else if (__r <= _Lim::lowest()) { return _Lim::min(); diff --git a/libcxx/include/__random/discard_block_engine.h b/libcxx/include/__random/discard_block_engine.h index db33623d9485..7bdcb6555cd5 100644 --- a/libcxx/include/__random/discard_block_engine.h +++ b/libcxx/include/__random/discard_block_engine.h @@ -11,10 +11,12 @@ #include <__config> #include <__random/is_seed_sequence.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> #include <__utility/move.h> +#include <cstddef> #include <iosfwd> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -90,7 +92,7 @@ public: seed(_Sseq& __q) {__e_.seed(__q); __n_ = 0;} // generating functions - result_type operator()(); + _LIBCPP_HIDE_FROM_ABI result_type operator()(); _LIBCPP_INLINE_VISIBILITY void discard(unsigned long long __z) {for (; __z; --__z) operator()();} diff --git a/libcxx/include/__random/discrete_distribution.h b/libcxx/include/__random/discrete_distribution.h index 03f49ba87239..a6546faae851 100644 --- a/libcxx/include/__random/discrete_distribution.h +++ b/libcxx/include/__random/discrete_distribution.h @@ -53,10 +53,10 @@ public: : __p_(__wl.begin(), __wl.end()) {__init();} #endif // _LIBCPP_CXX03_LANG template<class _UnaryOperation> - param_type(size_t __nw, double __xmin, double __xmax, + _LIBCPP_HIDE_FROM_ABI param_type(size_t __nw, double __xmin, double __xmax, _UnaryOperation __fw); - vector<double> probabilities() const; + _LIBCPP_HIDE_FROM_ABI vector<double> probabilities() const; friend _LIBCPP_INLINE_VISIBILITY bool operator==(const param_type& __x, const param_type& __y) @@ -66,7 +66,7 @@ public: {return !(__x == __y);} private: - void __init(); + _LIBCPP_HIDE_FROM_ABI void __init(); friend class discrete_distribution; @@ -115,7 +115,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__random/exponential_distribution.h b/libcxx/include/__random/exponential_distribution.h index 8edf1ac3f68c..b33b072eca08 100644 --- a/libcxx/include/__random/exponential_distribution.h +++ b/libcxx/include/__random/exponential_distribution.h @@ -79,7 +79,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__random/extreme_value_distribution.h b/libcxx/include/__random/extreme_value_distribution.h index b3cba392490b..c583ec06a314 100644 --- a/libcxx/include/__random/extreme_value_distribution.h +++ b/libcxx/include/__random/extreme_value_distribution.h @@ -84,7 +84,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__random/fisher_f_distribution.h b/libcxx/include/__random/fisher_f_distribution.h index b5479acb47c6..b757607bc461 100644 --- a/libcxx/include/__random/fisher_f_distribution.h +++ b/libcxx/include/__random/fisher_f_distribution.h @@ -82,7 +82,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__random/gamma_distribution.h b/libcxx/include/__random/gamma_distribution.h index 0d7fc3f82800..777f6b5c76d5 100644 --- a/libcxx/include/__random/gamma_distribution.h +++ b/libcxx/include/__random/gamma_distribution.h @@ -85,7 +85,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__random/generate_canonical.h b/libcxx/include/__random/generate_canonical.h index 5fada6df5903..5f0aa6fd850b 100644 --- a/libcxx/include/__random/generate_canonical.h +++ b/libcxx/include/__random/generate_canonical.h @@ -30,20 +30,20 @@ template<class _RealType, size_t __bits, class _URNG> _LIBCPP_HIDE_FROM_ABI _RealType generate_canonical(_URNG& __g) { - const size_t _Dt = numeric_limits<_RealType>::digits; - const size_t __b = _Dt < __bits ? _Dt : __bits; + const size_t __dt = numeric_limits<_RealType>::digits; + const size_t __b = __dt < __bits ? __dt : __bits; #ifdef _LIBCPP_CXX03_LANG - const size_t __logR = __log2<uint64_t, _URNG::_Max - _URNG::_Min + uint64_t(1)>::value; + const size_t __log_r = __log2<uint64_t, _URNG::_Max - _URNG::_Min + uint64_t(1)>::value; #else - const size_t __logR = __log2<uint64_t, _URNG::max() - _URNG::min() + uint64_t(1)>::value; + const size_t __log_r = __log2<uint64_t, _URNG::max() - _URNG::min() + uint64_t(1)>::value; #endif - const size_t __k = __b / __logR + (__b % __logR != 0) + (__b == 0); - const _RealType _Rp = static_cast<_RealType>(_URNG::max() - _URNG::min()) + _RealType(1); - _RealType __base = _Rp; - _RealType _Sp = __g() - _URNG::min(); - for (size_t __i = 1; __i < __k; ++__i, __base *= _Rp) - _Sp += (__g() - _URNG::min()) * __base; - return _Sp / __base; + const size_t __k = __b / __log_r + (__b % __log_r != 0) + (__b == 0); + const _RealType __rp = static_cast<_RealType>(_URNG::max() - _URNG::min()) + _RealType(1); + _RealType __base = __rp; + _RealType __sp = __g() - _URNG::min(); + for (size_t __i = 1; __i < __k; ++__i, __base *= __rp) + __sp += (__g() - _URNG::min()) * __base; + return __sp / __base; } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__random/independent_bits_engine.h b/libcxx/include/__random/independent_bits_engine.h index 151492a81bd0..a86c22157d0b 100644 --- a/libcxx/include/__random/independent_bits_engine.h +++ b/libcxx/include/__random/independent_bits_engine.h @@ -12,10 +12,13 @@ #include <__config> #include <__random/is_seed_sequence.h> #include <__random/log2.h> +#include <__type_traits/conditional.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_convertible.h> #include <__utility/move.h> +#include <cstddef> #include <iosfwd> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -161,7 +164,7 @@ public: private: _LIBCPP_INLINE_VISIBILITY result_type __eval(false_type); - result_type __eval(true_type); + _LIBCPP_HIDE_FROM_ABI result_type __eval(true_type); template <size_t __count> _LIBCPP_INLINE_VISIBILITY @@ -196,7 +199,7 @@ template<class _Engine, size_t __w, class _UIntType> _UIntType independent_bits_engine<_Engine, __w, _UIntType>::__eval(true_type) { - result_type _Sp = 0; + result_type __sp = 0; for (size_t __k = 0; __k < __n0; ++__k) { _Engine_result_type __u; @@ -204,7 +207,7 @@ independent_bits_engine<_Engine, __w, _UIntType>::__eval(true_type) { __u = __e_() - _Engine::min(); } while (__u >= __y0); - _Sp = static_cast<result_type>(__lshift<__w0>(_Sp) + (__u & __mask0)); + __sp = static_cast<result_type>(__lshift<__w0>(__sp) + (__u & __mask0)); } for (size_t __k = __n0; __k < __n; ++__k) { @@ -213,9 +216,9 @@ independent_bits_engine<_Engine, __w, _UIntType>::__eval(true_type) { __u = __e_() - _Engine::min(); } while (__u >= __y1); - _Sp = static_cast<result_type>(__lshift<__w0+1>(_Sp) + (__u & __mask1)); + __sp = static_cast<result_type>(__lshift<__w0+1>(__sp) + (__u & __mask1)); } - return _Sp; + return __sp; } template<class _Eng, size_t _Wp, class _UInt> diff --git a/libcxx/include/__random/is_seed_sequence.h b/libcxx/include/__random/is_seed_sequence.h index 3c82b2790b03..06621c3cee0d 100644 --- a/libcxx/include/__random/is_seed_sequence.h +++ b/libcxx/include/__random/is_seed_sequence.h @@ -10,7 +10,9 @@ #define _LIBCPP___RANDOM_IS_SEED_SEQUENCE_H #include <__config> -#include <type_traits> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cv.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__random/is_valid.h b/libcxx/include/__random/is_valid.h index 1d65de00fbb6..113452bc5d35 100644 --- a/libcxx/include/__random/is_valid.h +++ b/libcxx/include/__random/is_valid.h @@ -10,8 +10,12 @@ #define _LIBCPP___RANDOM_IS_VALID_H #include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_unsigned.h> +#include <__utility/declval.h> #include <cstdint> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__random/linear_congruential_engine.h b/libcxx/include/__random/linear_congruential_engine.h index 0d91f14120b6..2c2276eccf05 100644 --- a/libcxx/include/__random/linear_congruential_engine.h +++ b/libcxx/include/__random/linear_congruential_engine.h @@ -11,9 +11,11 @@ #include <__config> #include <__random/is_seed_sequence.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_unsigned.h> #include <cstdint> #include <iosfwd> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -294,9 +296,9 @@ private: void seed(false_type, false_type, result_type __s) {__x_ = __s % __m;} template<class _Sseq> - void __seed(_Sseq& __q, integral_constant<unsigned, 1>); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 1>); template<class _Sseq> - void __seed(_Sseq& __q, integral_constant<unsigned, 2>); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 2>); template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np> diff --git a/libcxx/include/__random/log2.h b/libcxx/include/__random/log2.h index 72bf0759eeac..4ccd1ddc9bf2 100644 --- a/libcxx/include/__random/log2.h +++ b/libcxx/include/__random/log2.h @@ -10,8 +10,8 @@ #define _LIBCPP___RANDOM_LOG2_H #include <__config> +#include <__type_traits/conditional.h> #include <cstddef> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__random/lognormal_distribution.h b/libcxx/include/__random/lognormal_distribution.h index 048d7dade9eb..1e8ac39dbac0 100644 --- a/libcxx/include/__random/lognormal_distribution.h +++ b/libcxx/include/__random/lognormal_distribution.h @@ -24,142 +24,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#ifdef _LIBCPP_ABI_OLD_LOGNORMAL_DISTRIBUTION - -template<class _RealType = double> -class _LIBCPP_TEMPLATE_VIS lognormal_distribution -{ -public: - // types - typedef _RealType result_type; - - class _LIBCPP_TEMPLATE_VIS param_type - { - normal_distribution<result_type> __nd_; - public: - typedef lognormal_distribution distribution_type; - - _LIBCPP_INLINE_VISIBILITY - explicit param_type(result_type __m = 0, result_type __s = 1) - : __nd_(__m, __s) {} - - _LIBCPP_INLINE_VISIBILITY - result_type m() const {return __nd_.mean();} - _LIBCPP_INLINE_VISIBILITY - result_type s() const {return __nd_.stddev();} - - friend _LIBCPP_INLINE_VISIBILITY - bool operator==(const param_type& __x, const param_type& __y) - {return __x.__nd_ == __y.__nd_;} - friend _LIBCPP_INLINE_VISIBILITY - bool operator!=(const param_type& __x, const param_type& __y) - {return !(__x == __y);} - friend class lognormal_distribution; - - template <class _CharT, class _Traits, class _RT> - friend - basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __os, - const lognormal_distribution<_RT>& __x); - - template <class _CharT, class _Traits, class _RT> - friend - basic_istream<_CharT, _Traits>& - operator>>(basic_istream<_CharT, _Traits>& __is, - lognormal_distribution<_RT>& __x); - }; - -private: - param_type __p_; - -public: - // constructor and reset functions -#ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY - lognormal_distribution() : lognormal_distribution(0) {} - _LIBCPP_INLINE_VISIBILITY - explicit lognormal_distribution(result_type __m, result_type __s = 1) - : __p_(param_type(__m, __s)) {} -#else - _LIBCPP_INLINE_VISIBILITY - explicit lognormal_distribution(result_type __m = 0, - result_type __s = 1) - : __p_(param_type(__m, __s)) {} -#endif - _LIBCPP_INLINE_VISIBILITY - explicit lognormal_distribution(const param_type& __p) - : __p_(__p) {} - _LIBCPP_INLINE_VISIBILITY - void reset() {__p_.__nd_.reset();} - - // generating functions - template<class _URNG> - _LIBCPP_INLINE_VISIBILITY - result_type operator()(_URNG& __g) - {return (*this)(__g, __p_);} - template<class _URNG> - _LIBCPP_INLINE_VISIBILITY - result_type operator()(_URNG& __g, const param_type& __p) - {return _VSTD::exp(const_cast<normal_distribution<result_type>&>(__p.__nd_)(__g));} - - // property functions - _LIBCPP_INLINE_VISIBILITY - result_type m() const {return __p_.m();} - _LIBCPP_INLINE_VISIBILITY - result_type s() const {return __p_.s();} - - _LIBCPP_INLINE_VISIBILITY - param_type param() const {return __p_;} - _LIBCPP_INLINE_VISIBILITY - void param(const param_type& __p) {__p_ = __p;} - - _LIBCPP_INLINE_VISIBILITY - result_type min() const {return 0;} - _LIBCPP_INLINE_VISIBILITY - result_type max() const {return numeric_limits<result_type>::infinity();} - - friend _LIBCPP_INLINE_VISIBILITY - bool operator==(const lognormal_distribution& __x, - const lognormal_distribution& __y) - {return __x.__p_ == __y.__p_;} - friend _LIBCPP_INLINE_VISIBILITY - bool operator!=(const lognormal_distribution& __x, - const lognormal_distribution& __y) - {return !(__x == __y);} - - template <class _CharT, class _Traits, class _RT> - friend - basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __os, - const lognormal_distribution<_RT>& __x); - - template <class _CharT, class _Traits, class _RT> - friend - basic_istream<_CharT, _Traits>& - operator>>(basic_istream<_CharT, _Traits>& __is, - lognormal_distribution<_RT>& __x); -}; - -template <class _CharT, class _Traits, class _RT> -inline _LIBCPP_INLINE_VISIBILITY -basic_ostream<_CharT, _Traits>& -operator<<(basic_ostream<_CharT, _Traits>& __os, - const lognormal_distribution<_RT>& __x) -{ - return __os << __x.__p_.__nd_; -} - -template <class _CharT, class _Traits, class _RT> -inline _LIBCPP_INLINE_VISIBILITY -basic_istream<_CharT, _Traits>& -operator>>(basic_istream<_CharT, _Traits>& __is, - lognormal_distribution<_RT>& __x) -{ - return __is >> __x.__p_.__nd_; -} - -#else // _LIBCPP_ABI_OLD_LOGNORMAL_DISTRIBUTION - template<class _RealType = double> class _LIBCPP_TEMPLATE_VIS lognormal_distribution { @@ -290,8 +154,6 @@ operator>>(basic_istream<_CharT, _Traits>& __is, return __is >> __x.__nd_; } -#endif // _LIBCPP_ABI_OLD_LOGNORMAL_DISTRIBUTION - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/libcxx/include/__random/mersenne_twister_engine.h b/libcxx/include/__random/mersenne_twister_engine.h index 3a58e311b001..663a6c704b77 100644 --- a/libcxx/include/__random/mersenne_twister_engine.h +++ b/libcxx/include/__random/mersenne_twister_engine.h @@ -17,7 +17,6 @@ #include <cstdint> #include <iosfwd> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -141,7 +140,7 @@ public: explicit mersenne_twister_engine(_Sseq& __q, typename enable_if<__is_seed_sequence<_Sseq, mersenne_twister_engine>::value>::type* = 0) {seed(__q);} - void seed(result_type __sd = default_seed); + _LIBCPP_HIDE_FROM_ABI void seed(result_type __sd = default_seed); template<class _Sseq> _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -153,7 +152,7 @@ public: {__seed(__q, integral_constant<unsigned, 1 + (__w - 1) / 32>());} // generating functions - result_type operator()(); + _LIBCPP_HIDE_FROM_ABI result_type operator()(); _LIBCPP_INLINE_VISIBILITY void discard(unsigned long long __z) {for (; __z; --__z) operator()();} @@ -199,9 +198,9 @@ public: private: template<class _Sseq> - void __seed(_Sseq& __q, integral_constant<unsigned, 1>); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 1>); template<class _Sseq> - void __seed(_Sseq& __q, integral_constant<unsigned, 2>); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 2>); template <size_t __count> _LIBCPP_INLINE_VISIBILITY @@ -403,9 +402,9 @@ mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, const size_t __j = (__i_ + 1) % __n; const result_type __mask = __r == _Dt ? result_type(~0) : (result_type(1) << __r) - result_type(1); - const result_type _Yp = (__x_[__i_] & ~__mask) | (__x_[__j] & __mask); + const result_type __yp = (__x_[__i_] & ~__mask) | (__x_[__j] & __mask); const size_t __k = (__i_ + __m) % __n; - __x_[__i_] = __x_[__k] ^ __rshift<1>(_Yp) ^ (__a * (_Yp & 1)); + __x_[__i_] = __x_[__k] ^ __rshift<1>(__yp) ^ (__a * (__yp & 1)); result_type __z = __x_[__i_] ^ (__rshift<__u>(__x_[__i_]) & __d); __i_ = __j; __z ^= __lshift<__s>(__z) & __b; diff --git a/libcxx/include/__random/negative_binomial_distribution.h b/libcxx/include/__random/negative_binomial_distribution.h index 333c9350cd72..21942710feb2 100644 --- a/libcxx/include/__random/negative_binomial_distribution.h +++ b/libcxx/include/__random/negative_binomial_distribution.h @@ -85,7 +85,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY @@ -135,8 +136,9 @@ negative_binomial_distribution<_IntType>::operator()(_URNG& __urng, const param_ else ++__f; } - _LIBCPP_ASSERT(__f >= 0, "std::negative_binomial_distribution should never produce negative values. " - "This is almost certainly a signed integer overflow issue on __f."); + _LIBCPP_ASSERT_UNCATEGORIZED(__f >= 0, + "std::negative_binomial_distribution should never produce negative values. " + "This is almost certainly a signed integer overflow issue on __f."); return __f; } return poisson_distribution<result_type>(gamma_distribution<double> diff --git a/libcxx/include/__random/normal_distribution.h b/libcxx/include/__random/normal_distribution.h index b2ed47e6af46..e2bf041b71fe 100644 --- a/libcxx/include/__random/normal_distribution.h +++ b/libcxx/include/__random/normal_distribution.h @@ -86,7 +86,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY @@ -133,30 +134,30 @@ _RealType normal_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p) { static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); - result_type _Up; + result_type __up; if (__v_hot_) { __v_hot_ = false; - _Up = __v_; + __up = __v_; } else { - uniform_real_distribution<result_type> _Uni(-1, 1); + uniform_real_distribution<result_type> __uni(-1, 1); result_type __u; result_type __v; result_type __s; do { - __u = _Uni(__g); - __v = _Uni(__g); + __u = __uni(__g); + __v = __uni(__g); __s = __u * __u + __v * __v; } while (__s > 1 || __s == 0); - result_type _Fp = _VSTD::sqrt(-2 * _VSTD::log(__s) / __s); - __v_ = __v * _Fp; + result_type __fp = _VSTD::sqrt(-2 * _VSTD::log(__s) / __s); + __v_ = __v * __fp; __v_hot_ = true; - _Up = __u * _Fp; + __up = __u * __fp; } - return _Up * __p.stddev() + __p.mean(); + return __up * __p.stddev() + __p.mean(); } template <class _CharT, class _Traits, class _RT> @@ -189,16 +190,16 @@ operator>>(basic_istream<_CharT, _Traits>& __is, __is.flags(_Istream::dec | _Istream::skipws); result_type __mean; result_type __stddev; - result_type _Vp = 0; - bool _V_hot = false; - __is >> __mean >> __stddev >> _V_hot; - if (_V_hot) - __is >> _Vp; + result_type __vp = 0; + bool __v_hot = false; + __is >> __mean >> __stddev >> __v_hot; + if (__v_hot) + __is >> __vp; if (!__is.fail()) { __x.param(param_type(__mean, __stddev)); - __x.__v_hot_ = _V_hot; - __x.__v_ = _Vp; + __x.__v_hot_ = __v_hot; + __x.__v_ = __vp; } return __is; } diff --git a/libcxx/include/__random/piecewise_constant_distribution.h b/libcxx/include/__random/piecewise_constant_distribution.h index a1f3ef9df50e..5b26ab65e63f 100644 --- a/libcxx/include/__random/piecewise_constant_distribution.h +++ b/libcxx/include/__random/piecewise_constant_distribution.h @@ -41,19 +41,19 @@ public: public: typedef piecewise_constant_distribution distribution_type; - param_type(); + _LIBCPP_HIDE_FROM_ABI param_type(); template<class _InputIteratorB, class _InputIteratorW> - param_type(_InputIteratorB __f_b, _InputIteratorB __l_b, + _LIBCPP_HIDE_FROM_ABI param_type(_InputIteratorB __f_b, _InputIteratorB __l_b, _InputIteratorW __f_w); #ifndef _LIBCPP_CXX03_LANG template<class _UnaryOperation> - param_type(initializer_list<result_type> __bl, _UnaryOperation __fw); + _LIBCPP_HIDE_FROM_ABI param_type(initializer_list<result_type> __bl, _UnaryOperation __fw); #endif // _LIBCPP_CXX03_LANG template<class _UnaryOperation> - param_type(size_t __nw, result_type __xmin, result_type __xmax, + _LIBCPP_HIDE_FROM_ABI param_type(size_t __nw, result_type __xmin, result_type __xmax, _UnaryOperation __fw); - param_type(param_type const&) = default; - param_type & operator=(const param_type& __rhs); + _LIBCPP_HIDE_FROM_ABI param_type(param_type const&) = default; + _LIBCPP_HIDE_FROM_ABI param_type & operator=(const param_type& __rhs); _LIBCPP_INLINE_VISIBILITY vector<result_type> intervals() const {return __b_;} @@ -68,7 +68,7 @@ public: {return !(__x == __y);} private: - void __init(); + _LIBCPP_HIDE_FROM_ABI void __init(); friend class piecewise_constant_distribution; @@ -125,7 +125,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__random/piecewise_linear_distribution.h b/libcxx/include/__random/piecewise_linear_distribution.h index fc2eb47c7b0f..6be44b29fcc8 100644 --- a/libcxx/include/__random/piecewise_linear_distribution.h +++ b/libcxx/include/__random/piecewise_linear_distribution.h @@ -41,19 +41,19 @@ public: public: typedef piecewise_linear_distribution distribution_type; - param_type(); + _LIBCPP_HIDE_FROM_ABI param_type(); template<class _InputIteratorB, class _InputIteratorW> - param_type(_InputIteratorB __f_b, _InputIteratorB __l_b, + _LIBCPP_HIDE_FROM_ABI param_type(_InputIteratorB __f_b, _InputIteratorB __l_b, _InputIteratorW __f_w); #ifndef _LIBCPP_CXX03_LANG template<class _UnaryOperation> - param_type(initializer_list<result_type> __bl, _UnaryOperation __fw); + _LIBCPP_HIDE_FROM_ABI param_type(initializer_list<result_type> __bl, _UnaryOperation __fw); #endif // _LIBCPP_CXX03_LANG template<class _UnaryOperation> - param_type(size_t __nw, result_type __xmin, result_type __xmax, + _LIBCPP_HIDE_FROM_ABI param_type(size_t __nw, result_type __xmin, result_type __xmax, _UnaryOperation __fw); - param_type(param_type const&) = default; - param_type & operator=(const param_type& __rhs); + _LIBCPP_HIDE_FROM_ABI param_type(param_type const&) = default; + _LIBCPP_HIDE_FROM_ABI param_type & operator=(const param_type& __rhs); _LIBCPP_INLINE_VISIBILITY vector<result_type> intervals() const {return __b_;} @@ -68,7 +68,7 @@ public: {return !(__x == __y);} private: - void __init(); + _LIBCPP_HIDE_FROM_ABI void __init(); friend class piecewise_linear_distribution; @@ -125,7 +125,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY @@ -188,23 +189,23 @@ void piecewise_linear_distribution<_RealType>::param_type::__init() { __areas_.assign(__densities_.size() - 1, result_type()); - result_type _Sp = 0; + result_type __sp = 0; for (size_t __i = 0; __i < __areas_.size(); ++__i) { __areas_[__i] = (__densities_[__i+1] + __densities_[__i]) * (__b_[__i+1] - __b_[__i]) * .5; - _Sp += __areas_[__i]; + __sp += __areas_[__i]; } for (size_t __i = __areas_.size(); __i > 1;) { --__i; - __areas_[__i] = __areas_[__i-1] / _Sp; + __areas_[__i] = __areas_[__i-1] / __sp; } __areas_[0] = 0; for (size_t __i = 1; __i < __areas_.size(); ++__i) __areas_[__i] += __areas_[__i-1]; for (size_t __i = 0; __i < __densities_.size(); ++__i) - __densities_[__i] /= _Sp; + __densities_[__i] /= __sp; } template<class _RealType> diff --git a/libcxx/include/__random/poisson_distribution.h b/libcxx/include/__random/poisson_distribution.h index 334c6102b341..eed120ebb7a7 100644 --- a/libcxx/include/__random/poisson_distribution.h +++ b/libcxx/include/__random/poisson_distribution.h @@ -52,7 +52,7 @@ public: public: typedef poisson_distribution distribution_type; - explicit param_type(double __mean = 1.0); + _LIBCPP_HIDE_FROM_ABI explicit param_type(double __mean = 1.0); _LIBCPP_INLINE_VISIBILITY double mean() const {return __mean_;} @@ -93,7 +93,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY @@ -144,12 +145,12 @@ poisson_distribution<_IntType>::param_type::param_type(double __mean) __d_ = 6 * __mean_ * __mean_; __l_ = _VSTD::trunc(__mean_ - 1.1484); __omega_ = .3989423 / __s_; - double __b1_ = .4166667E-1 / __mean_; - double __b2_ = .3 * __b1_ * __b1_; - __c3_ = .1428571 * __b1_ * __b2_; - __c2_ = __b2_ - 15. * __c3_; - __c1_ = __b1_ - 6. * __b2_ + 45. * __c3_; - __c0_ = 1. - __b1_ + 3. * __b2_ - 15. * __c3_; + double __b1 = .4166667E-1 / __mean_; + double __b2 = .3 * __b1 * __b1; + __c3_ = .1428571 * __b1 * __b2; + __c2_ = __b2 - 15. * __c3_; + __c1_ = __b1 - 6. * __b2 + 45. * __c3_; + __c0_ = 1. - __b1 + 3. * __b2 - 15. * __c3_; __c_ = .1069 / __mean_; } } diff --git a/libcxx/include/__random/random_device.h b/libcxx/include/__random/random_device.h index e82b437a3b54..e7c37241a72c 100644 --- a/libcxx/include/__random/random_device.h +++ b/libcxx/include/__random/random_device.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if !defined(_LIBCPP_HAS_NO_RANDOM_DEVICE) -class _LIBCPP_TYPE_VIS random_device +class _LIBCPP_EXPORTED_FROM_ABI random_device { #ifdef _LIBCPP_USING_DEV_RANDOM int __f_; @@ -58,7 +58,7 @@ public: // constructors #ifndef _LIBCPP_CXX03_LANG - random_device() : random_device("/dev/urandom") {} + _LIBCPP_HIDE_FROM_ABI random_device() : random_device("/dev/urandom") {} explicit random_device(const string& __token); #else explicit random_device(const string& __token = "/dev/urandom"); diff --git a/libcxx/include/__random/seed_seq.h b/libcxx/include/__random/seed_seq.h index 330537fa0023..506b979cf812 100644 --- a/libcxx/include/__random/seed_seq.h +++ b/libcxx/include/__random/seed_seq.h @@ -13,6 +13,8 @@ #include <__algorithm/fill.h> #include <__algorithm/max.h> #include <__config> +#include <__iterator/iterator_traits.h> +#include <cstdint> #include <initializer_list> #include <vector> @@ -52,7 +54,7 @@ public: // generating functions template<class _RandomAccessIterator> - void generate(_RandomAccessIterator __first, _RandomAccessIterator __last); + _LIBCPP_HIDE_FROM_ABI void generate(_RandomAccessIterator __first, _RandomAccessIterator __last); // property functions _LIBCPP_INLINE_VISIBILITY @@ -70,7 +72,7 @@ public: private: template<class _InputIterator> - void __init(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI void __init(_InputIterator __first, _InputIterator __last); vector<result_type> __v_; }; diff --git a/libcxx/include/__random/shuffle_order_engine.h b/libcxx/include/__random/shuffle_order_engine.h index 4a27289c2f81..e07f230d21c7 100644 --- a/libcxx/include/__random/shuffle_order_engine.h +++ b/libcxx/include/__random/shuffle_order_engine.h @@ -12,10 +12,13 @@ #include <__algorithm/equal.h> #include <__config> #include <__random/is_seed_sequence.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_convertible.h> #include <__utility/move.h> +#include <cstddef> #include <cstdint> #include <iosfwd> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -201,10 +204,10 @@ private: _LIBCPP_INLINE_VISIBILITY result_type __evalf() { - const double _Fp = __d == 0 ? + const double __fp = __d == 0 ? __n / (2. * 0x8000000000000000ull) : __n / (double)__d; - const size_t __j = static_cast<size_t>(_Fp * (__y_ - _Min)); + const size_t __j = static_cast<size_t>(__fp * (__y_ - _Min)); __y_ = __v_[__j]; __v_[__j] = __e_(); return __y_; @@ -262,16 +265,16 @@ operator>>(basic_istream<_CharT, _Traits>& __is, typedef basic_istream<_CharT, _Traits> _Istream; __is.flags(_Istream::dec | _Istream::skipws); _Eng __e; - result_type _Vp[_Kp+1]; + result_type __vp[_Kp+1]; __is >> __e; for (size_t __i = 0; __i < _Kp+1; ++__i) - __is >> _Vp[__i]; + __is >> __vp[__i]; if (!__is.fail()) { __x.__e_ = __e; for (size_t __i = 0; __i < _Kp; ++__i) - __x.__v_[__i] = _Vp[__i]; - __x.__y_ = _Vp[_Kp]; + __x.__v_[__i] = __vp[__i]; + __x.__y_ = __vp[_Kp]; } return __is; } diff --git a/libcxx/include/__random/student_t_distribution.h b/libcxx/include/__random/student_t_distribution.h index 64847aa66ae7..2d2be23657ae 100644 --- a/libcxx/include/__random/student_t_distribution.h +++ b/libcxx/include/__random/student_t_distribution.h @@ -81,7 +81,8 @@ public: _LIBCPP_INLINE_VISIBILITY result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__random/subtract_with_carry_engine.h b/libcxx/include/__random/subtract_with_carry_engine.h index b25ca84e3afd..c8954ca11195 100644 --- a/libcxx/include/__random/subtract_with_carry_engine.h +++ b/libcxx/include/__random/subtract_with_carry_engine.h @@ -18,7 +18,6 @@ #include <cstdint> #include <iosfwd> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -121,7 +120,7 @@ public: {__seed(__q, integral_constant<unsigned, 1 + (__w - 1) / 32>());} // generating functions - result_type operator()(); + _LIBCPP_HIDE_FROM_ABI result_type operator()(); _LIBCPP_INLINE_VISIBILITY void discard(unsigned long long __z) {for (; __z; --__z) operator()();} @@ -155,12 +154,12 @@ public: private: - void seed(result_type __sd, integral_constant<unsigned, 1>); - void seed(result_type __sd, integral_constant<unsigned, 2>); + _LIBCPP_HIDE_FROM_ABI void seed(result_type __sd, integral_constant<unsigned, 1>); + _LIBCPP_HIDE_FROM_ABI void seed(result_type __sd, integral_constant<unsigned, 2>); template<class _Sseq> - void __seed(_Sseq& __q, integral_constant<unsigned, 1>); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 1>); template<class _Sseq> - void __seed(_Sseq& __q, integral_constant<unsigned, 2>); + _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 2>); }; template<class _UIntType, size_t __w, size_t __s, size_t __r> diff --git a/libcxx/include/__random/uniform_int_distribution.h b/libcxx/include/__random/uniform_int_distribution.h index b7db8a3f9cbb..3a2b95c035b3 100644 --- a/libcxx/include/__random/uniform_int_distribution.h +++ b/libcxx/include/__random/uniform_int_distribution.h @@ -9,15 +9,16 @@ #ifndef _LIBCPP___RANDOM_UNIFORM_INT_DISTRIBUTION_H #define _LIBCPP___RANDOM_UNIFORM_INT_DISTRIBUTION_H +#include <__bit/countl.h> #include <__config> #include <__random/is_valid.h> #include <__random/log2.h> -#include <bit> +#include <__type_traits/conditional.h> +#include <__type_traits/make_unsigned.h> #include <cstddef> #include <cstdint> #include <iosfwd> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -63,14 +64,14 @@ private: public: // constructors and seeding functions - __independent_bits_engine(_Engine& __e, size_t __w); + _LIBCPP_HIDE_FROM_ABI __independent_bits_engine(_Engine& __e, size_t __w); // generating functions - result_type operator()() {return __eval(integral_constant<bool, _Rp != 0>());} + _LIBCPP_HIDE_FROM_ABI result_type operator()() {return __eval(integral_constant<bool, _Rp != 0>());} private: - result_type __eval(false_type); - result_type __eval(true_type); + _LIBCPP_HIDE_FROM_ABI result_type __eval(false_type); + _LIBCPP_HIDE_FROM_ABI result_type __eval(true_type); }; template<class _Engine, class _UIntType> @@ -120,8 +121,8 @@ template<class _Engine, class _UIntType> _UIntType __independent_bits_engine<_Engine, _UIntType>::__eval(true_type) { - const size_t _WRt = numeric_limits<result_type>::digits; - result_type _Sp = 0; + const size_t __w_rt = numeric_limits<result_type>::digits; + result_type __sp = 0; for (size_t __k = 0; __k < __n0_; ++__k) { _Engine_result_type __u; @@ -129,11 +130,11 @@ __independent_bits_engine<_Engine, _UIntType>::__eval(true_type) { __u = __e_() - _Engine::min(); } while (__u >= __y0_); - if (__w0_ < _WRt) - _Sp <<= __w0_; + if (__w0_ < __w_rt) + __sp <<= __w0_; else - _Sp = 0; - _Sp += __u & __mask0_; + __sp = 0; + __sp += __u & __mask0_; } for (size_t __k = __n0_; __k < __n_; ++__k) { @@ -142,13 +143,13 @@ __independent_bits_engine<_Engine, _UIntType>::__eval(true_type) { __u = __e_() - _Engine::min(); } while (__u >= __y1_); - if (__w0_ < _WRt - 1) - _Sp <<= __w0_ + 1; + if (__w0_ < __w_rt - 1) + __sp <<= __w0_ + 1; else - _Sp = 0; - _Sp += __u & __mask1_; + __sp = 0; + __sp += __u & __mask1_; } - return _Sp; + return __sp; } template<class _IntType = int> @@ -166,12 +167,12 @@ public: public: typedef uniform_int_distribution distribution_type; - explicit param_type(result_type __a = 0, + _LIBCPP_HIDE_FROM_ABI explicit param_type(result_type __a = 0, result_type __b = numeric_limits<result_type>::max()) : __a_(__a), __b_(__b) {} - result_type a() const {return __a_;} - result_type b() const {return __b_;} + _LIBCPP_HIDE_FROM_ABI result_type a() const {return __a_;} + _LIBCPP_HIDE_FROM_ABI result_type b() const {return __b_;} _LIBCPP_HIDE_FROM_ABI friend bool operator==(const param_type& __x, const param_type& __y) @@ -187,8 +188,8 @@ private: public: // constructors and reset functions #ifndef _LIBCPP_CXX03_LANG - uniform_int_distribution() : uniform_int_distribution(0) {} - explicit uniform_int_distribution( + _LIBCPP_HIDE_FROM_ABI uniform_int_distribution() : uniform_int_distribution(0) {} + _LIBCPP_HIDE_FROM_ABI explicit uniform_int_distribution( result_type __a, result_type __b = numeric_limits<result_type>::max()) : __p_(param_type(__a, __b)) {} #else @@ -197,23 +198,25 @@ public: result_type __b = numeric_limits<result_type>::max()) : __p_(param_type(__a, __b)) {} #endif - explicit uniform_int_distribution(const param_type& __p) : __p_(__p) {} - void reset() {} + _LIBCPP_HIDE_FROM_ABI explicit uniform_int_distribution(const param_type& __p) : __p_(__p) {} + _LIBCPP_HIDE_FROM_ABI void reset() {} // generating functions - template<class _URNG> result_type operator()(_URNG& __g) + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g) {return (*this)(__g, __p_);} - template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + template<class _URNG> + _LIBCPP_HIDE_FROM_ABI result_type operator()(_URNG& __g, const param_type& __p); // property functions - result_type a() const {return __p_.a();} - result_type b() const {return __p_.b();} + _LIBCPP_HIDE_FROM_ABI result_type a() const {return __p_.a();} + _LIBCPP_HIDE_FROM_ABI result_type b() const {return __p_.b();} - param_type param() const {return __p_;} - void param(const param_type& __p) {__p_ = __p;} + _LIBCPP_HIDE_FROM_ABI param_type param() const {return __p_;} + _LIBCPP_HIDE_FROM_ABI void param(const param_type& __p) {__p_ = __p;} - result_type min() const {return a();} - result_type max() const {return b();} + _LIBCPP_HIDE_FROM_ABI result_type min() const {return a();} + _LIBCPP_HIDE_FROM_ABI result_type max() const {return b();} _LIBCPP_HIDE_FROM_ABI friend bool operator==(const uniform_int_distribution& __x, @@ -234,22 +237,22 @@ _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK static_assert(__libcpp_random_is_valid_urng<_URNG>::value, ""); typedef __conditional_t<sizeof(result_type) <= sizeof(uint32_t), uint32_t, __make_unsigned_t<result_type> > _UIntType; - const _UIntType _Rp = _UIntType(__p.b()) - _UIntType(__p.a()) + _UIntType(1); - if (_Rp == 1) + const _UIntType __rp = _UIntType(__p.b()) - _UIntType(__p.a()) + _UIntType(1); + if (__rp == 1) return __p.a(); - const size_t _Dt = numeric_limits<_UIntType>::digits; + const size_t __dt = numeric_limits<_UIntType>::digits; typedef __independent_bits_engine<_URNG, _UIntType> _Eng; - if (_Rp == 0) - return static_cast<result_type>(_Eng(__g, _Dt)()); - size_t __w = _Dt - std::__countl_zero(_Rp) - 1; - if ((_Rp & (numeric_limits<_UIntType>::max() >> (_Dt - __w))) != 0) + if (__rp == 0) + return static_cast<result_type>(_Eng(__g, __dt)()); + size_t __w = __dt - std::__countl_zero(__rp) - 1; + if ((__rp & (numeric_limits<_UIntType>::max() >> (__dt - __w))) != 0) ++__w; _Eng __e(__g, __w); _UIntType __u; do { __u = __e(); - } while (__u >= _Rp); + } while (__u >= __rp); return static_cast<result_type>(__u + __p.a()); } diff --git a/libcxx/include/__random/uniform_random_bit_generator.h b/libcxx/include/__random/uniform_random_bit_generator.h index 84a30b0ebe16..ddb3158eead9 100644 --- a/libcxx/include/__random/uniform_random_bit_generator.h +++ b/libcxx/include/__random/uniform_random_bit_generator.h @@ -13,7 +13,8 @@ #include <__concepts/invocable.h> #include <__concepts/same_as.h> #include <__config> -#include <type_traits> +#include <__functional/invoke.h> +#include <__type_traits/integral_constant.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,7 +25,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [rand.req.urng] template<class _Gen> @@ -36,7 +37,7 @@ concept uniform_random_bit_generator = requires bool_constant<(_Gen::min() < _Gen::max())>::value; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__random/uniform_real_distribution.h b/libcxx/include/__random/uniform_real_distribution.h index b52b68977f82..1388cef95f39 100644 --- a/libcxx/include/__random/uniform_real_distribution.h +++ b/libcxx/include/__random/uniform_real_distribution.h @@ -14,7 +14,6 @@ #include <__random/is_valid.h> #include <iosfwd> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -65,7 +64,7 @@ public: #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY uniform_real_distribution() : uniform_real_distribution(0) {} - explicit uniform_real_distribution(result_type __a, result_type __b = 1) + _LIBCPP_HIDE_FROM_ABI explicit uniform_real_distribution(result_type __a, result_type __b = 1) : __p_(param_type(__a, __b)) {} #else _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/__ranges/access.h b/libcxx/include/__ranges/access.h index e48a71adf7e8..502bd5e951c4 100644 --- a/libcxx/include/__ranges/access.h +++ b/libcxx/include/__ranges/access.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template <class _Tp> @@ -223,7 +223,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/all.h b/libcxx/include/__ranges/all.h index 511f7b3b46f3..2c88f51b6644 100644 --- a/libcxx/include/__ranges/all.h +++ b/libcxx/include/__ranges/all.h @@ -11,6 +11,8 @@ #define _LIBCPP___RANGES_ALL_H #include <__config> +#include <__functional/compose.h> // TODO(modules): Those should not be required +#include <__functional/perfect_forward.h> // #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__ranges/access.h> @@ -18,10 +20,10 @@ #include <__ranges/owning_view.h> #include <__ranges/range_adaptor.h> #include <__ranges/ref_view.h> +#include <__type_traits/decay.h> #include <__utility/auto_cast.h> #include <__utility/declval.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -29,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges::views { @@ -77,7 +79,7 @@ using all_t = decltype(views::all(std::declval<_Range>())); } // namespace ranges::views -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/as_rvalue_view.h b/libcxx/include/__ranges/as_rvalue_view.h index 422d8a8e0834..295aa94ed9fe 100644 --- a/libcxx/include/__ranges/as_rvalue_view.h +++ b/libcxx/include/__ranges/as_rvalue_view.h @@ -28,6 +28,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + #if _LIBCPP_STD_VER >= 23 _LIBCPP_BEGIN_NAMESPACE_STD @@ -125,7 +128,7 @@ struct __fn : __range_adaptor_closure<__fn> { } // namespace __as_rvalue inline namespace __cpo { -constexpr auto as_rvalue = __as_rvalue::__fn{}; +inline constexpr auto as_rvalue = __as_rvalue::__fn{}; } // namespace __cpo } // namespace views } // namespace ranges @@ -134,4 +137,6 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER >= 23 +_LIBCPP_POP_MACROS + #endif // _LIBCPP___RANGES_AS_RVALUE_H diff --git a/libcxx/include/__ranges/common_view.h b/libcxx/include/__ranges/common_view.h index 8d7ae5841579..f4cd18074904 100644 --- a/libcxx/include/__ranges/common_view.h +++ b/libcxx/include/__ranges/common_view.h @@ -24,15 +24,17 @@ #include <__ranges/view_interface.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -130,8 +132,10 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___RANGES_COMMON_VIEW_H diff --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h index e34c545578ab..b87a71460610 100644 --- a/libcxx/include/__ranges/concepts.h +++ b/libcxx/include/__ranges/concepts.h @@ -37,7 +37,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -73,6 +73,9 @@ namespace ranges { template <range _Rp> using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp>>; + template <range _Rp> + using range_common_reference_t = iter_common_reference_t<iterator_t<_Rp>>; + // [range.sized] template <class _Tp> concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); }; @@ -140,7 +143,7 @@ namespace ranges { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/container_compatible_range.h b/libcxx/include/__ranges/container_compatible_range.h new file mode 100644 index 000000000000..a58f1119885e --- /dev/null +++ b/libcxx/include/__ranges/container_compatible_range.h @@ -0,0 +1,33 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_CONTAINER_COMPATIBLE_RANGE_H +#define _LIBCPP___RANGES_CONTAINER_COMPATIBLE_RANGE_H + +#include <__concepts/convertible_to.h> +#include <__config> +#include <__ranges/concepts.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +template <class _Range, class _Tp> +concept _ContainerCompatibleRange = + ranges::input_range<_Range> && convertible_to<ranges::range_reference_t<_Range>, _Tp>; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_CONTAINER_COMPATIBLE_RANGE_H diff --git a/libcxx/include/__ranges/copyable_box.h b/libcxx/include/__ranges/copyable_box.h deleted file mode 100644 index fb3d6e409c8f..000000000000 --- a/libcxx/include/__ranges/copyable_box.h +++ /dev/null @@ -1,180 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___RANGES_COPYABLE_BOX_H -#define _LIBCPP___RANGES_COPYABLE_BOX_H - -#include <__concepts/constructible.h> -#include <__concepts/copyable.h> -#include <__concepts/movable.h> -#include <__config> -#include <__memory/addressof.h> -#include <__memory/construct_at.h> -#include <__utility/move.h> -#include <optional> -#include <type_traits> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -#if _LIBCPP_STD_VER > 17 - -// __copyable_box allows turning a type that is copy-constructible (but maybe not copy-assignable) into -// a type that is both copy-constructible and copy-assignable. It does that by introducing an empty state -// and basically doing destroy-then-copy-construct in the assignment operator. The empty state is necessary -// to handle the case where the copy construction fails after destroying the object. -// -// In some cases, we can completely avoid the use of an empty state; we provide a specialization of -// __copyable_box that does this, see below for the details. - -template<class _Tp> -concept __copy_constructible_object = copy_constructible<_Tp> && is_object_v<_Tp>; - -namespace ranges { - // Primary template - uses std::optional and introduces an empty state in case assignment fails. - template<__copy_constructible_object _Tp> - class __copyable_box { - _LIBCPP_NO_UNIQUE_ADDRESS optional<_Tp> __val_; - - public: - template<class ..._Args> - requires is_constructible_v<_Tp, _Args...> - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __copyable_box(in_place_t, _Args&& ...__args) - noexcept(is_nothrow_constructible_v<_Tp, _Args...>) - : __val_(in_place, std::forward<_Args>(__args)...) - { } - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) - requires default_initializable<_Tp> - : __val_(in_place) - { } - - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box const&) = default; - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box&&) = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box const& __other) - noexcept(is_nothrow_copy_constructible_v<_Tp>) - { - if (this != std::addressof(__other)) { - if (__other.__has_value()) __val_.emplace(*__other); - else __val_.reset(); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - __copyable_box& operator=(__copyable_box&&) requires movable<_Tp> = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box&& __other) - noexcept(is_nothrow_move_constructible_v<_Tp>) - { - if (this != std::addressof(__other)) { - if (__other.__has_value()) __val_.emplace(std::move(*__other)); - else __val_.reset(); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return *__val_; } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return *__val_; } - - _LIBCPP_HIDE_FROM_ABI constexpr const _Tp *operator->() const noexcept { return __val_.operator->(); } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp *operator->() noexcept { return __val_.operator->(); } - - _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return __val_.has_value(); } - }; - - // This partial specialization implements an optimization for when we know we don't need to store - // an empty state to represent failure to perform an assignment. For copy-assignment, this happens: - // - // 1. If the type is copyable (which includes copy-assignment), we can use the type's own assignment operator - // directly and avoid using std::optional. - // 2. If the type is not copyable, but it is nothrow-copy-constructible, then we can implement assignment as - // destroy-and-then-construct and we know it will never fail, so we don't need an empty state. - // - // The exact same reasoning can be applied for move-assignment, with copyable replaced by movable and - // nothrow-copy-constructible replaced by nothrow-move-constructible. This specialization is enabled - // whenever we can apply any of these optimizations for both the copy assignment and the move assignment - // operator. - template<class _Tp> - concept __doesnt_need_empty_state_for_copy = copyable<_Tp> || is_nothrow_copy_constructible_v<_Tp>; - - template<class _Tp> - concept __doesnt_need_empty_state_for_move = movable<_Tp> || is_nothrow_move_constructible_v<_Tp>; - - template<__copy_constructible_object _Tp> - requires __doesnt_need_empty_state_for_copy<_Tp> && __doesnt_need_empty_state_for_move<_Tp> - class __copyable_box<_Tp> { - _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; - - public: - template<class ..._Args> - requires is_constructible_v<_Tp, _Args...> - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __copyable_box(in_place_t, _Args&& ...__args) - noexcept(is_nothrow_constructible_v<_Tp, _Args...>) - : __val_(std::forward<_Args>(__args)...) - { } - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) - requires default_initializable<_Tp> - : __val_() - { } - - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box const&) = default; - _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box&&) = default; - - // Implementation of assignment operators in case we perform optimization (1) - _LIBCPP_HIDE_FROM_ABI __copyable_box& operator=(__copyable_box const&) requires copyable<_Tp> = default; - _LIBCPP_HIDE_FROM_ABI __copyable_box& operator=(__copyable_box&&) requires movable<_Tp> = default; - - // Implementation of assignment operators in case we perform optimization (2) - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box const& __other) noexcept { - static_assert(is_nothrow_copy_constructible_v<_Tp>); - if (this != std::addressof(__other)) { - std::destroy_at(std::addressof(__val_)); - std::construct_at(std::addressof(__val_), __other.__val_); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __copyable_box& operator=(__copyable_box&& __other) noexcept { - static_assert(is_nothrow_move_constructible_v<_Tp>); - if (this != std::addressof(__other)) { - std::destroy_at(std::addressof(__val_)); - std::construct_at(std::addressof(__val_), std::move(__other.__val_)); - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return __val_; } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return __val_; } - - _LIBCPP_HIDE_FROM_ABI constexpr const _Tp *operator->() const noexcept { return std::addressof(__val_); } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp *operator->() noexcept { return std::addressof(__val_); } - - _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return true; } - }; -} // namespace ranges - -#endif // _LIBCPP_STD_VER > 17 - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___RANGES_COPYABLE_BOX_H diff --git a/libcxx/include/__ranges/counted.h b/libcxx/include/__ranges/counted.h index 138aa0e1dde5..882f90b1ed82 100644 --- a/libcxx/include/__ranges/counted.h +++ b/libcxx/include/__ranges/counted.h @@ -19,10 +19,11 @@ #include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> #include <__ranges/subrange.h> +#include <__type_traits/decay.h> #include <__utility/forward.h> #include <__utility/move.h> +#include <cstddef> #include <span> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -30,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges::views { @@ -75,7 +76,7 @@ inline namespace __cpo { } // namespace ranges::views -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/dangling.h b/libcxx/include/__ranges/dangling.h index c10453454dc3..613084d5fb9f 100644 --- a/libcxx/include/__ranges/dangling.h +++ b/libcxx/include/__ranges/dangling.h @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { struct dangling { @@ -35,7 +35,7 @@ using borrowed_iterator_t = _If<borrowed_range<_Rp>, iterator_t<_Rp>, dangling>; // borrowed_subrange_t defined in <__ranges/subrange.h> } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/data.h b/libcxx/include/__ranges/data.h index 0ac25b52c727..6c099085af34 100644 --- a/libcxx/include/__ranges/data.h +++ b/libcxx/include/__ranges/data.h @@ -30,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.prim.data] @@ -105,7 +105,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h index 8f3564a8c760..f10476f0011e 100644 --- a/libcxx/include/__ranges/drop_view.h +++ b/libcxx/include/__ranges/drop_view.h @@ -30,13 +30,19 @@ #include <__ranges/iota_view.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> +#include <__ranges/repeat_view.h> #include <__ranges/size.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_cvref.h> #include <__utility/auto_cast.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -47,7 +53,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template<view _View> @@ -66,14 +72,14 @@ namespace ranges { _View __base_ = _View(); public: - drop_view() requires default_initializable<_View> = default; + _LIBCPP_HIDE_FROM_ABI drop_view() requires default_initializable<_View> = default; _LIBCPP_HIDE_FROM_ABI - constexpr drop_view(_View __base, range_difference_t<_View> __count) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 drop_view(_View __base, range_difference_t<_View> __count) : __count_(__count) , __base_(std::move(__base)) { - _LIBCPP_ASSERT(__count_ >= 0, "count must be greater than or equal to zero."); + _LIBCPP_ASSERT_UNCATEGORIZED(__count_ >= 0, "count must be greater than or equal to zero."); } _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& requires copy_constructible<_View> { return __base_; } @@ -255,13 +261,39 @@ struct __fn { { // Introducing local variables avoids calculating `min` and `distance` twice (at the cost of diverging from the // expression used in the `noexcept` clause and the return statement). - auto dist = ranges::distance(__rng); - auto clamped = std::min<_Dist>(dist, std::forward<_Np>(__n)); + auto __dist = ranges::distance(__rng); + auto __clamped = std::min<_Dist>(__dist, std::forward<_Np>(__n)); return _RawRange( - ranges::begin(__rng) + clamped, + ranges::begin(__rng) + __clamped, ranges::end(__rng), - std::__to_unsigned_like(dist - clamped) + std::__to_unsigned_like(__dist - __clamped) );} +// clang-format off +#if _LIBCPP_STD_VER >= 23 + // [range.drop.overview]: the `repeat_view` "_RawRange models sized_range" case. + template <class _Range, + convertible_to<range_difference_t<_Range>> _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires (__is_repeat_specialization<_RawRange> && sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + noexcept(noexcept(views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) + -> decltype( views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) + { return views::repeat(*__range.__value_, ranges::distance(__range) - std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); } + + // [range.drop.overview]: the `repeat_view` "otherwise" case. + template <class _Range, + convertible_to<range_difference_t<_Range>> _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires (__is_repeat_specialization<_RawRange> && !sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()(_Range&& __range, _Np&&) const + noexcept(noexcept(_LIBCPP_AUTO_CAST(std::forward<_Range>(__range)))) + -> decltype( _LIBCPP_AUTO_CAST(std::forward<_Range>(__range))) + { return _LIBCPP_AUTO_CAST(std::forward<_Range>(__range)); } +#endif +// clang-format on // [range.drop.overview]: the "otherwise" case. template <class _Range, convertible_to<range_difference_t<_Range>> _Np, @@ -269,6 +301,9 @@ struct __fn { // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other // overloads. requires (!(__is_empty_view<_RawRange> || +#if _LIBCPP_STD_VER >= 23 + __is_repeat_specialization<_RawRange> || +#endif (__is_subrange_specialization_with_store_size<_RawRange> && sized_range<_RawRange> && random_access_range<_RawRange>) || @@ -299,7 +334,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/drop_while_view.h b/libcxx/include/__ranges/drop_while_view.h index 7c28992f1874..677b5bc66d44 100644 --- a/libcxx/include/__ranges/drop_while_view.h +++ b/libcxx/include/__ranges/drop_while_view.h @@ -20,8 +20,8 @@ #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> #include <__ranges/enable_borrowed_range.h> +#include <__ranges/movable_box.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> @@ -51,7 +51,7 @@ public: requires default_initializable<_View> && default_initializable<_Pred> = default; - _LIBCPP_HIDE_FROM_ABI constexpr drop_while_view(_View __base, _Pred __pred) + _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 drop_while_view(_View __base, _Pred __pred) : __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {} _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& @@ -65,9 +65,10 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr const _Pred& pred() const { return *__pred_; } _LIBCPP_HIDE_FROM_ABI constexpr auto begin() { - _LIBCPP_ASSERT(__pred_.__has_value(), - "drop_while_view needs to have a non-empty predicate before calling begin() -- did a previous " - "assignment to this drop_while_view fail?"); + _LIBCPP_ASSERT_UNCATEGORIZED( + __pred_.__has_value(), + "drop_while_view needs to have a non-empty predicate before calling begin() -- did a previous " + "assignment to this drop_while_view fail?"); if constexpr (_UseCache) { if (!__cached_begin_.__has_value()) { __cached_begin_.__emplace(ranges::find_if_not(__base_, std::cref(*__pred_))); @@ -82,7 +83,7 @@ public: private: _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_; static constexpr bool _UseCache = forward_range<_View>; using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; diff --git a/libcxx/include/__ranges/elements_view.h b/libcxx/include/__ranges/elements_view.h index 3afd6ddbe8f2..325e4c9dca63 100644 --- a/libcxx/include/__ranges/elements_view.h +++ b/libcxx/include/__ranges/elements_view.h @@ -26,9 +26,9 @@ #include <__ranges/range_adaptor.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> -#include <__tuple_dir/tuple_element.h> -#include <__tuple_dir/tuple_like.h> -#include <__tuple_dir/tuple_size.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_like.h> +#include <__tuple/tuple_size.h> #include <__type_traits/is_reference.h> #include <__type_traits/maybe_const.h> #include <__type_traits/remove_cv.h> @@ -49,12 +49,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { -template <class _View, size_t _Np, bool _Const> -class __elements_view_iterator; - -template <class _View, size_t _Np, bool _Const> -class __elements_view_sentinel; - template <class _Tp, size_t _Np> concept __has_tuple_element = __tuple_like<_Tp> && _Np < tuple_size<_Tp>::value; @@ -66,6 +60,13 @@ template <input_range _View, size_t _Np> __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && __returnable_element<range_reference_t<_View>, _Np> class elements_view : public view_interface<elements_view<_View, _Np>> { +private: + template <bool> + class __iterator; + + template <bool> + class __sentinel; + public: _LIBCPP_HIDE_FROM_ABI elements_view() requires default_initializable<_View> @@ -130,12 +131,6 @@ public: } private: - template <bool _Const> - using __iterator = __elements_view_iterator<_View, _Np, _Const>; - - template <bool _Const> - using __sentinel = __elements_view_sentinel<_View, _Np, _Const>; - _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); }; @@ -160,13 +155,18 @@ struct __elements_view_iterator_category_base<_Base, _Np> { using iterator_category = decltype(__get_iterator_category()); }; -template <class _View, size_t _Np, bool _Const> -class __elements_view_iterator : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> { - template <class, size_t, bool > - friend class __elements_view_iterator; +template <input_range _View, size_t _Np> + requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && + __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && + __returnable_element<range_reference_t<_View>, _Np> +template <bool _Const> +class elements_view<_View, _Np>::__iterator + : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> { + template <bool> + friend class __iterator; - template <class, size_t, bool > - friend class __elements_view_sentinel; + template <bool> + friend class __sentinel; using _Base = __maybe_const<_Const, _View>; @@ -198,14 +198,13 @@ public: using value_type = remove_cvref_t<tuple_element_t<_Np, range_value_t<_Base>>>; using difference_type = range_difference_t<_Base>; - _LIBCPP_HIDE_FROM_ABI __elements_view_iterator() + _LIBCPP_HIDE_FROM_ABI __iterator() requires default_initializable<iterator_t<_Base>> = default; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __elements_view_iterator(iterator_t<_Base> __current) - : __current_(std::move(__current)) {} + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {} - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator(__elements_view_iterator<_View, _Np, !_Const> __i) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i) requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> : __current_(std::move(__i.__current_)) {} @@ -215,44 +214,44 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return __get_element(__current_); } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { ++__current_; return *this; } _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator operator++(int) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) requires forward_range<_Base> { - auto temp = *this; + auto __temp = *this; ++__current_; - return temp; + return __temp; } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator--() + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() requires bidirectional_range<_Base> { --__current_; return *this; } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator operator--(int) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) requires bidirectional_range<_Base> { - auto temp = *this; + auto __temp = *this; --__current_; - return temp; + return __temp; } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator+=(difference_type __n) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) requires random_access_range<_Base> { __current_ += __n; return *this; } - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator-=(difference_type __n) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) requires random_access_range<_Base> { __current_ -= __n; @@ -265,99 +264,91 @@ public: return __get_element(__current_ + __n); } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) requires equality_comparable<iterator_t<_Base>> { return __x.__current_ == __y.__current_; } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator<(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __x.__current_ < __y.__current_; } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator>(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __y < __x; } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator<=(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return !(__y < __x); } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator>=(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return !(__x < __y); } - _LIBCPP_HIDE_FROM_ABI friend constexpr auto - operator<=>(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> { return __x.__current_ <=> __y.__current_; } - _LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator - operator+(const __elements_view_iterator& __x, difference_type __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __x, difference_type __y) requires random_access_range<_Base> { - return __elements_view_iterator{__x} += __y; + return __iterator{__x} += __y; } - _LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator - operator+(difference_type __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __x, const __iterator& __y) requires random_access_range<_Base> { return __y + __x; } - _LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator - operator-(const __elements_view_iterator& __x, difference_type __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __x, difference_type __y) requires random_access_range<_Base> { - return __elements_view_iterator{__x} -= __y; + return __iterator{__x} -= __y; } - _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type - operator-(const __elements_view_iterator& __x, const __elements_view_iterator& __y) + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> { return __x.__current_ - __y.__current_; } }; -template <class _View, size_t _Np, bool _Const> -class __elements_view_sentinel { +template <input_range _View, size_t _Np> + requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && + __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && + __returnable_element<range_reference_t<_View>, _Np> +template <bool _Const> +class elements_view<_View, _Np>::__sentinel { private: using _Base = __maybe_const<_Const, _View>; _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>(); - template <class, size_t, bool > - friend class __elements_view_sentinel; + template <bool> + friend class __sentinel; template <bool _AnyConst> - _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) - __get_current(const __elements_view_iterator<_View, _Np, _AnyConst>& __iter) { + _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_current(const __iterator<_AnyConst>& __iter) { return (__iter.__current_); } public: - _LIBCPP_HIDE_FROM_ABI __elements_view_sentinel() = default; + _LIBCPP_HIDE_FROM_ABI __sentinel() = default; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __elements_view_sentinel(sentinel_t<_Base> __end) - : __end_(std::move(__end)) {} + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {} - _LIBCPP_HIDE_FROM_ABI constexpr __elements_view_sentinel(__elements_view_sentinel<_View, _Np, !_Const> __other) + _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __other) requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> : __end_(std::move(__other.__end_)) {} @@ -365,22 +356,21 @@ public: template <bool _OtherConst> requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const __elements_view_iterator<_View, _Np, _OtherConst>& __x, const __elements_view_sentinel& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __get_current(__x) == __y.__end_; } template <bool _OtherConst> requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> - operator-(const __elements_view_iterator<_View, _Np, _OtherConst>& __x, const __elements_view_sentinel& __y) { + operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __get_current(__x) - __y.__end_; } template <bool _OtherConst> requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> - operator-(const __elements_view_sentinel& __x, const __elements_view_iterator<_View, _Np, _OtherConst>& __y) { + operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { return __x.__end_ - __get_current(__y); } }; diff --git a/libcxx/include/__ranges/empty.h b/libcxx/include/__ranges/empty.h index 8a1c75c0bae0..64996f4a6f7b 100644 --- a/libcxx/include/__ranges/empty.h +++ b/libcxx/include/__ranges/empty.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.prim.empty] @@ -75,7 +75,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/empty_view.h b/libcxx/include/__ranges/empty_view.h index 58e69ac19f29..bb445b4e6f94 100644 --- a/libcxx/include/__ranges/empty_view.h +++ b/libcxx/include/__ranges/empty_view.h @@ -13,7 +13,8 @@ #include <__config> #include <__ranges/enable_borrowed_range.h> #include <__ranges/view_interface.h> -#include <type_traits> +#include <__type_traits/is_object.h> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -21,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template<class _Tp> @@ -46,7 +47,7 @@ namespace ranges { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/enable_borrowed_range.h b/libcxx/include/__ranges/enable_borrowed_range.h index 833d266403ca..1d068335e20a 100644 --- a/libcxx/include/__ranges/enable_borrowed_range.h +++ b/libcxx/include/__ranges/enable_borrowed_range.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -33,7 +33,7 @@ inline constexpr bool enable_borrowed_range = false; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/enable_view.h b/libcxx/include/__ranges/enable_view.h index c85064b915ab..0c1dff3821ea 100644 --- a/libcxx/include/__ranges/enable_view.h +++ b/libcxx/include/__ranges/enable_view.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -43,7 +43,7 @@ inline constexpr bool enable_view = derived_from<_Tp, view_base> || } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/filter_view.h b/libcxx/include/__ranges/filter_view.h index f8633a3fee84..1cef94ca6744 100644 --- a/libcxx/include/__ranges/filter_view.h +++ b/libcxx/include/__ranges/filter_view.h @@ -11,12 +11,12 @@ #define _LIBCPP___RANGES_FILTER_VIEW_H #include <__algorithm/ranges_find_if.h> +#include <__assert> #include <__concepts/constructible.h> #include <__concepts/copyable.h> #include <__concepts/derived_from.h> #include <__concepts/equality_comparable.h> #include <__config> -#include <__debug> #include <__functional/bind_back.h> #include <__functional/invoke.h> #include <__functional/reference_wrapper.h> @@ -28,14 +28,17 @@ #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> +#include <__ranges/movable_box.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_object.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -43,23 +46,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { - - template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> - requires view<_View> && is_object_v<_Pred> - class __filter_view_iterator; - - template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> - requires view<_View> && is_object_v<_Pred> - class __filter_view_sentinel; - template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires view<_View> && is_object_v<_Pred> class filter_view : public view_interface<filter_view<_View, _Pred>> { _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_; // We cache the result of begin() to allow providing an amortized O(1) begin() whenever // the underlying range is at least a forward_range. @@ -67,20 +61,15 @@ namespace ranges { using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache(); - using __iterator = __filter_view_iterator<_View, _Pred>; - using __sentinel = __filter_view_sentinel<_View, _Pred>; - - friend __iterator; - friend __sentinel; + class __iterator; + class __sentinel; public: _LIBCPP_HIDE_FROM_ABI filter_view() requires default_initializable<_View> && default_initializable<_Pred> = default; - _LIBCPP_HIDE_FROM_ABI - constexpr filter_view(_View __base, _Pred __pred) - : __base_(std::move(__base)), __pred_(in_place, std::move(__pred)) - { } + _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 filter_view(_View __base, _Pred __pred) + : __base_(std::move(__base)), __pred_(in_place, std::move(__pred)) {} template<class _Vp = _View> _LIBCPP_HIDE_FROM_ABI @@ -93,7 +82,9 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() { - _LIBCPP_ASSERT(__pred_.__has_value(), "Trying to call begin() on a filter_view that does not have a valid predicate."); + _LIBCPP_ASSERT_UNCATEGORIZED( + __pred_.__has_value(), + "Trying to call begin() on a filter_view that does not have a valid predicate."); if constexpr (_UseCache) { if (!__cached_begin_.__has_value()) { __cached_begin_.__emplace(ranges::find_if(__base_, std::ref(*__pred_))); @@ -131,13 +122,11 @@ namespace ranges { template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires view<_View> && is_object_v<_Pred> - class __filter_view_iterator : public __filter_iterator_category<_View> { - - using __filter_view = filter_view<_View, _Pred>; + class filter_view<_View, _Pred>::__iterator : public __filter_iterator_category<_View> { public: _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __current_ = iterator_t<_View>(); - _LIBCPP_NO_UNIQUE_ADDRESS __filter_view* __parent_ = nullptr; + _LIBCPP_NO_UNIQUE_ADDRESS filter_view* __parent_ = nullptr; using iterator_concept = _If<bidirectional_range<_View>, bidirectional_iterator_tag, @@ -149,10 +138,10 @@ namespace ranges { using difference_type = range_difference_t<_View>; _LIBCPP_HIDE_FROM_ABI - __filter_view_iterator() requires default_initializable<iterator_t<_View>> = default; + __iterator() requires default_initializable<iterator_t<_View>> = default; _LIBCPP_HIDE_FROM_ABI - constexpr __filter_view_iterator(__filter_view& __parent, iterator_t<_View> __current) + constexpr __iterator(filter_view& __parent, iterator_t<_View> __current) : __current_(std::move(__current)), __parent_(std::addressof(__parent)) { } @@ -171,7 +160,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __filter_view_iterator& operator++() { + constexpr __iterator& operator++() { __current_ = ranges::find_if(std::move(++__current_), ranges::end(__parent_->__base_), std::ref(*__parent_->__pred_)); return *this; @@ -179,42 +168,42 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; } _LIBCPP_HIDE_FROM_ABI - constexpr __filter_view_iterator operator++(int) requires forward_range<_View> { + constexpr __iterator operator++(int) requires forward_range<_View> { auto __tmp = *this; ++*this; return __tmp; } _LIBCPP_HIDE_FROM_ABI - constexpr __filter_view_iterator& operator--() requires bidirectional_range<_View> { + constexpr __iterator& operator--() requires bidirectional_range<_View> { do { --__current_; } while (!std::invoke(*__parent_->__pred_, *__current_)); return *this; } _LIBCPP_HIDE_FROM_ABI - constexpr __filter_view_iterator operator--(int) requires bidirectional_range<_View> { - auto tmp = *this; + constexpr __iterator operator--(int) requires bidirectional_range<_View> { + auto __tmp = *this; --*this; - return tmp; + return __tmp; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(__filter_view_iterator const& __x, __filter_view_iterator const& __y) + friend constexpr bool operator==(__iterator const& __x, __iterator const& __y) requires equality_comparable<iterator_t<_View>> { return __x.__current_ == __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr range_rvalue_reference_t<_View> iter_move(__filter_view_iterator const& __it) + friend constexpr range_rvalue_reference_t<_View> iter_move(__iterator const& __it) noexcept(noexcept(ranges::iter_move(__it.__current_))) { return ranges::iter_move(__it.__current_); } _LIBCPP_HIDE_FROM_ABI - friend constexpr void iter_swap(__filter_view_iterator const& __x, __filter_view_iterator const& __y) + friend constexpr void iter_swap(__iterator const& __x, __iterator const& __y) noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) requires indirectly_swappable<iterator_t<_View>> { @@ -224,17 +213,15 @@ namespace ranges { template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires view<_View> && is_object_v<_Pred> - class __filter_view_sentinel { - using __filter_view = filter_view<_View, _Pred>; - + class filter_view<_View, _Pred>::__sentinel { public: sentinel_t<_View> __end_ = sentinel_t<_View>(); _LIBCPP_HIDE_FROM_ABI - __filter_view_sentinel() = default; + __sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __filter_view_sentinel(__filter_view& __parent) + constexpr explicit __sentinel(filter_view& __parent) : __end_(ranges::end(__parent.__base_)) { } @@ -242,7 +229,7 @@ namespace ranges { constexpr sentinel_t<_View> base() const { return __end_; } _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(__filter_view_iterator<_View, _Pred> const& __x, __filter_view_sentinel const& __y) { + operator==(__iterator const& __x, __sentinel const& __y) { return __x.__current_ == __y.__end_; } }; @@ -273,7 +260,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/from_range.h b/libcxx/include/__ranges/from_range.h new file mode 100644 index 000000000000..a6cb9e3d439e --- /dev/null +++ b/libcxx/include/__ranges/from_range.h @@ -0,0 +1,33 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_FROM_RANGE_H +#define _LIBCPP___RANGES_FROM_RANGE_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +struct from_range_t { + explicit from_range_t() = default; +}; + +inline constexpr from_range_t from_range{}; + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_FROM_RANGE_H diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h index 3654096b7e17..f372688abfda 100644 --- a/libcxx/include/__ranges/iota_view.h +++ b/libcxx/include/__ranges/iota_view.h @@ -27,12 +27,15 @@ #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> #include <__iterator/unreachable_sentinel.h> -#include <__ranges/copyable_box.h> #include <__ranges/enable_borrowed_range.h> +#include <__ranges/movable_box.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/type_identity.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -40,12 +43,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template<class _Int> struct __get_wider_signed { - static auto __call() { + consteval static auto __call() { if constexpr (sizeof(_Int) < sizeof(short)) return type_identity<short>{}; else if constexpr (sizeof(_Int) < sizeof(int)) return type_identity<int>{}; else if constexpr (sizeof(_Int) < sizeof(long)) return type_identity<long>{}; @@ -83,14 +86,6 @@ namespace ranges { { __j - __j } -> convertible_to<_IotaDiffT<_Iter>>; }; - template <weakly_incrementable _Start> - requires copyable<_Start> - struct __iota_view_iterator; - - template <weakly_incrementable _Start, semiregular _BoundSentinel> - requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start> - struct __iota_view_sentinel; - template<class> struct __iota_iterator_category {}; @@ -102,9 +97,212 @@ namespace ranges { template <weakly_incrementable _Start, semiregular _BoundSentinel = unreachable_sentinel_t> requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start> class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> { + struct __iterator : public __iota_iterator_category<_Start> { + friend class iota_view; + + using iterator_concept = + _If<__advanceable<_Start>, random_access_iterator_tag, + _If<__decrementable<_Start>, bidirectional_iterator_tag, + _If<incrementable<_Start>, forward_iterator_tag, + /*Else*/ input_iterator_tag>>>; + + using value_type = _Start; + using difference_type = _IotaDiffT<_Start>; + + _Start __value_ = _Start(); + + _LIBCPP_HIDE_FROM_ABI + __iterator() requires default_initializable<_Start> = default; + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __iterator(_Start __value) : __value_(std::move(__value)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) { + return __value_; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator++() { + ++__value_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr void operator++(int) { ++*this; } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator operator++(int) requires incrementable<_Start> { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator--() requires __decrementable<_Start> { + --__value_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator operator--(int) requires __decrementable<_Start> { + auto __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator+=(difference_type __n) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { + if (__n >= difference_type(0)) { + __value_ += static_cast<_Start>(__n); + } else { + __value_ -= static_cast<_Start>(-__n); + } + } else { + __value_ += __n; + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr __iterator& operator-=(difference_type __n) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { + if (__n >= difference_type(0)) { + __value_ -= static_cast<_Start>(__n); + } else { + __value_ += static_cast<_Start>(-__n); + } + } else { + __value_ -= __n; + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI + constexpr _Start operator[](difference_type __n) const + requires __advanceable<_Start> + { + return _Start(__value_ + __n); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + requires equality_comparable<_Start> + { + return __x.__value_ == __y.__value_; + } - using __iterator = __iota_view_iterator<_Start>; - using __sentinel = __iota_view_sentinel<_Start, _BoundSentinel>; + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return __x.__value_ < __y.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return __y < __x; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return !(__y < __x); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return !(__x < __y); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> && three_way_comparable<_Start> + { + return __x.__value_ <=> __y.__value_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator+(__iterator __i, difference_type __n) + requires __advanceable<_Start> + { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator+(difference_type __n, __iterator __i) + requires __advanceable<_Start> + { + return __i + __n; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr __iterator operator-(__iterator __i, difference_type __n) + requires __advanceable<_Start> + { + __i -= __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start>) { + if constexpr (__signed_integer_like<_Start>) { + return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_)); + } + if (__y.__value_ > __x.__value_) { + return difference_type(-difference_type(__y.__value_ - __x.__value_)); + } + return difference_type(__x.__value_ - __y.__value_); + } + return __x.__value_ - __y.__value_; + } + }; + + struct __sentinel { + friend class iota_view; + + private: + _BoundSentinel __bound_sentinel_ = _BoundSentinel(); + + public: + _LIBCPP_HIDE_FROM_ABI + __sentinel() = default; + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_BoundSentinel __bound_sentinel) + : __bound_sentinel_(std::move(__bound_sentinel)) {} + + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { + return __x.__value_ == __y.__bound_sentinel_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __sentinel& __y) + requires sized_sentinel_for<_BoundSentinel, _Start> + { + return __x.__value_ - __y.__bound_sentinel_; + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr iter_difference_t<_Start> operator-(const __sentinel& __x, const __iterator& __y) + requires sized_sentinel_for<_BoundSentinel, _Start> + { + return -(__y - __x); + } + }; _Start __value_ = _Start(); _BoundSentinel __bound_sentinel_ = _BoundSentinel(); @@ -117,28 +315,28 @@ namespace ranges { constexpr explicit iota_view(_Start __value) : __value_(std::move(__value)) { } _LIBCPP_HIDE_FROM_ABI - constexpr iota_view(type_identity_t<_Start> __value, type_identity_t<_BoundSentinel> __bound_sentinel) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(type_identity_t<_Start> __value, type_identity_t<_BoundSentinel> __bound_sentinel) : __value_(std::move(__value)), __bound_sentinel_(std::move(__bound_sentinel)) { // Validate the precondition if possible. if constexpr (totally_ordered_with<_Start, _BoundSentinel>) { - _LIBCPP_ASSERT(ranges::less_equal()(__value_, __bound_sentinel_), - "Precondition violated: value is greater than bound."); + _LIBCPP_ASSERT_UNCATEGORIZED(ranges::less_equal()(__value_, __bound_sentinel_), + "Precondition violated: value is greater than bound."); } } _LIBCPP_HIDE_FROM_ABI - constexpr iota_view(__iterator __first, __iterator __last) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __iterator __last) requires same_as<_Start, _BoundSentinel> : iota_view(std::move(__first.__value_), std::move(__last.__value_)) {} _LIBCPP_HIDE_FROM_ABI - constexpr iota_view(__iterator __first, _BoundSentinel __last) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, _BoundSentinel __last) requires same_as<_BoundSentinel, unreachable_sentinel_t> : iota_view(std::move(__first.__value_), std::move(__last)) {} _LIBCPP_HIDE_FROM_ABI - constexpr iota_view(__iterator __first, __sentinel __last) - requires(!same_as<_Start, _BoundSentinel> && !same_as<_Start, unreachable_sentinel_t>) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 iota_view(__iterator __first, __sentinel __last) + requires(!same_as<_Start, _BoundSentinel> && !same_as<_BoundSentinel, unreachable_sentinel_t>) : iota_view(std::move(__first.__value_), std::move(__last.__bound_sentinel_)) {} _LIBCPP_HIDE_FROM_ABI @@ -185,224 +383,6 @@ namespace ranges { template <class _Start, class _BoundSentinel> inline constexpr bool enable_borrowed_range<iota_view<_Start, _BoundSentinel>> = true; - template <weakly_incrementable _Start> - requires copyable<_Start> - struct __iota_view_iterator : public __iota_iterator_category<_Start> { - - template <weakly_incrementable _StartT, semiregular _BoundSentinelT> - requires __weakly_equality_comparable_with<_StartT, _BoundSentinelT> && copyable<_StartT> - friend class iota_view; - - using iterator_concept = - _If<__advanceable<_Start>, random_access_iterator_tag, - _If<__decrementable<_Start>, bidirectional_iterator_tag, - _If<incrementable<_Start>, forward_iterator_tag, - /*Else*/ input_iterator_tag>>>; - - using value_type = _Start; - using difference_type = _IotaDiffT<_Start>; - - _Start __value_ = _Start(); - - _LIBCPP_HIDE_FROM_ABI - __iota_view_iterator() requires default_initializable<_Start> = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __iota_view_iterator(_Start __value) : __value_(std::move(__value)) {} - - _LIBCPP_HIDE_FROM_ABI - constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) { - return __value_; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator& operator++() { - ++__value_; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr void operator++(int) { ++*this; } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator operator++(int) requires incrementable<_Start> { - auto __tmp = *this; - ++*this; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator& operator--() requires __decrementable<_Start> { - --__value_; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator operator--(int) requires __decrementable<_Start> { - auto __tmp = *this; - --*this; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator& operator+=(difference_type __n) - requires __advanceable<_Start> - { - if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { - if (__n >= difference_type(0)) { - __value_ += static_cast<_Start>(__n); - } else { - __value_ -= static_cast<_Start>(-__n); - } - } else { - __value_ += __n; - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr __iota_view_iterator& operator-=(difference_type __n) - requires __advanceable<_Start> - { - if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { - if (__n >= difference_type(0)) { - __value_ -= static_cast<_Start>(__n); - } else { - __value_ += static_cast<_Start>(-__n); - } - } else { - __value_ -= __n; - } - return *this; - } - - _LIBCPP_HIDE_FROM_ABI - constexpr _Start operator[](difference_type __n) const - requires __advanceable<_Start> - { - return _Start(__value_ + __n); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires equality_comparable<_Start> - { - return __x.__value_ == __y.__value_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires totally_ordered<_Start> - { - return __x.__value_ < __y.__value_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires totally_ordered<_Start> - { - return __y < __x; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<=(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires totally_ordered<_Start> - { - return !(__y < __x); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>=(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires totally_ordered<_Start> - { - return !(__x < __y); - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr auto operator<=>(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires totally_ordered<_Start> && three_way_comparable<_Start> - { - return __x.__value_ <=> __y.__value_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iota_view_iterator operator+(__iota_view_iterator __i, difference_type __n) - requires __advanceable<_Start> - { - __i += __n; - return __i; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iota_view_iterator operator+(difference_type __n, __iota_view_iterator __i) - requires __advanceable<_Start> - { - return __i + __n; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr __iota_view_iterator operator-(__iota_view_iterator __i, difference_type __n) - requires __advanceable<_Start> - { - __i -= __n; - return __i; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr difference_type operator-(const __iota_view_iterator& __x, const __iota_view_iterator& __y) - requires __advanceable<_Start> - { - if constexpr (__integer_like<_Start>) { - if constexpr (__signed_integer_like<_Start>) { - return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_)); - } - if (__y.__value_ > __x.__value_) { - return difference_type(-difference_type(__y.__value_ - __x.__value_)); - } - return difference_type(__x.__value_ - __y.__value_); - } - return __x.__value_ - __y.__value_; - } - }; - - template <weakly_incrementable _Start, semiregular _BoundSentinel> - requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start> - struct __iota_view_sentinel { - - template <weakly_incrementable _StartT, semiregular _BoundSentinelT> - requires __weakly_equality_comparable_with<_StartT, _BoundSentinelT> && copyable<_StartT> - friend class iota_view; - - using __iterator = __iota_view_iterator<_Start>; - - private: - _BoundSentinel __bound_sentinel_ = _BoundSentinel(); - - public: - _LIBCPP_HIDE_FROM_ABI - __iota_view_sentinel() = default; - constexpr explicit __iota_view_sentinel(_BoundSentinel __bound_sentinel) : __bound_sentinel_(std::move(__bound_sentinel)) {} - - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator& __x, const __iota_view_sentinel& __y) { - return __x.__value_ == __y.__bound_sentinel_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __iota_view_sentinel& __y) - requires sized_sentinel_for<_BoundSentinel, _Start> - { - return __x.__value_ - __y.__bound_sentinel_; - } - - _LIBCPP_HIDE_FROM_ABI - friend constexpr iter_difference_t<_Start> operator-(const __iota_view_sentinel& __x, const __iterator& __y) - requires sized_sentinel_for<_BoundSentinel, _Start> - { - return -(__y - __x); - } - }; - namespace views { namespace __iota { struct __fn { @@ -427,7 +407,7 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/istream_view.h b/libcxx/include/__ranges/istream_view.h index 69a9df35a4d2..66cd91527616 100644 --- a/libcxx/include/__ranges/istream_view.h +++ b/libcxx/include/__ranges/istream_view.h @@ -36,18 +36,10 @@ namespace ranges { template <class _Val, class _CharT, class _Traits> concept __stream_extractable = requires(basic_istream<_CharT, _Traits>& __is, _Val& __t) { __is >> __t; }; -template <movable _Val, class _CharT, class _Traits> - requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> -class __basic_istream_view_iterator; - template <movable _Val, class _CharT, class _Traits = char_traits<_CharT>> requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> { - using __iterator = __basic_istream_view_iterator<_Val, _CharT, _Traits>; - - template <movable _ValueType, class _CharType, class _TraitsType> - requires default_initializable<_ValueType> && __stream_extractable<_ValueType, _CharType, _TraitsType> - friend class __basic_istream_view_iterator; + class __iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit basic_istream_view(basic_istream<_CharT, _Traits>& __stream) @@ -67,23 +59,23 @@ private: template <movable _Val, class _CharT, class _Traits> requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits> -class __basic_istream_view_iterator { +class basic_istream_view<_Val, _CharT, _Traits>::__iterator { public: using iterator_concept = input_iterator_tag; using difference_type = ptrdiff_t; using value_type = _Val; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __basic_istream_view_iterator( + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator( basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept : __parent_(std::addressof(__parent)) {} - __basic_istream_view_iterator(const __basic_istream_view_iterator&) = delete; - _LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator(__basic_istream_view_iterator&&) = default; + __iterator(const __iterator&) = delete; + _LIBCPP_HIDE_FROM_ABI __iterator(__iterator&&) = default; - __basic_istream_view_iterator& operator=(const __basic_istream_view_iterator&) = delete; - _LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator& operator=(__basic_istream_view_iterator&&) = default; + __iterator& operator=(const __iterator&) = delete; + _LIBCPP_HIDE_FROM_ABI __iterator& operator=(__iterator&&) = default; - _LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI __iterator& operator++() { *__parent_->__stream_ >> __parent_->__value_; return *this; } @@ -92,7 +84,7 @@ public: _LIBCPP_HIDE_FROM_ABI _Val& operator*() const { return __parent_->__value_; } - _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __basic_istream_view_iterator& __x, default_sentinel_t) { + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __x, default_sentinel_t) { return !*__x.__get_parent_stream(); } diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h index 869540fc99c2..e6240dfd2580 100644 --- a/libcxx/include/__ranges/join_view.h +++ b/libcxx/include/__ranges/join_view.h @@ -22,6 +22,7 @@ #include <__iterator/iterator_traits.h> #include <__iterator/iterator_with_data.h> #include <__iterator/segmented_iterator.h> +#include <__memory/addressof.h> #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> @@ -29,10 +30,10 @@ #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> +#include <__type_traits/common_type.h> #include <__type_traits/maybe_const.h> #include <__utility/forward.h> #include <optional> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -40,7 +41,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +// Note: `join_view` is still marked experimental because there is an ABI-breaking change that affects `join_view` in +// the pipeline (https://isocpp.org/files/papers/D2770R0.html). +// TODO: make `join_view` non-experimental once D2770 is implemented. +#if _LIBCPP_STD_VER >= 20 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) namespace ranges { template<class> @@ -66,14 +70,6 @@ namespace ranges { >; }; - template <input_range _View, bool _Const> - requires view<_View> && input_range<range_reference_t<_View>> - struct __join_view_iterator; - - template <input_range _View, bool _Const> - requires view<_View> && input_range<range_reference_t<_View>> - struct __join_view_sentinel; - template<input_range _View> requires view<_View> && input_range<range_reference_t<_View>> class join_view @@ -81,19 +77,9 @@ namespace ranges { private: using _InnerRange = range_reference_t<_View>; - template<bool _Const> - using __iterator = __join_view_iterator<_View, _Const>; - - template<bool _Const> - using __sentinel = __join_view_sentinel<_View, _Const>; + template<bool> struct __iterator; - template <input_range _View2, bool _Const2> - requires view<_View2> && input_range<range_reference_t<_View2>> - friend struct __join_view_iterator; - - template <input_range _View2, bool _Const2> - requires view<_View2> && input_range<range_reference_t<_View2>> - friend struct __join_view_sentinel; + template<bool> struct __sentinel; template <class> friend struct std::__segmented_iterator_traits; @@ -164,12 +150,12 @@ namespace ranges { } }; - template<input_range _View, bool _Const> + template<input_range _View> requires view<_View> && input_range<range_reference_t<_View>> - struct __join_view_sentinel { - template<input_range _View2, bool> - requires view<_View2> && input_range<range_reference_t<_View2>> - friend struct __join_view_sentinel; + template<bool _Const> + struct join_view<_View>::__sentinel { + template<bool> + friend struct __sentinel; private: using _Parent = __maybe_const<_Const, join_view<_View>>; @@ -178,37 +164,42 @@ namespace ranges { public: _LIBCPP_HIDE_FROM_ABI - __join_view_sentinel() = default; + __sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __join_view_sentinel(_Parent& __parent) + constexpr explicit __sentinel(_Parent& __parent) : __end_(ranges::end(__parent.__base_)) {} _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_sentinel(__join_view_sentinel<_View, !_Const> __s) + constexpr __sentinel(__sentinel<!_Const> __s) requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> : __end_(std::move(__s.__end_)) {} template<bool _OtherConst> requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __join_view_iterator<_View, _OtherConst>& __x, const __join_view_sentinel& __y) { + friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __x.__outer_ == __y.__end_; } }; - template<input_range _View, bool _Const> + // https://reviews.llvm.org/D142811#inline-1383022 + // To simplify the segmented iterator traits specialization, + // make the iterator `final` + template<input_range _View> requires view<_View> && input_range<range_reference_t<_View>> - struct __join_view_iterator + template<bool _Const> + struct join_view<_View>::__iterator final : public __join_view_iterator_category<__maybe_const<_Const, _View>> { - template<input_range _View2, bool> - requires view<_View2> && input_range<range_reference_t<_View2>> - friend struct __join_view_iterator; + template<bool> + friend struct __iterator; template <class> friend struct std::__segmented_iterator_traits; + static constexpr bool __is_join_view_iterator = true; + private: using _Parent = __maybe_const<_Const, join_view<_View>>; using _Base = __maybe_const<_Const, _View>; @@ -243,7 +234,7 @@ namespace ranges { __inner_.reset(); } - _LIBCPP_HIDE_FROM_ABI constexpr __join_view_iterator(_Parent* __parent, _Outer __outer, _Inner __inner) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent* __parent, _Outer __outer, _Inner __inner) : __outer_(std::move(__outer)), __inner_(std::move(__inner)), __parent_(__parent) {} public: @@ -264,17 +255,17 @@ namespace ranges { range_difference_t<_Base>, range_difference_t<range_reference_t<_Base>>>; _LIBCPP_HIDE_FROM_ABI - __join_view_iterator() requires default_initializable<_Outer> = default; + __iterator() requires default_initializable<_Outer> = default; _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator(_Parent& __parent, _Outer __outer) + constexpr __iterator(_Parent& __parent, _Outer __outer) : __outer_(std::move(__outer)) , __parent_(std::addressof(__parent)) { __satisfy(); } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator(__join_view_iterator<_View, !_Const> __i) + constexpr __iterator(__iterator<!_Const> __i) requires _Const && convertible_to<iterator_t<_View>, _Outer> && convertible_to<iterator_t<_InnerRange>, _Inner> @@ -295,7 +286,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator& operator++() { + constexpr __iterator& operator++() { auto&& __inner = [&]() -> auto&& { if constexpr (__ref_is_glvalue) return *__outer_; @@ -315,7 +306,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator operator++(int) + constexpr __iterator operator++(int) requires __ref_is_glvalue && forward_range<_Base> && forward_range<range_reference_t<_Base>> @@ -326,7 +317,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator& operator--() + constexpr __iterator& operator--() requires __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && @@ -345,7 +336,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator operator--(int) + constexpr __iterator operator--(int) requires __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && @@ -357,7 +348,7 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __join_view_iterator& __x, const __join_view_iterator& __y) + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) requires __ref_is_glvalue && equality_comparable<iterator_t<_Base>> && equality_comparable<iterator_t<range_reference_t<_Base>>> @@ -366,14 +357,14 @@ namespace ranges { } _LIBCPP_HIDE_FROM_ABI - friend constexpr decltype(auto) iter_move(const __join_view_iterator& __i) + friend constexpr decltype(auto) iter_move(const __iterator& __i) noexcept(noexcept(ranges::iter_move(*__i.__inner_))) { return ranges::iter_move(*__i.__inner_); } _LIBCPP_HIDE_FROM_ABI - friend constexpr void iter_swap(const __join_view_iterator& __x, const __join_view_iterator& __y) + friend constexpr void iter_swap(const __iterator& __x, const __iterator& __y) noexcept(noexcept(ranges::iter_swap(*__x.__inner_, *__y.__inner_))) requires indirectly_swappable<_Inner> { @@ -401,12 +392,12 @@ inline namespace __cpo { } // namespace views } // namespace ranges -template <class _View, bool _Const> - requires(ranges::common_range<typename ranges::__join_view_iterator<_View, _Const>::_Parent> && - __is_cpp17_random_access_iterator<typename ranges::__join_view_iterator<_View, _Const>::_Outer>::value && - __is_cpp17_random_access_iterator<typename ranges::__join_view_iterator<_View, _Const>::_Inner>::value) -struct __segmented_iterator_traits<ranges::__join_view_iterator<_View, _Const>> { - using _JoinViewIterator = ranges::__join_view_iterator<_View, _Const>; +template <class _JoinViewIterator> + requires(_JoinViewIterator::__is_join_view_iterator && + ranges::common_range<typename _JoinViewIterator::_Parent> && + __has_random_access_iterator_category<typename _JoinViewIterator::_Outer>::value && + __has_random_access_iterator_category<typename _JoinViewIterator::_Inner>::value) +struct __segmented_iterator_traits<_JoinViewIterator> { using __segment_iterator = _LIBCPP_NODEBUG __iterator_with_data<typename _JoinViewIterator::_Outer, typename _JoinViewIterator::_Parent*>; @@ -445,7 +436,7 @@ struct __segmented_iterator_traits<ranges::__join_view_iterator<_View, _Const>> } }; -#endif // _LIBCPP_STD_VER > 17 +#endif // #if _LIBCPP_STD_VER >= 20 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h index 3a95075884b9..04182a530fc5 100644 --- a/libcxx/include/__ranges/lazy_split_view.h +++ b/libcxx/include/__ranges/lazy_split_view.h @@ -12,6 +12,7 @@ #include <__algorithm/ranges_find.h> #include <__algorithm/ranges_mismatch.h> +#include <__assert> #include <__concepts/constructible.h> #include <__concepts/convertible_to.h> #include <__concepts/derived_from.h> @@ -34,10 +35,13 @@ #include <__ranges/single_view.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/maybe_const.h> +#include <__type_traits/remove_reference.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -45,7 +49,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -78,14 +82,14 @@ public: requires default_initializable<_View> && default_initializable<_Pattern> = default; _LIBCPP_HIDE_FROM_ABI - constexpr lazy_split_view(_View __base, _Pattern __pattern) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 lazy_split_view(_View __base, _Pattern __pattern) : __base_(std::move(__base)), __pattern_(std::move(__pattern)) {} template <input_range _Range> requires constructible_from<_View, views::all_t<_Range>> && constructible_from<_Pattern, single_view<range_value_t<_Range>>> _LIBCPP_HIDE_FROM_ABI - constexpr lazy_split_view(_Range&& __r, range_value_t<_Range> __e) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 lazy_split_view(_Range&& __r, range_value_t<_Range> __e) : __base_(views::all(std::forward<_Range>(__r))) , __pattern_(views::single(std::move(__e))) {} @@ -276,7 +280,7 @@ private: _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __outer_iterator& __x, default_sentinel_t) { - _LIBCPP_ASSERT(__x.__parent_, "Cannot call comparison on a default-constructed iterator."); + _LIBCPP_ASSERT_UNCATEGORIZED(__x.__parent_, "Cannot call comparison on a default-constructed iterator."); return __x.__current() == ranges::end(__x.__parent_base()) && !__x.__trailing_empty_; } }; @@ -307,7 +311,7 @@ private: _LIBCPP_HIDE_FROM_ABI constexpr bool __is_done() const { - _LIBCPP_ASSERT(__i_.__parent_, "Cannot call comparison on a default-constructed iterator."); + _LIBCPP_ASSERT_UNCATEGORIZED(__i_.__parent_, "Cannot call comparison on a default-constructed iterator."); auto [__pcur, __pend] = ranges::subrange{__i_.__parent_->__pattern_}; auto __end = ranges::end(__i_.__parent_->__base_); @@ -458,7 +462,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/movable_box.h b/libcxx/include/__ranges/movable_box.h new file mode 100644 index 000000000000..8b3716a06c5b --- /dev/null +++ b/libcxx/include/__ranges/movable_box.h @@ -0,0 +1,206 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_MOVABLE_BOX_H +#define _LIBCPP___RANGES_MOVABLE_BOX_H + +#include <__concepts/constructible.h> +#include <__concepts/copyable.h> +#include <__concepts/movable.h> +#include <__config> +#include <__memory/addressof.h> +#include <__memory/construct_at.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__utility/move.h> +#include <optional> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +// __movable_box allows turning a type that is move-constructible (but maybe not move-assignable) into +// a type that is both move-constructible and move-assignable. It does that by introducing an empty state +// and basically doing destroy-then-copy-construct in the assignment operator. The empty state is necessary +// to handle the case where the copy construction fails after destroying the object. +// +// In some cases, we can completely avoid the use of an empty state; we provide a specialization of +// __movable_box that does this, see below for the details. + +// until C++23, `__movable_box` was named `__copyable_box` and required the stored type to be copy-constructible, not +// just move-constructible; we preserve the old behavior in pre-C++23 modes. +template <class _Tp> +concept __movable_box_object = +# if _LIBCPP_STD_VER >= 23 + move_constructible<_Tp> +# else + copy_constructible<_Tp> +# endif + && is_object_v<_Tp>; + +namespace ranges { +// Primary template - uses std::optional and introduces an empty state in case assignment fails. +template <__movable_box_object _Tp> +class __movable_box { + _LIBCPP_NO_UNIQUE_ADDRESS optional<_Tp> __val_; + +public: + template <class... _Args> + requires is_constructible_v<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __movable_box(in_place_t, _Args&&... __args) noexcept( + is_nothrow_constructible_v<_Tp, _Args...>) + : __val_(in_place, std::forward<_Args>(__args)...) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) + requires default_initializable<_Tp> + : __val_(in_place) {} + + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box const&) = default; + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box&&) = default; + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& + operator=(__movable_box const& __other) noexcept(is_nothrow_copy_constructible_v<_Tp>) +# if _LIBCPP_STD_VER >= 23 + requires copy_constructible<_Tp> +# endif + { + if (this != std::addressof(__other)) { + if (__other.__has_value()) + __val_.emplace(*__other); + else + __val_.reset(); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __movable_box& operator=(__movable_box&&) + requires movable<_Tp> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& + operator=(__movable_box&& __other) noexcept(is_nothrow_move_constructible_v<_Tp>) { + if (this != std::addressof(__other)) { + if (__other.__has_value()) + __val_.emplace(std::move(*__other)); + else + __val_.reset(); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return *__val_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return *__val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { return __val_.operator->(); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { return __val_.operator->(); } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return __val_.has_value(); } +}; + +// This partial specialization implements an optimization for when we know we don't need to store +// an empty state to represent failure to perform an assignment. For copy-assignment, this happens: +// +// 1. If the type is copyable (which includes copy-assignment), we can use the type's own assignment operator +// directly and avoid using std::optional. +// 2. If the type is not copyable, but it is nothrow-copy-constructible, then we can implement assignment as +// destroy-and-then-construct and we know it will never fail, so we don't need an empty state. +// +// The exact same reasoning can be applied for move-assignment, with copyable replaced by movable and +// nothrow-copy-constructible replaced by nothrow-move-constructible. This specialization is enabled +// whenever we can apply any of these optimizations for both the copy assignment and the move assignment +// operator. + +# if _LIBCPP_STD_VER >= 23 +template <class _Tp> +concept __doesnt_need_empty_state = + (copy_constructible<_Tp> + // 1. If copy_constructible<T> is true, movable-box<T> should store only a T if either T models + // copyable, or is_nothrow_move_constructible_v<T> && is_nothrow_copy_constructible_v<T> is true. + ? copyable<_Tp> || (is_nothrow_move_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Tp>) + // 2. Otherwise, movable-box<T> should store only a T if either T models movable or + // is_nothrow_move_constructible_v<T> is true. + : movable<_Tp> || is_nothrow_move_constructible_v<_Tp>); +# else + +template <class _Tp> +concept __doesnt_need_empty_state_for_copy = copyable<_Tp> || is_nothrow_copy_constructible_v<_Tp>; + +template <class _Tp> +concept __doesnt_need_empty_state_for_move = movable<_Tp> || is_nothrow_move_constructible_v<_Tp>; + +template <class _Tp> +concept __doesnt_need_empty_state = __doesnt_need_empty_state_for_copy<_Tp> && __doesnt_need_empty_state_for_move<_Tp>; +# endif + +template <__movable_box_object _Tp> + requires __doesnt_need_empty_state<_Tp> +class __movable_box<_Tp> { + _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; + +public: + template <class... _Args> + requires is_constructible_v<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __movable_box(in_place_t, _Args&&... __args) noexcept( + is_nothrow_constructible_v<_Tp, _Args...>) + : __val_(std::forward<_Args>(__args)...) {} + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box() noexcept(is_nothrow_default_constructible_v<_Tp>) + requires default_initializable<_Tp> + : __val_() {} + + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box const&) = default; + _LIBCPP_HIDE_FROM_ABI __movable_box(__movable_box&&) = default; + + // Implementation of assignment operators in case we perform optimization (1) + _LIBCPP_HIDE_FROM_ABI __movable_box& operator=(__movable_box const&) + requires copyable<_Tp> + = default; + _LIBCPP_HIDE_FROM_ABI __movable_box& operator=(__movable_box&&) + requires movable<_Tp> + = default; + + // Implementation of assignment operators in case we perform optimization (2) + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& operator=(__movable_box const& __other) noexcept { + static_assert(is_nothrow_copy_constructible_v<_Tp>); + if (this != std::addressof(__other)) { + std::destroy_at(std::addressof(__val_)); + std::construct_at(std::addressof(__val_), __other.__val_); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __movable_box& operator=(__movable_box&& __other) noexcept { + static_assert(is_nothrow_move_constructible_v<_Tp>); + if (this != std::addressof(__other)) { + std::destroy_at(std::addressof(__val_)); + std::construct_at(std::addressof(__val_), std::move(__other.__val_)); + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return __val_; } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return __val_; } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { return std::addressof(__val_); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { return std::addressof(__val_); } + + _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return true; } +}; +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_MOVABLE_BOX_H diff --git a/libcxx/include/__ranges/non_propagating_cache.h b/libcxx/include/__ranges/non_propagating_cache.h index d50c577fc30f..f5223962049c 100644 --- a/libcxx/include/__ranges/non_propagating_cache.h +++ b/libcxx/include/__ranges/non_propagating_cache.h @@ -16,7 +16,6 @@ #include <__memory/addressof.h> #include <__utility/forward.h> #include <optional> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -24,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { // __non_propagating_cache is a helper type that allows storing an optional value in it, @@ -44,10 +43,11 @@ namespace ranges { // This helper class is needed to perform copy and move elision when // constructing the contained type from an iterator. struct __wrapper { - template<class ..._Args> - constexpr explicit __wrapper(__forward_tag, _Args&& ...__args) : __t_(std::forward<_Args>(__args)...) { } - template<class _Fn> - constexpr explicit __wrapper(__from_tag, _Fn const& __f) : __t_(__f()) { } + template <class... _Args> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __wrapper(__forward_tag, _Args&&... __args) + : __t_(std::forward<_Args>(__args)...) {} + template <class _Fn> + _LIBCPP_HIDE_FROM_ABI constexpr explicit __wrapper(__from_tag, _Fn const& __f) : __t_(__f()) {} _Tp __t_; }; @@ -107,7 +107,7 @@ namespace ranges { struct __empty_cache { }; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/owning_view.h b/libcxx/include/__ranges/owning_view.h index e150f6d9f248..c846de899b3f 100644 --- a/libcxx/include/__ranges/owning_view.h +++ b/libcxx/include/__ranges/owning_view.h @@ -20,16 +20,19 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> +#include <__type_traits/remove_cvref.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template<range _Rp> @@ -38,11 +41,11 @@ namespace ranges { _Rp __r_ = _Rp(); public: - owning_view() requires default_initializable<_Rp> = default; + _LIBCPP_HIDE_FROM_ABI owning_view() requires default_initializable<_Rp> = default; _LIBCPP_HIDE_FROM_ABI constexpr owning_view(_Rp&& __r) : __r_(std::move(__r)) {} - owning_view(owning_view&&) = default; - owning_view& operator=(owning_view&&) = default; + _LIBCPP_HIDE_FROM_ABI owning_view(owning_view&&) = default; + _LIBCPP_HIDE_FROM_ABI owning_view& operator=(owning_view&&) = default; _LIBCPP_HIDE_FROM_ABI constexpr _Rp& base() & noexcept { return __r_; } _LIBCPP_HIDE_FROM_ABI constexpr const _Rp& base() const& noexcept { return __r_; } @@ -76,8 +79,10 @@ public: } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___RANGES_OWNING_VIEW_H diff --git a/libcxx/include/__ranges/range_adaptor.h b/libcxx/include/__ranges/range_adaptor.h index 37e48179e378..2688e4cd0437 100644 --- a/libcxx/include/__ranges/range_adaptor.h +++ b/libcxx/include/__ranges/range_adaptor.h @@ -18,17 +18,22 @@ #include <__functional/compose.h> #include <__functional/invoke.h> #include <__ranges/concepts.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // CRTP base that one can derive from in order to be considered a range adaptor closure // by the library. When deriving from this class, a pipe operator will be provided to @@ -42,7 +47,7 @@ struct __range_adaptor_closure; // i.e. something that can be called via the `x | f` notation. template <class _Fn> struct __range_adaptor_closure_t : _Fn, __range_adaptor_closure<__range_adaptor_closure_t<_Fn>> { - constexpr explicit __range_adaptor_closure_t(_Fn&& __f) : _Fn(std::move(__f)) { } + _LIBCPP_HIDE_FROM_ABI constexpr explicit __range_adaptor_closure_t(_Fn&& __f) : _Fn(std::move(__f)) { } }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__range_adaptor_closure_t); @@ -70,8 +75,10 @@ struct __range_adaptor_closure { { return __range_adaptor_closure_t(std::__compose(std::forward<_OtherClosure>(__c2), std::forward<_Closure>(__c1))); } }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___RANGES_RANGE_ADAPTOR_H diff --git a/libcxx/include/__ranges/rbegin.h b/libcxx/include/__ranges/rbegin.h index 26b47321de93..1ceb1116d695 100644 --- a/libcxx/include/__ranges/rbegin.h +++ b/libcxx/include/__ranges/rbegin.h @@ -17,8 +17,11 @@ #include <__iterator/readable_traits.h> #include <__iterator/reverse_iterator.h> #include <__ranges/access.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> #include <__utility/auto_cast.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [ranges.access.rbegin] @@ -124,7 +127,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/ref_view.h b/libcxx/include/__ranges/ref_view.h index 1e5f7466f321..be32b8124202 100644 --- a/libcxx/include/__ranges/ref_view.h +++ b/libcxx/include/__ranges/ref_view.h @@ -24,8 +24,9 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> +#include <__type_traits/is_object.h> +#include <__utility/declval.h> #include <__utility/forward.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -33,7 +34,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template<range _Range> @@ -81,7 +82,7 @@ public: inline constexpr bool enable_borrowed_range<ref_view<_Tp>> = true; } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/rend.h b/libcxx/include/__ranges/rend.h index d2987e9fa8c3..7ee574ccfa67 100644 --- a/libcxx/include/__ranges/rend.h +++ b/libcxx/include/__ranges/rend.h @@ -18,8 +18,11 @@ #include <__iterator/reverse_iterator.h> #include <__ranges/access.h> #include <__ranges/rbegin.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> #include <__utility/auto_cast.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -27,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // [range.access.rend] @@ -128,7 +131,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/repeat_view.h b/libcxx/include/__ranges/repeat_view.h new file mode 100644 index 000000000000..fddf4baac89a --- /dev/null +++ b/libcxx/include/__ranges/repeat_view.h @@ -0,0 +1,260 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_REPEAT_VIEW_H +#define _LIBCPP___RANGES_REPEAT_VIEW_H + +#include <__concepts/constructible.h> +#include <__concepts/same_as.h> +#include <__concepts/semiregular.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/unreachable_sentinel.h> +#include <__memory/addressof.h> +#include <__ranges/iota_view.h> +#include <__ranges/movable_box.h> +#include <__ranges/view_interface.h> +#include <__type_traits/is_object.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/remove_cv.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include <__utility/piecewise_construct.h> +#include <tuple> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +namespace ranges { + +template <class _Tp> +concept __integer_like_with_usable_difference_type = + __signed_integer_like<_Tp> || (__integer_like<_Tp> && weakly_incrementable<_Tp>); + +template <class _Tp> +struct __repeat_view_iterator_difference { + using type = _IotaDiffT<_Tp>; +}; + +template <__signed_integer_like _Tp> +struct __repeat_view_iterator_difference<_Tp> { + using type = _Tp; +}; + +template <class _Tp> +using __repeat_view_iterator_difference_t = typename __repeat_view_iterator_difference<_Tp>::type; + +namespace views::__drop { +struct __fn; +} // namespace views::__drop + +namespace views::__take { +struct __fn; +} // namespace views::__take + +template <move_constructible _Tp, semiregular _Bound = unreachable_sentinel_t> + requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && + (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) +class repeat_view : public view_interface<repeat_view<_Tp, _Bound>> { + friend struct views::__take::__fn; + friend struct views::__drop::__fn; + class __iterator; + +public: + _LIBCPP_HIDE_FROM_ABI repeat_view() + requires default_initializable<_Tp> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(const _Tp& __value, _Bound __bound_sentinel = _Bound()) + requires copy_constructible<_Tp> + : __value_(in_place, __value), __bound_(__bound_sentinel) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__bound_ >= 0, "The value of bound must be greater than or equal to 0"); + } + + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view(_Tp&& __value, _Bound __bound_sentinel = _Bound()) + : __value_(in_place, std::move(__value)), __bound_(__bound_sentinel) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__bound_ >= 0, "The value of bound must be greater than or equal to 0"); + } + + template <class... _TpArgs, class... _BoundArgs> + requires(constructible_from<_Tp, _TpArgs...> && constructible_from<_Bound, _BoundArgs...>) + _LIBCPP_HIDE_FROM_ABI constexpr explicit repeat_view( + piecewise_construct_t, tuple<_TpArgs...> __value_args, tuple<_BoundArgs...> __bound_args = tuple<>{}) + : __value_(in_place, std::make_from_tuple<_Tp>(std::move(__value_args))), + __bound_(std::make_from_tuple<_Bound>(std::move(__bound_args))) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT( + __bound_ >= 0, "The behavior is undefined if Bound is not unreachable_sentinel_t and bound is negative"); + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator begin() const { return __iterator(std::addressof(*__value_)); } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator end() const + requires(!same_as<_Bound, unreachable_sentinel_t>) + { + return __iterator(std::addressof(*__value_), __bound_); + } + + _LIBCPP_HIDE_FROM_ABI constexpr unreachable_sentinel_t end() const noexcept { return unreachable_sentinel; } + + _LIBCPP_HIDE_FROM_ABI constexpr auto size() const + requires(!same_as<_Bound, unreachable_sentinel_t>) + { + return std::__to_unsigned_like(__bound_); + } + +private: + __movable_box<_Tp> __value_; + _LIBCPP_NO_UNIQUE_ADDRESS _Bound __bound_ = _Bound(); +}; + +template <class _Tp, class _Bound> +repeat_view(_Tp, _Bound) -> repeat_view<_Tp, _Bound>; + +// [range.repeat.iterator] +template <move_constructible _Tp, semiregular _Bound> + requires(is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> && + (__integer_like_with_usable_difference_type<_Bound> || same_as<_Bound, unreachable_sentinel_t>)) +class repeat_view<_Tp, _Bound>::__iterator { + friend class repeat_view; + + using _IndexT = conditional_t<same_as<_Bound, unreachable_sentinel_t>, ptrdiff_t, _Bound>; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(const _Tp* __value, _IndexT __bound_sentinel = _IndexT()) + : __value_(__value), __current_(__bound_sentinel) {} + +public: + using iterator_concept = random_access_iterator_tag; + using iterator_category = random_access_iterator_tag; + using value_type = _Tp; + using difference_type = __repeat_view_iterator_difference_t<_IndexT>; + + _LIBCPP_HIDE_FROM_ABI __iterator() = default; + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const noexcept { return *__value_; } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { + ++__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { + auto __tmp = *this; + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ > 0, "The value of bound must be greater than or equal to 0"); + --__current_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) { + auto __tmp = *this; + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ + __n >= 0, "The value of bound must be greater than or equal to 0"); + __current_ += __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) { + if constexpr (!same_as<_Bound, unreachable_sentinel_t>) + _LIBCPP_ASSERT(__current_ - __n >= 0, "The value of bound must be greater than or equal to 0"); + __current_ -= __n; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](difference_type __n) const noexcept { return *(*this + __n); } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { + return __x.__current_ == __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) { + return __x.__current_ <=> __y.__current_; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n) { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, __iterator __i) { + __i += __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(__iterator __i, difference_type __n) { + __i -= __n; + return __i; + } + + _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) { + return static_cast<difference_type>(__x.__current_) - static_cast<difference_type>(__y.__current_); + } + +private: + const _Tp* __value_ = nullptr; + _IndexT __current_ = _IndexT(); +}; + +// clang-format off +namespace views { +namespace __repeat { +struct __fn { + template <class _Tp> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value) const + noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value)))) + -> decltype( ranges::repeat_view(std::forward<_Tp>(__value))) + { return ranges::repeat_view(std::forward<_Tp>(__value)); } + + + template <class _Tp, class _Bound> + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) const + noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)))) + -> decltype( ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel))) + { return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)); } +}; +} // namespace __repeat +// clang-format on + +inline namespace __cpo { +inline constexpr auto repeat = __repeat::__fn{}; +} // namespace __cpo +} // namespace views + +template <class _Tp> +inline constexpr bool __is_repeat_specialization = false; + +template <class _Tp, class _Bound> +inline constexpr bool __is_repeat_specialization<repeat_view<_Tp, _Bound>> = true; + +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_REPEAT_VIEW_H diff --git a/libcxx/include/__ranges/reverse_view.h b/libcxx/include/__ranges/reverse_view.h index d7b137805448..01d1b97b3ce2 100644 --- a/libcxx/include/__ranges/reverse_view.h +++ b/libcxx/include/__ranges/reverse_view.h @@ -24,9 +24,10 @@ #include <__ranges/size.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -34,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template<view _View> @@ -184,7 +185,7 @@ namespace ranges { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/single_view.h b/libcxx/include/__ranges/single_view.h index 5c4b91869c1c..5724e2d1b6d5 100644 --- a/libcxx/include/__ranges/single_view.h +++ b/libcxx/include/__ranges/single_view.h @@ -12,13 +12,15 @@ #include <__concepts/constructible.h> #include <__config> -#include <__ranges/copyable_box.h> +#include <__ranges/movable_box.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_object.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> -#include <type_traits> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,51 +28,51 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { - template<copy_constructible _Tp> - requires is_object_v<_Tp> - class single_view : public view_interface<single_view<_Tp>> { - __copyable_box<_Tp> __value_; - - public: - _LIBCPP_HIDE_FROM_ABI - single_view() requires default_initializable<_Tp> = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit single_view(const _Tp& __t) : __value_(in_place, __t) {} - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit single_view(_Tp&& __t) : __value_(in_place, std::move(__t)) {} - - template<class... _Args> - requires constructible_from<_Tp, _Args...> - _LIBCPP_HIDE_FROM_ABI - constexpr explicit single_view(in_place_t, _Args&&... __args) +# if _LIBCPP_STD_VER >= 23 +template <move_constructible _Tp> +# else +template <copy_constructible _Tp> +# endif + requires is_object_v<_Tp> +class single_view : public view_interface<single_view<_Tp>> { + __movable_box<_Tp> __value_; + +public: + _LIBCPP_HIDE_FROM_ABI single_view() + requires default_initializable<_Tp> + = default; + + _LIBCPP_HIDE_FROM_ABI constexpr explicit single_view(const _Tp& __t) +# if _LIBCPP_STD_VER >= 23 + requires copy_constructible<_Tp> +# endif + : __value_(in_place, __t) { + } + + _LIBCPP_HIDE_FROM_ABI constexpr explicit single_view(_Tp&& __t) : __value_(in_place, std::move(__t)) {} + + template <class... _Args> + requires constructible_from<_Tp, _Args...> + _LIBCPP_HIDE_FROM_ABI constexpr explicit single_view(in_place_t, _Args&&... __args) : __value_{in_place, std::forward<_Args>(__args)...} {} - _LIBCPP_HIDE_FROM_ABI - constexpr _Tp* begin() noexcept { return data(); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* begin() noexcept { return data(); } - _LIBCPP_HIDE_FROM_ABI - constexpr const _Tp* begin() const noexcept { return data(); } + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* begin() const noexcept { return data(); } - _LIBCPP_HIDE_FROM_ABI - constexpr _Tp* end() noexcept { return data() + 1; } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* end() noexcept { return data() + 1; } - _LIBCPP_HIDE_FROM_ABI - constexpr const _Tp* end() const noexcept { return data() + 1; } + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* end() const noexcept { return data() + 1; } - _LIBCPP_HIDE_FROM_ABI - static constexpr size_t size() noexcept { return 1; } + _LIBCPP_HIDE_FROM_ABI static constexpr size_t size() noexcept { return 1; } - _LIBCPP_HIDE_FROM_ABI - constexpr _Tp* data() noexcept { return __value_.operator->(); } + _LIBCPP_HIDE_FROM_ABI constexpr _Tp* data() noexcept { return __value_.operator->(); } - _LIBCPP_HIDE_FROM_ABI - constexpr const _Tp* data() const noexcept { return __value_.operator->(); } - }; + _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* data() const noexcept { return __value_.operator->(); } +}; template<class _Tp> single_view(_Tp) -> single_view<_Tp>; @@ -95,7 +97,7 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h index 0ac8d63063d4..f22dd1ff7b79 100644 --- a/libcxx/include/__ranges/size.h +++ b/libcxx/include/__ranges/size.h @@ -30,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template<class> @@ -141,7 +141,7 @@ inline namespace __cpo { } // namespace __cpo } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/split_view.h b/libcxx/include/__ranges/split_view.h index 9758ee935f29..a27ac4ef7a19 100644 --- a/libcxx/include/__ranges/split_view.h +++ b/libcxx/include/__ranges/split_view.h @@ -42,12 +42,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { -template <class _View, class _Pattern> -struct __split_view_iterator; - -template <class _View, class _Pattern> -struct __split_view_sentinel; - template <forward_range _View, forward_range _Pattern> requires view<_View> && view<_Pattern> && indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> @@ -59,13 +53,13 @@ private: _Cache __cached_begin_ = _Cache(); template <class, class> - friend struct __split_view_iterator; + friend struct __iterator; template <class, class> - friend struct __split_view_sentinel; + friend struct __sentinel; - using __iterator = __split_view_iterator<_View, _Pattern>; - using __sentinel = __split_view_sentinel<_View, _Pattern>; + struct __iterator; + struct __sentinel; _LIBCPP_HIDE_FROM_ABI constexpr subrange<iterator_t<_View>> __find_next(iterator_t<_View> __it) { auto [__begin, __end] = ranges::search(subrange(__it, ranges::end(__base_)), __pattern_); @@ -81,13 +75,14 @@ public: requires default_initializable<_View> && default_initializable<_Pattern> = default; - _LIBCPP_HIDE_FROM_ABI constexpr split_view(_View __base, _Pattern __pattern) + _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 split_view(_View __base, _Pattern __pattern) : __base_(std::move(__base)), __pattern_(std::move((__pattern))) {} template <forward_range _Range> requires constructible_from<_View, views::all_t<_Range>> && constructible_from<_Pattern, single_view<range_value_t<_Range>>> - _LIBCPP_HIDE_FROM_ABI constexpr split_view(_Range&& __range, range_value_t<_Range> __elem) + _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 + split_view(_Range&& __range, range_value_t<_Range> __elem) : __base_(views::all(std::forward<_Range>(__range))), __pattern_(views::single(std::move(__elem))) {} _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& @@ -120,16 +115,17 @@ split_view(_Range&&, _Pattern&&) -> split_view<views::all_t<_Range>, views::all_ template <forward_range _Range> split_view(_Range&&, range_value_t<_Range>) -> split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>; -template <class _View, class _Pattern> -struct __split_view_iterator { +template <forward_range _View, forward_range _Pattern> + requires view<_View> && view<_Pattern> && + indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> +struct split_view<_View, _Pattern>::__iterator { private: - split_view<_View, _Pattern>* __parent_ = nullptr; + split_view* __parent_ = nullptr; _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __cur_ = iterator_t<_View>(); _LIBCPP_NO_UNIQUE_ADDRESS subrange<iterator_t<_View>> __next_ = subrange<iterator_t<_View>>(); bool __trailing_empty_ = false; - template <class, class> - friend struct __split_view_sentinel; + friend struct __sentinel; public: using iterator_concept = forward_iterator_tag; @@ -137,9 +133,9 @@ public: using value_type = subrange<iterator_t<_View>>; using difference_type = range_difference_t<_View>; - _LIBCPP_HIDE_FROM_ABI __split_view_iterator() = default; + _LIBCPP_HIDE_FROM_ABI __iterator() = default; - _LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator( + _LIBCPP_HIDE_FROM_ABI constexpr __iterator( split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next) : __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {} @@ -147,7 +143,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return {__cur_, __next_.begin()}; } - _LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator& operator++() { + _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { __cur_ = __next_.begin(); if (__cur_ != ranges::end(__parent_->__base_)) { __cur_ = __next_.end(); @@ -163,36 +159,35 @@ public: return *this; } - _LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator operator++(int) { + _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) { auto __tmp = *this; ++*this; return __tmp; } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const __split_view_iterator& __x, const __split_view_iterator& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { return __x.__cur_ == __y.__cur_ && __x.__trailing_empty_ == __y.__trailing_empty_; } }; -template <class _View, class _Pattern> -struct __split_view_sentinel { +template <forward_range _View, forward_range _Pattern> + requires view<_View> && view<_Pattern> && + indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to> +struct split_view<_View, _Pattern>::__sentinel { private: _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_View> __end_ = sentinel_t<_View>(); - _LIBCPP_HIDE_FROM_ABI static constexpr bool - __equals(const __split_view_iterator<_View, _Pattern>& __x, const __split_view_sentinel& __y) { + _LIBCPP_HIDE_FROM_ABI static constexpr bool __equals(const __iterator& __x, const __sentinel& __y) { return __x.__cur_ == __y.__end_ && !__x.__trailing_empty_; } public: - _LIBCPP_HIDE_FROM_ABI __split_view_sentinel() = default; + _LIBCPP_HIDE_FROM_ABI __sentinel() = default; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __split_view_sentinel(split_view<_View, _Pattern>& __parent) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent) : __end_(ranges::end(__parent.__base_)) {} - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const __split_view_iterator<_View, _Pattern>& __x, const __split_view_sentinel& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { return __equals(__x, __y); } }; diff --git a/libcxx/include/__ranges/subrange.h b/libcxx/include/__ranges/subrange.h index 2d9e4cc7e55e..75f9284a582f 100644 --- a/libcxx/include/__ranges/subrange.h +++ b/libcxx/include/__ranges/subrange.h @@ -29,9 +29,9 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> -#include <__tuple_dir/pair_like.h> -#include <__tuple_dir/tuple_element.h> -#include <__tuple_dir/tuple_size.h> +#include <__tuple/pair_like.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_size.h> #include <__type_traits/conditional.h> #include <__type_traits/decay.h> #include <__type_traits/is_pointer.h> @@ -46,9 +46,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { template<class _From, class _To> @@ -82,7 +85,7 @@ namespace ranges { private: static constexpr bool _MustProvideSizeAtConstruction = !_StoreSize; // just to improve compiler diagnostics - struct _Empty { constexpr _Empty(auto) noexcept { } }; + struct _Empty { _LIBCPP_HIDE_FROM_ABI constexpr _Empty(auto) noexcept { } }; using _Size = conditional_t<_StoreSize, make_unsigned_t<iter_difference_t<_Iter>>, _Empty>; _LIBCPP_NO_UNIQUE_ADDRESS _Iter __begin_ = _Iter(); _LIBCPP_NO_UNIQUE_ADDRESS _Sent __end_ = _Sent(); @@ -105,7 +108,7 @@ namespace ranges { : __begin_(std::move(__iter)), __end_(std::move(__sent)), __size_(__n) { if constexpr (sized_sentinel_for<_Sent, _Iter>) - _LIBCPP_ASSERT((__end_ - __begin_) == static_cast<iter_difference_t<_Iter>>(__n), + _LIBCPP_ASSERT_UNCATEGORIZED((__end_ - __begin_) == static_cast<iter_difference_t<_Iter>>(__n), "std::ranges::subrange was passed an invalid size hint"); } @@ -284,8 +287,10 @@ struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> { using type = _Sp; }; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___RANGES_SUBRANGE_H diff --git a/libcxx/include/__ranges/take_view.h b/libcxx/include/__ranges/take_view.h index bea3862cd7c8..4204017d9249 100644 --- a/libcxx/include/__ranges/take_view.h +++ b/libcxx/include/__ranges/take_view.h @@ -31,14 +31,18 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/iota_view.h> #include <__ranges/range_adaptor.h> +#include <__ranges/repeat_view.h> #include <__ranges/size.h> #include <__ranges/subrange.h> #include <__ranges/view_interface.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/maybe_const.h> +#include <__type_traits/remove_cvref.h> #include <__utility/auto_cast.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -49,7 +53,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -64,9 +68,10 @@ public: _LIBCPP_HIDE_FROM_ABI take_view() requires default_initializable<_View> = default; - _LIBCPP_HIDE_FROM_ABI constexpr take_view(_View __base, range_difference_t<_View> __count) + _LIBCPP_HIDE_FROM_ABI + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 take_view(_View __base, range_difference_t<_View> __count) : __base_(std::move(__base)), __count_(__count) { - _LIBCPP_ASSERT(__count >= 0, "count has to be greater than or equal to zero"); + _LIBCPP_ASSERT_UNCATEGORIZED(__count >= 0, "count has to be greater than or equal to zero"); } _LIBCPP_HIDE_FROM_ABI @@ -297,6 +302,31 @@ struct __fn { *ranges::begin(__rng), *ranges::begin(__rng) + std::min<_Dist>(ranges::distance(__rng), std::forward<_Np>(__n)) ); } +// clang-format off +#if _LIBCPP_STD_VER >= 23 + // [range.take.overview]: the `repeat_view` "_RawRange models sized_range" case. + template <class _Range, + convertible_to<range_difference_t<_Range>> _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires(__is_repeat_specialization<_RawRange> && sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + noexcept(noexcept(views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))))) + -> decltype( views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n)))) + { return views::repeat(*__range.__value_, std::min<_Dist>(ranges::distance(__range), std::forward<_Np>(__n))); } + + // [range.take.overview]: the `repeat_view` "otherwise" case. + template <class _Range, + convertible_to<range_difference_t<_Range>> _Np, + class _RawRange = remove_cvref_t<_Range>, + class _Dist = range_difference_t<_Range>> + requires(__is_repeat_specialization<_RawRange> && !sized_range<_RawRange>) + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Np&& __n) const + noexcept(noexcept(views::repeat(*__range.__value_, static_cast<_Dist>(__n)))) + -> decltype( views::repeat(*__range.__value_, static_cast<_Dist>(__n))) + { return views::repeat(*__range.__value_, static_cast<_Dist>(__n)); } +#endif +// clang-format on // [range.take.overview]: the "otherwise" case. template <class _Range, convertible_to<range_difference_t<_Range>> _Np, @@ -304,6 +334,9 @@ struct __fn { // Note: without specifically excluding the other cases, GCC sees this overload as ambiguous with the other // overloads. requires (!(__is_empty_view<_RawRange> || +#if _LIBCPP_STD_VER >= 23 + __is_repeat_specialization<_RawRange> || +#endif (__is_iota_specialization<_RawRange> && sized_range<_RawRange> && random_access_range<_RawRange>) || @@ -334,7 +367,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/take_while_view.h b/libcxx/include/__ranges/take_while_view.h index 59c0a4f82889..b4bdd1865de1 100644 --- a/libcxx/include/__ranges/take_while_view.h +++ b/libcxx/include/__ranges/take_while_view.h @@ -20,7 +20,7 @@ #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> +#include <__ranges/movable_box.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> #include <__type_traits/decay.h> @@ -53,27 +53,21 @@ template <class _View, class _Pred> concept __take_while_const_is_range = range<const _View> && indirect_unary_predicate<const _Pred, iterator_t<const _View>>; -template <class, class, bool> -class __take_while_view_sentinel; - template <view _View, class _Pred> requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>> class take_while_view : public view_interface<take_while_view<_View, _Pred>> { - template <class, class, bool> - friend class __take_while_view_sentinel; - - template <bool _Const> - using __sentinel = __take_while_view_sentinel<_View, _Pred, _Const>; + template <bool> + class __sentinel; _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Pred> __pred_; public: _LIBCPP_HIDE_FROM_ABI take_while_view() requires default_initializable<_View> && default_initializable<_Pred> = default; - _LIBCPP_HIDE_FROM_ABI constexpr take_while_view(_View __base, _Pred __pred) + _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 take_while_view(_View __base, _Pred __pred) : __base_(std::move(__base)), __pred_(std::in_place, std::move(__pred)) {} _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& @@ -114,37 +108,37 @@ public: template <class _Range, class _Pred> take_while_view(_Range&&, _Pred) -> take_while_view<views::all_t<_Range>, _Pred>; -template <class _View, class _Pred, bool _Const> -class __take_while_view_sentinel { +template <view _View, class _Pred> + requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>> +template <bool _Const> +class take_while_view<_View, _Pred>::__sentinel { using _Base = __maybe_const<_Const, _View>; sentinel_t<_Base> __end_ = sentinel_t<_Base>(); const _Pred* __pred_ = nullptr; - template <class, class, bool> - friend class __take_while_view_sentinel; + friend class __sentinel<!_Const>; public: - _LIBCPP_HIDE_FROM_ABI __take_while_view_sentinel() = default; + _LIBCPP_HIDE_FROM_ABI __sentinel() = default; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __take_while_view_sentinel(sentinel_t<_Base> __end, const _Pred* __pred) + _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end, const _Pred* __pred) : __end_(std::move(__end)), __pred_(__pred) {} - _LIBCPP_HIDE_FROM_ABI constexpr __take_while_view_sentinel(__take_while_view_sentinel<_View, _Pred, !_Const> __s) + _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s) requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> : __end_(std::move(__s.__end_)), __pred_(__s.__pred_) {} _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; } - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const iterator_t<_Base>& __x, const __take_while_view_sentinel& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const iterator_t<_Base>& __x, const __sentinel& __y) { return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x); } template <bool _OtherConst = !_Const> requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __take_while_view_sentinel& __y) { + operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __sentinel& __y) { return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x); } }; diff --git a/libcxx/include/__ranges/to.h b/libcxx/include/__ranges/to.h new file mode 100644 index 000000000000..95c300bfa6f2 --- /dev/null +++ b/libcxx/include/__ranges/to.h @@ -0,0 +1,247 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_TO_H +#define _LIBCPP___RANGES_TO_H + +#include <__algorithm/ranges_copy.h> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/derived_from.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/bind_back.h> +#include <__iterator/back_insert_iterator.h> +#include <__iterator/insert_iterator.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/from_range.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/size.h> +#include <__ranges/transform_view.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_volatile.h> +#include <__type_traits/type_identity.h> +#include <__utility/declval.h> +#include <__utility/forward.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 23 + +namespace ranges { + +// TODO(clang-15): in the Standard, it's a `constexpr bool` variable, not a concept, but constexpr variables don't +// short-circuit properly on Clang 15 (fixed in later versions), so use a concept as a workaround. +template <class _Container> +concept __reservable_container = sized_range<_Container> && requires(_Container& __c, range_size_t<_Container> __n) { + __c.reserve(__n); + { __c.capacity() } -> same_as<decltype(__n)>; + { __c.max_size() } -> same_as<decltype(__n)>; +}; + +template <class _Container, class _Ref> +constexpr bool __container_insertable = requires(_Container& __c, _Ref&& __ref) { + requires( + requires { __c.push_back(std::forward<_Ref>(__ref)); } || + requires { __c.insert(__c.end(), std::forward<_Ref>(__ref)); }); +}; + +template <class _Ref, class _Container> +_LIBCPP_HIDE_FROM_ABI constexpr auto __container_inserter(_Container& __c) { + if constexpr (requires { __c.push_back(std::declval<_Ref>()); }) { + return std::back_inserter(__c); + } else { + return std::inserter(__c, __c.end()); + } +} + +// Note: making this a concept allows short-circuiting the second condition. +template <class _Container, class _Range> +concept __try_non_recursive_conversion = + !input_range<_Container> || convertible_to<range_reference_t<_Range>, range_value_t<_Container>>; + +template <class _Container, class _Range, class... _Args> +concept __constructible_from_iter_pair = + common_range<_Range> && requires { typename iterator_traits<iterator_t<_Range>>::iterator_category; } && + derived_from<typename iterator_traits<iterator_t<_Range>>::iterator_category, input_iterator_tag> && + constructible_from<_Container, iterator_t<_Range>, sentinel_t<_Range>, _Args...>; + +template <class> +concept __always_false = false; + +// `ranges::to` base template -- the `_Container` type is a simple type template parameter. +template <class _Container, input_range _Range, class... _Args> + requires(!view<_Container>) +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr _Container to(_Range&& __range, _Args&&... __args) { + // Mandates: C is a cv-unqualified class type. + static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const"); + static_assert( + !is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile"); + + // First see if the non-recursive case applies -- the conversion target is either: + // - a range with a convertible value type; + // - a non-range type which might support being created from the input argument(s) (e.g. an `optional`). + if constexpr (__try_non_recursive_conversion<_Container, _Range>) { + // Case 1 -- construct directly from the given range. + if constexpr (constructible_from<_Container, _Range, _Args...>) { + return _Container(std::forward<_Range>(__range), std::forward<_Args>(__args)...); + } + + // Case 2 -- construct using the `from_range_t` tagged constructor. + else if constexpr (constructible_from<_Container, from_range_t, _Range, _Args...>) { + return _Container(from_range, std::forward<_Range>(__range), std::forward<_Args>(__args)...); + } + + // Case 3 -- construct from a begin-end iterator pair. + else if constexpr (__constructible_from_iter_pair<_Container, _Range, _Args...>) { + return _Container(ranges::begin(__range), ranges::end(__range), std::forward<_Args>(__args)...); + } + + // Case 4 -- default-construct (or construct from the extra arguments) and insert, reserving the size if possible. + else if constexpr (constructible_from<_Container, _Args...> && + __container_insertable<_Container, range_reference_t<_Range>>) { + _Container __result(std::forward<_Args>(__args)...); + if constexpr (sized_range<_Range> && __reservable_container<_Container>) { + __result.reserve(static_cast<range_size_t<_Container>>(ranges::size(__range))); + } + + ranges::copy(__range, ranges::__container_inserter<range_reference_t<_Range>>(__result)); + + return __result; + + } else { + static_assert(__always_false<_Container>, "ranges::to: unable to convert to the given container type."); + } + + // Try the recursive case. + } else if constexpr (input_range<range_reference_t<_Range>>) { + return ranges::to<_Container>( + __range | views::transform([](auto&& __elem) { + return ranges::to<range_value_t<_Container>>(std::forward<decltype(__elem)>(__elem)); + }), + std::forward<_Args>(__args)...); + + } else { + static_assert(__always_false<_Container>, "ranges::to: unable to convert to the given container type."); + } +} + +template <class _Range> +struct __minimal_input_iterator { + using iterator_category = input_iterator_tag; + using value_type = range_value_t<_Range>; + using difference_type = ptrdiff_t; + using pointer = add_pointer_t<range_reference_t<_Range>>; + using reference = range_reference_t<_Range>; + + reference operator*() const; + pointer operator->() const; + __minimal_input_iterator& operator++(); + __minimal_input_iterator operator++(int); + bool operator==(const __minimal_input_iterator&) const; +}; + +// Deduces the full type of the container from the given template template parameter. +template <template <class...> class _Container, input_range _Range, class... _Args> +struct _Deducer { + _LIBCPP_HIDE_FROM_ABI static constexpr auto __deduce_func() { + using _InputIter = __minimal_input_iterator<_Range>; + + // Case 1 -- can construct directly from the given range. + if constexpr (requires { _Container(std::declval<_Range>(), std::declval<_Args>()...); }) { + using _Result = decltype( // + _Container(std::declval<_Range>(), std::declval<_Args>()...)); + return type_identity<_Result>{}; + + // Case 2 -- can construct from the given range using the `from_range_t` tagged constructor. + } else if constexpr ( // + requires { _Container(from_range, std::declval<_Range>(), std::declval<_Args>()...); }) { + using _Result = // + decltype(_Container(from_range, std::declval<_Range>(), std::declval<_Args>()...)); + return type_identity<_Result>{}; + + // Case 3 -- can construct from a begin-end iterator pair. + } else if constexpr ( // + requires { _Container(std::declval<_InputIter>(), std::declval<_InputIter>(), std::declval<_Args>()...); }) { + using _Result = + decltype(_Container(std::declval<_InputIter>(), std::declval<_InputIter>(), std::declval<_Args>()...)); + return type_identity<_Result>{}; + + } else { + static_assert(__always_false<_Range>, + "ranges::to: unable to deduce the container type from the template template argument."); + } + } + + using type = typename decltype(__deduce_func())::type; +}; + +// `ranges::to` specialization -- `_Container` is a template template parameter requiring deduction to figure out the +// container element type. +template <template <class...> class _Container, input_range _Range, class... _Args> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto to(_Range&& __range, _Args&&... __args) { + using _DeduceExpr = typename _Deducer<_Container, _Range, _Args...>::type; + return ranges::to<_DeduceExpr>(std::forward<_Range>(__range), std::forward<_Args>(__args)...); +} + +// Range adaptor closure object 1 -- wrapping the `ranges::to` version where `_Container` is a simple type template +// parameter. +template <class _Container, class... _Args> + requires(!view<_Container>) +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto to(_Args&&... __args) { + // Mandates: C is a cv-unqualified class type. + static_assert(!is_const_v<_Container>, "The target container cannot be const-qualified, please remove the const"); + static_assert( + !is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile"); + + auto __to_func = []<input_range _Range, class... _Tail>(_Range && __range, _Tail && ... __tail) + requires requires { // + /**/ ranges::to<_Container>(std::forward<_Range>(__range), std::forward<_Tail>(__tail)...); + } + { + return ranges::to<_Container>(std::forward<_Range>(__range), std::forward<_Tail>(__tail)...); + }; + + return __range_adaptor_closure_t(std::__bind_back(__to_func, std::forward<_Args>(__args)...)); +} + +// Range adaptor closure object 2 -- wrapping the `ranges::to` version where `_Container` is a template template +// parameter. +template <template <class...> class _Container, class... _Args> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto to(_Args&&... __args) { + // clang-format off + auto __to_func = []<input_range _Range, class... _Tail, + class _DeducedExpr = typename _Deducer<_Container, _Range, _Tail...>::type> + (_Range&& __range, _Tail&& ... __tail) + requires requires { // + /**/ ranges::to<_DeducedExpr>(std::forward<_Range>(__range), std::forward<_Tail>(__tail)...); + } + { + return ranges::to<_DeducedExpr>(std::forward<_Range>(__range), std::forward<_Tail>(__tail)...); + }; + // clang-format on + + return __range_adaptor_closure_t(std::__bind_back(__to_func, std::forward<_Args>(__args)...)); +} + +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_TO_H diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h index 66d9e80e6e61..3678f9d64f7b 100644 --- a/libcxx/include/__ranges/transform_view.h +++ b/libcxx/include/__ranges/transform_view.h @@ -20,22 +20,28 @@ #include <__config> #include <__functional/bind_back.h> #include <__functional/invoke.h> +#include <__functional/perfect_forward.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__memory/addressof.h> #include <__ranges/access.h> #include <__ranges/all.h> #include <__ranges/concepts.h> -#include <__ranges/copyable_box.h> #include <__ranges/empty.h> +#include <__ranges/movable_box.h> #include <__ranges/range_adaptor.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_reference.h> #include <__type_traits/maybe_const.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -43,7 +49,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -57,33 +63,17 @@ concept __transform_view_constraints = regular_invocable<_Fn&, range_reference_t<_View>> && __can_reference<invoke_result_t<_Fn&, range_reference_t<_View>>>; -template <input_range _View, copy_constructible _Function, bool _IsConst> - requires __transform_view_constraints<_View, _Function> -class __transform_view_iterator; - -template <input_range _View, copy_constructible _Function, bool _IsConst> - requires __transform_view_constraints<_View, _Function> -class __transform_view_sentinel; - -template<input_range _View, copy_constructible _Fn> +# if _LIBCPP_STD_VER >= 23 +template <input_range _View, move_constructible _Fn> +# else +template <input_range _View, copy_constructible _Fn> +# endif requires __transform_view_constraints<_View, _Fn> class transform_view : public view_interface<transform_view<_View, _Fn>> { + template<bool> class __iterator; + template<bool> class __sentinel; - template <bool _IsConst> - using __iterator = __transform_view_iterator<_View, _Fn, _IsConst>; - - template <bool _IsConst> - using __sentinel = __transform_view_sentinel<_View, _Fn, _IsConst>; - - template <input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_iterator; - - template <input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_sentinel; - - _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Fn> __func_; + _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Fn> __func_; _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); public: @@ -92,7 +82,7 @@ public: requires default_initializable<_View> && default_initializable<_Fn> = default; _LIBCPP_HIDE_FROM_ABI - constexpr transform_view(_View __base, _Fn __func) + constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 transform_view(_View __base, _Fn __func) : __func_(std::in_place, std::move(__func)), __base_(std::move(__base)) {} _LIBCPP_HIDE_FROM_ABI @@ -166,7 +156,7 @@ struct __transform_view_iterator_category_base<_View, _Fn> { using _Cat = typename iterator_traits<iterator_t<_View>>::iterator_category; using iterator_category = conditional_t< - is_lvalue_reference_v<invoke_result_t<_Fn&, range_reference_t<_View>>>, + is_reference_v<invoke_result_t<_Fn&, range_reference_t<_View>>>, conditional_t< derived_from<_Cat, contiguous_iterator_tag>, random_access_iterator_tag, @@ -176,23 +166,25 @@ struct __transform_view_iterator_category_base<_View, _Fn> { >; }; -template<input_range _View, copy_constructible _Fn, bool _Const> +# if _LIBCPP_STD_VER >= 23 +template <input_range _View, move_constructible _Fn> +# else +template <input_range _View, copy_constructible _Fn> +# endif requires __transform_view_constraints<_View, _Fn> -class __transform_view_iterator - : public __transform_view_iterator_category_base<_View, _Fn> { +template <bool _Const> +class transform_view<_View, _Fn>::__iterator : public __transform_view_iterator_category_base<_View, _Fn> { - using _Parent = __maybe_const<_Const, transform_view<_View, _Fn>>; + using _Parent = __maybe_const<_Const, transform_view>; using _Base = __maybe_const<_Const, _View>; _Parent *__parent_ = nullptr; - template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_iterator; + template<bool> + friend class transform_view<_View, _Fn>::__iterator; - template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_sentinel; + template<bool> + friend class transform_view<_View, _Fn>::__sentinel; public: iterator_t<_Base> __current_ = iterator_t<_Base>(); @@ -202,17 +194,17 @@ public: using difference_type = range_difference_t<_Base>; _LIBCPP_HIDE_FROM_ABI - __transform_view_iterator() requires default_initializable<iterator_t<_Base>> = default; + __iterator() requires default_initializable<iterator_t<_Base>> = default; _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator(_Parent& __parent, iterator_t<_Base> __current) + constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current) : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {} - // Note: `__i` should always be `__transform_view_iterator<false>`, but directly using - // `__transform_view_iterator<false>` is ill-formed when `_Const` is false + // Note: `__i` should always be `__iterator<false>`, but directly using + // `__iterator<false>` is ill-formed when `_Const` is false // (see http://wg21.link/class.copy.ctor#5). _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator(__transform_view_iterator<_View, _Fn, !_Const> __i) + constexpr __iterator(__iterator<!_Const> __i) requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> : __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {} @@ -234,7 +226,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator& operator++() { + constexpr __iterator& operator++() { ++__current_; return *this; } @@ -243,7 +235,7 @@ public: constexpr void operator++(int) { ++__current_; } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator operator++(int) + constexpr __iterator operator++(int) requires forward_range<_Base> { auto __tmp = *this; @@ -252,7 +244,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator& operator--() + constexpr __iterator& operator--() requires bidirectional_range<_Base> { --__current_; @@ -260,7 +252,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator operator--(int) + constexpr __iterator operator--(int) requires bidirectional_range<_Base> { auto __tmp = *this; @@ -269,7 +261,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator& operator+=(difference_type __n) + constexpr __iterator& operator+=(difference_type __n) requires random_access_range<_Base> { __current_ += __n; @@ -277,7 +269,7 @@ public: } _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_iterator& operator-=(difference_type __n) + constexpr __iterator& operator-=(difference_type __n) requires random_access_range<_Base> { __current_ -= __n; @@ -293,77 +285,77 @@ public: } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) requires equality_comparable<iterator_t<_Base>> { return __x.__current_ == __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __x.__current_ < __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __x.__current_ > __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<=(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __x.__current_ <= __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>=(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> { return __x.__current_ >= __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr auto operator<=>(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> { return __x.__current_ <=> __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __transform_view_iterator operator+(__transform_view_iterator __i, difference_type __n) + friend constexpr __iterator operator+(__iterator __i, difference_type __n) requires random_access_range<_Base> { - return __transform_view_iterator{*__i.__parent_, __i.__current_ + __n}; + return __iterator{*__i.__parent_, __i.__current_ + __n}; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __transform_view_iterator operator+(difference_type __n, __transform_view_iterator __i) + friend constexpr __iterator operator+(difference_type __n, __iterator __i) requires random_access_range<_Base> { - return __transform_view_iterator{*__i.__parent_, __i.__current_ + __n}; + return __iterator{*__i.__parent_, __i.__current_ + __n}; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __transform_view_iterator operator-(__transform_view_iterator __i, difference_type __n) + friend constexpr __iterator operator-(__iterator __i, difference_type __n) requires random_access_range<_Base> { - return __transform_view_iterator{*__i.__parent_, __i.__current_ - __n}; + return __iterator{*__i.__parent_, __i.__current_ - __n}; } _LIBCPP_HIDE_FROM_ABI - friend constexpr difference_type operator-(const __transform_view_iterator& __x, const __transform_view_iterator& __y) + friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> { return __x.__current_ - __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr decltype(auto) iter_move(const __transform_view_iterator& __i) + friend constexpr decltype(auto) iter_move(const __iterator& __i) noexcept(noexcept(*__i)) { if constexpr (is_lvalue_reference_v<decltype(*__i)>) @@ -373,37 +365,37 @@ public: } }; -template<input_range _View, copy_constructible _Fn, bool _Const> +# if _LIBCPP_STD_VER >= 23 +template <input_range _View, move_constructible _Fn> +# else +template <input_range _View, copy_constructible _Fn> +# endif requires __transform_view_constraints<_View, _Fn> -class __transform_view_sentinel { - using _Parent = __maybe_const<_Const, transform_view<_View, _Fn>>; +template <bool _Const> +class transform_view<_View, _Fn>::__sentinel { + using _Parent = __maybe_const<_Const, transform_view>; using _Base = __maybe_const<_Const, _View>; - template <bool _IsConst> - using __iterator = __transform_view_iterator<_View, _Fn, _IsConst>; - sentinel_t<_Base> __end_ = sentinel_t<_Base>(); - template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_iterator; + template<bool> + friend class transform_view<_View, _Fn>::__iterator; - template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst> - requires __transform_view_constraints<_ViewType, _FunctionType> - friend class __transform_view_sentinel; + template<bool> + friend class transform_view<_View, _Fn>::__sentinel; public: _LIBCPP_HIDE_FROM_ABI - __transform_view_sentinel() = default; + __sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __transform_view_sentinel(sentinel_t<_Base> __end) : __end_(__end) {} + constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {} - // Note: `__i` should always be `__transform_view_sentinel<false>`, but directly using - // `__transform_view_sentinel<false>` is ill-formed when `_Const` is false + // Note: `__i` should always be `__sentinel<false>`, but directly using + // `__sentinel<false>` is ill-formed when `_Const` is false // (see http://wg21.link/class.copy.ctor#5). _LIBCPP_HIDE_FROM_ABI - constexpr __transform_view_sentinel(__transform_view_sentinel<_View, _Fn, !_Const> __i) + constexpr __sentinel(__sentinel<!_Const> __i) requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> : __end_(std::move(__i.__end_)) {} @@ -413,7 +405,7 @@ public: template<bool _OtherConst> requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __transform_view_sentinel& __y) { + friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __x.__current_ == __y.__end_; } @@ -421,7 +413,7 @@ public: requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> - operator-(const __iterator<_OtherConst>& __x, const __transform_view_sentinel& __y) { + operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __x.__current_ - __y.__end_; } @@ -429,7 +421,7 @@ public: requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> - operator-(const __transform_view_sentinel& __x, const __iterator<_OtherConst>& __y) { + operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { return __x.__end_ - __y.__current_; } }; @@ -460,7 +452,7 @@ inline namespace __cpo { } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/view_interface.h b/libcxx/include/__ranges/view_interface.h index 5581eb9c732a..e548355d29a4 100644 --- a/libcxx/include/__ranges/view_interface.h +++ b/libcxx/include/__ranges/view_interface.h @@ -31,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -118,7 +118,7 @@ public: constexpr decltype(auto) front() requires forward_range<_D2> { - _LIBCPP_ASSERT(!empty(), + _LIBCPP_ASSERT_UNCATEGORIZED(!empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view."); return *ranges::begin(__derived()); } @@ -128,7 +128,7 @@ public: constexpr decltype(auto) front() const requires forward_range<const _D2> { - _LIBCPP_ASSERT(!empty(), + _LIBCPP_ASSERT_UNCATEGORIZED(!empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view."); return *ranges::begin(__derived()); } @@ -138,7 +138,7 @@ public: constexpr decltype(auto) back() requires bidirectional_range<_D2> && common_range<_D2> { - _LIBCPP_ASSERT(!empty(), + _LIBCPP_ASSERT_UNCATEGORIZED(!empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view."); return *ranges::prev(ranges::end(__derived())); } @@ -148,7 +148,7 @@ public: constexpr decltype(auto) back() const requires bidirectional_range<const _D2> && common_range<const _D2> { - _LIBCPP_ASSERT(!empty(), + _LIBCPP_ASSERT_UNCATEGORIZED(!empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view."); return *ranges::prev(ranges::end(__derived())); } @@ -170,7 +170,7 @@ public: } // namespace ranges -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/views.h b/libcxx/include/__ranges/views.h index d40c64ad8c02..906c4e46c343 100644 --- a/libcxx/include/__ranges/views.h +++ b/libcxx/include/__ranges/views.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 namespace ranges { @@ -28,7 +28,7 @@ namespace views { } namespace views = ranges::views; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__ranges/zip_view.h b/libcxx/include/__ranges/zip_view.h index 5624726e13ee..2fd1fb30475a 100644 --- a/libcxx/include/__ranges/zip_view.h +++ b/libcxx/include/__ranges/zip_view.h @@ -30,11 +30,13 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/make_unsigned.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/integer_sequence.h> #include <__utility/move.h> #include <tuple> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -45,7 +47,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 namespace ranges { @@ -77,7 +79,9 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_transform(_Fun&& __f, _Tuple&& __tu template <class _Fun, class _Tuple> _LIBCPP_HIDE_FROM_ABI constexpr void __tuple_for_each(_Fun&& __f, _Tuple&& __tuple) { std::apply( - [&]<class... _Types>(_Types&&... __elements) { (std::invoke(__f, std::forward<_Types>(__elements)), ...); }, + [&]<class... _Types>(_Types&&... __elements) { + (static_cast<void>(std::invoke(__f, std::forward<_Types>(__elements))), ...); + }, std::forward<_Tuple>(__tuple)); } @@ -503,7 +507,7 @@ inline namespace __cpo { } // namespace views } // namespace ranges -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer index 7d0beda277ad..6854f6a4b2f8 100644 --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -23,9 +23,18 @@ #include <__memory/compressed_pair.h> #include <__memory/pointer_traits.h> #include <__memory/swap_allocator.h> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/is_trivially_destructible.h> +#include <__type_traits/remove_reference.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <type_traits> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -44,139 +53,173 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp, class _Allocator = allocator<_Tp> > struct __split_buffer { -private: - __split_buffer(const __split_buffer&); - __split_buffer& operator=(const __split_buffer&); public: - typedef _Tp value_type; - typedef _Allocator allocator_type; - typedef __libcpp_remove_reference_t<allocator_type> __alloc_rr; - typedef allocator_traits<__alloc_rr> __alloc_traits; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef typename __alloc_traits::size_type size_type; - typedef typename __alloc_traits::difference_type difference_type; - typedef typename __alloc_traits::pointer pointer; - typedef typename __alloc_traits::const_pointer const_pointer; - typedef pointer iterator; - typedef const_pointer const_iterator; - - pointer __first_; - pointer __begin_; - pointer __end_; - __compressed_pair<pointer, allocator_type> __end_cap_; - - typedef __add_lvalue_reference_t<allocator_type> __alloc_ref; - typedef __add_lvalue_reference_t<allocator_type> __alloc_const_ref; - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __alloc_rr& __alloc() _NOEXCEPT {return __end_cap_.second();} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const __alloc_rr& __alloc() const _NOEXCEPT {return __end_cap_.second();} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT {return __end_cap_.first();} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT {return __end_cap_.first();} - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - __split_buffer() - _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - explicit __split_buffer(__alloc_rr& __a); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - explicit __split_buffer(const __alloc_rr& __a); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer(); - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c) - _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c, const __alloc_rr& __a); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer& operator=(__split_buffer&& __c) - _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && - is_nothrow_move_assignable<allocator_type>::value) || - !__alloc_traits::propagate_on_container_move_assignment::value); - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {return __begin_;} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {return __begin_;} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {return __end_;} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT {return __end_;} - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - void clear() _NOEXCEPT - {__destruct_at_end(__begin_);} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const {return static_cast<size_type>(__end_ - __begin_);} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const {return __end_ == __begin_;} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const {return static_cast<size_type>(__end_cap() - __first_);} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const {return static_cast<size_type>(__begin_ - __first_);} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const {return static_cast<size_type>(__end_cap() - __end_);} - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() {return *__begin_;} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const {return *__begin_;} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() {return *(__end_ - 1);} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const {return *(__end_ - 1);} - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(const_reference __x); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x); - template <class... _Args> - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args); - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() {__destruct_at_begin(__begin_+1);} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {__destruct_at_end(__end_-1);} - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x); - template <class _InputIter> - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> - __construct_at_end(_InputIter __first, _InputIter __last); - template <class _ForwardIterator> - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> - __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin) - {__destruct_at_begin(__new_begin, is_trivially_destructible<value_type>());} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - void __destruct_at_begin(pointer __new_begin, false_type); - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - void __destruct_at_begin(pointer __new_begin, true_type); - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - void __destruct_at_end(pointer __new_last) _NOEXCEPT - {__destruct_at_end(__new_last, false_type());} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT; - - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x) - _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| - __is_nothrow_swappable<__alloc_rr>::value); + using value_type = _Tp; + using allocator_type = _Allocator; + using __alloc_rr = __libcpp_remove_reference_t<allocator_type>; + using __alloc_traits = allocator_traits<__alloc_rr>; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = typename __alloc_traits::size_type; + using difference_type = typename __alloc_traits::difference_type; + using pointer = typename __alloc_traits::pointer; + using const_pointer = typename __alloc_traits::const_pointer; + using iterator = pointer; + using const_iterator = const_pointer; + + pointer __first_; + pointer __begin_; + pointer __end_; + __compressed_pair<pointer, allocator_type> __end_cap_; + + using __alloc_ref = __add_lvalue_reference_t<allocator_type>; + using __alloc_const_ref = __add_lvalue_reference_t<allocator_type>; + + __split_buffer(const __split_buffer&) = delete; + __split_buffer& operator=(const __split_buffer&) = delete; + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer() + _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) + : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __default_init_tag()) {} + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a) + : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) {} + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a) + : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) {} + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c) + _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c, const __alloc_rr& __a); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer& operator=(__split_buffer&& __c) + _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable<allocator_type>::value) || + !__alloc_traits::propagate_on_container_move_assignment::value); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer(); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __alloc_rr& __alloc() _NOEXCEPT { return __end_cap_.second(); } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const __alloc_rr& __alloc() const _NOEXCEPT { + return __end_cap_.second(); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT { return __end_cap_.first(); } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT { + return __end_cap_.first(); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __begin_; } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __begin_; } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __end_; } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __end_; } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(__begin_); } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const { + return static_cast<size_type>(__end_ - __begin_); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __end_ == __begin_; } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const { + return static_cast<size_type>(__end_cap() - __first_); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const { + return static_cast<size_type>(__begin_ - __first_); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const { + return static_cast<size_type>(__end_cap() - __end_); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__begin_; } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *__begin_; } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() { return *(__end_ - 1); } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const { return *(__end_ - 1); } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(const_reference __x); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x); + + template <class... _Args> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() { __destruct_at_begin(__begin_ + 1); } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() { __destruct_at_end(__end_ - 1); } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x); + + template <class _InputIter> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + __enable_if_t<__has_exactly_input_iterator_category<_InputIter>::value> + __construct_at_end(_InputIter __first, _InputIter __last); + + template <class _ForwardIterator> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value> + __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); + + template <class _Iterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last); + + template <class _Iterator> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __construct_at_end_with_size(_Iterator __first, size_type __n); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin) { + __destruct_at_begin(__new_begin, is_trivially_destructible<value_type>()); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin, false_type); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin, true_type); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last) _NOEXCEPT { + __destruct_at_end(__new_last, false_type()); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT; + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const; + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x) + _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable<__alloc_rr>::value); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const; private: - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - void __move_assign_alloc(__split_buffer& __c, true_type) - _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) - { - __alloc() = _VSTD::move(__c.__alloc()); - } + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer& __c, true_type) + _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) { + __alloc() = _VSTD::move(__c.__alloc()); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {} + + struct _ConstructTransaction { + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction( + pointer* __p, size_type __n) _NOEXCEPT + : __pos_(*__p), + __end_(*__p + __n), + __dest_(__p) {} - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT - {} - - struct _ConstructTransaction { - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT - : __pos_(*__p), __end_(*__p + __n), __dest_(__p) { - } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() { - *__dest_ = __pos_; - } - pointer __pos_; - const pointer __end_; - private: - pointer *__dest_; - }; + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() { *__dest_ = __pos_; } + + pointer __pos_; + const pointer __end_; + + private: + pointer* __dest_; + }; }; template <class _Tp, class _Allocator> @@ -241,9 +284,16 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_referen template <class _Tp, class _Allocator> template <class _InputIter> -_LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIter>::value> +_LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<__has_exactly_input_iterator_category<_InputIter>::value> __split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIter __last) { + __construct_at_end_with_sentinel(__first, __last); +} + +template <class _Tp, class _Allocator> +template <class _Iterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 +void __split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) { __alloc_rr& __a = this->__alloc(); for (; __first != __last; ++__first) { @@ -261,13 +311,19 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIt ++this->__end_; } } - template <class _Tp, class _Allocator> template <class _ForwardIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value> +_LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value> __split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) { - _ConstructTransaction __tx(&this->__end_, _VSTD::distance(__first, __last)); + __construct_at_end_with_size(__first, std::distance(__first, __last)); +} + +template <class _Tp, class _Allocator> +template <class _ForwardIterator> +_LIBCPP_CONSTEXPR_SINCE_CXX20 +void __split_buffer<_Tp, _Allocator>::__construct_at_end_with_size(_ForwardIterator __first, size_type __n) { + _ConstructTransaction __tx(&this->__end_, __n); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void) ++__first) { __alloc_traits::construct(this->__alloc(), _VSTD::__to_address(__tx.__pos_), *__first); @@ -330,31 +386,6 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __sta template <class _Tp, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 -inline -__split_buffer<_Tp, _Allocator>::__split_buffer() - _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) - : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __default_init_tag()) -{ -} - -template <class _Tp, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -inline -__split_buffer<_Tp, _Allocator>::__split_buffer(__alloc_rr& __a) - : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) -{ -} - -template <class _Tp, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -inline -__split_buffer<_Tp, _Allocator>::__split_buffer(const __alloc_rr& __a) - : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) -{ -} - -template <class _Tp, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::~__split_buffer() { clear(); @@ -463,10 +494,10 @@ __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT { if (capacity() > size()) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __split_buffer<value_type, __alloc_rr&> __t(size(), 0, __alloc()); __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_)); @@ -475,12 +506,12 @@ __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT _VSTD::swap(__begin_, __t.__begin_); _VSTD::swap(__end_, __t.__end_); _VSTD::swap(__end_cap(), __t.__end_cap()); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } diff --git a/libcxx/include/__std_mbstate_t.h b/libcxx/include/__std_mbstate_t.h new file mode 100644 index 000000000000..e79cc789fddf --- /dev/null +++ b/libcxx/include/__std_mbstate_t.h @@ -0,0 +1,29 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___STD_MBSTATE_T_H +#define _LIBCPP___STD_MBSTATE_T_H + +#include <__config> +#include <__mbstate_t.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// The goal of this header is to provide std::mbstate_t without requiring all +// of <cuchar> or <cwchar>. + +_LIBCPP_BEGIN_NAMESPACE_STD + +using ::mbstate_t _LIBCPP_USING_IF_EXISTS; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___STD_MBSTATE_T_H diff --git a/libcxx/include/__std_stream b/libcxx/include/__std_stream deleted file mode 100644 index e419e8c03af0..000000000000 --- a/libcxx/include/__std_stream +++ /dev/null @@ -1,361 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___STD_STREAM -#define _LIBCPP___STD_STREAM - -#include <__config> -#include <__locale> -#include <cstdio> -#include <istream> -#include <ostream> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - - -_LIBCPP_BEGIN_NAMESPACE_STD - -static const int __limit = 8; - -// __stdinbuf - -template <class _CharT> -class _LIBCPP_HIDDEN __stdinbuf - : public basic_streambuf<_CharT, char_traits<_CharT> > -{ -public: - typedef _CharT char_type; - typedef char_traits<char_type> traits_type; - typedef typename traits_type::int_type int_type; - typedef typename traits_type::pos_type pos_type; - typedef typename traits_type::off_type off_type; - typedef typename traits_type::state_type state_type; - - __stdinbuf(FILE* __fp, state_type* __st); - -protected: - virtual int_type underflow(); - virtual int_type uflow(); - virtual int_type pbackfail(int_type __c = traits_type::eof()); - virtual void imbue(const locale& __loc); - -private: - - FILE* __file_; - const codecvt<char_type, char, state_type>* __cv_; - state_type* __st_; - int __encoding_; - int_type __last_consumed_; - bool __last_consumed_is_next_; - bool __always_noconv_; - - __stdinbuf(const __stdinbuf&); - __stdinbuf& operator=(const __stdinbuf&); - - int_type __getchar(bool __consume); -}; - -template <class _CharT> -__stdinbuf<_CharT>::__stdinbuf(FILE* __fp, state_type* __st) - : __file_(__fp), - __st_(__st), - __last_consumed_(traits_type::eof()), - __last_consumed_is_next_(false) -{ - imbue(this->getloc()); -} - -template <class _CharT> -void -__stdinbuf<_CharT>::imbue(const locale& __loc) -{ - __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); - __encoding_ = __cv_->encoding(); - __always_noconv_ = __cv_->always_noconv(); - if (__encoding_ > __limit) - __throw_runtime_error("unsupported locale for standard input"); -} - -template <class _CharT> -typename __stdinbuf<_CharT>::int_type -__stdinbuf<_CharT>::underflow() -{ - return __getchar(false); -} - -template <class _CharT> -typename __stdinbuf<_CharT>::int_type -__stdinbuf<_CharT>::uflow() -{ - return __getchar(true); -} - -template <class _CharT> -typename __stdinbuf<_CharT>::int_type -__stdinbuf<_CharT>::__getchar(bool __consume) -{ - if (__last_consumed_is_next_) - { - int_type __result = __last_consumed_; - if (__consume) - { - __last_consumed_ = traits_type::eof(); - __last_consumed_is_next_ = false; - } - return __result; - } - char __extbuf[__limit]; - int __nread = _VSTD::max(1, __encoding_); - for (int __i = 0; __i < __nread; ++__i) - { - int __c = getc(__file_); - if (__c == EOF) - return traits_type::eof(); - __extbuf[__i] = static_cast<char>(__c); - } - char_type __1buf; - if (__always_noconv_) - __1buf = static_cast<char_type>(__extbuf[0]); - else - { - const char* __enxt; - char_type* __inxt; - codecvt_base::result __r; - do - { - state_type __sv_st = *__st_; - __r = __cv_->in(*__st_, __extbuf, __extbuf + __nread, __enxt, - &__1buf, &__1buf + 1, __inxt); - switch (__r) - { - case _VSTD::codecvt_base::ok: - break; - case codecvt_base::partial: - *__st_ = __sv_st; - if (__nread == sizeof(__extbuf)) - return traits_type::eof(); - { - int __c = getc(__file_); - if (__c == EOF) - return traits_type::eof(); - __extbuf[__nread] = static_cast<char>(__c); - } - ++__nread; - break; - case codecvt_base::error: - return traits_type::eof(); - case _VSTD::codecvt_base::noconv: - __1buf = static_cast<char_type>(__extbuf[0]); - break; - } - } while (__r == _VSTD::codecvt_base::partial); - } - if (!__consume) - { - for (int __i = __nread; __i > 0;) - { - if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF) - return traits_type::eof(); - } - } - else - __last_consumed_ = traits_type::to_int_type(__1buf); - return traits_type::to_int_type(__1buf); -} - -template <class _CharT> -typename __stdinbuf<_CharT>::int_type -__stdinbuf<_CharT>::pbackfail(int_type __c) -{ - if (traits_type::eq_int_type(__c, traits_type::eof())) - { - if (!__last_consumed_is_next_) - { - __c = __last_consumed_; - __last_consumed_is_next_ = !traits_type::eq_int_type(__last_consumed_, - traits_type::eof()); - } - return __c; - } - if (__last_consumed_is_next_) - { - char __extbuf[__limit]; - char* __enxt; - const char_type __ci = traits_type::to_char_type(__last_consumed_); - const char_type* __inxt; - switch (__cv_->out(*__st_, &__ci, &__ci + 1, __inxt, - __extbuf, __extbuf + sizeof(__extbuf), __enxt)) - { - case _VSTD::codecvt_base::ok: - break; - case _VSTD::codecvt_base::noconv: - __extbuf[0] = static_cast<char>(__last_consumed_); - __enxt = __extbuf + 1; - break; - case codecvt_base::partial: - case codecvt_base::error: - return traits_type::eof(); - } - while (__enxt > __extbuf) - if (ungetc(*--__enxt, __file_) == EOF) - return traits_type::eof(); - } - __last_consumed_ = __c; - __last_consumed_is_next_ = true; - return __c; -} - -// __stdoutbuf - -template <class _CharT> -class _LIBCPP_HIDDEN __stdoutbuf - : public basic_streambuf<_CharT, char_traits<_CharT> > -{ -public: - typedef _CharT char_type; - typedef char_traits<char_type> traits_type; - typedef typename traits_type::int_type int_type; - typedef typename traits_type::pos_type pos_type; - typedef typename traits_type::off_type off_type; - typedef typename traits_type::state_type state_type; - - __stdoutbuf(FILE* __fp, state_type* __st); - -protected: - virtual int_type overflow (int_type __c = traits_type::eof()); - virtual streamsize xsputn(const char_type* __s, streamsize __n); - virtual int sync(); - virtual void imbue(const locale& __loc); - -private: - FILE* __file_; - const codecvt<char_type, char, state_type>* __cv_; - state_type* __st_; - bool __always_noconv_; - - __stdoutbuf(const __stdoutbuf&); - __stdoutbuf& operator=(const __stdoutbuf&); -}; - -template <class _CharT> -__stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp, state_type* __st) - : __file_(__fp), - __cv_(&use_facet<codecvt<char_type, char, state_type> >(this->getloc())), - __st_(__st), - __always_noconv_(__cv_->always_noconv()) -{ -} - -template <class _CharT> -typename __stdoutbuf<_CharT>::int_type -__stdoutbuf<_CharT>::overflow(int_type __c) -{ - char __extbuf[__limit]; - char_type __1buf; - if (!traits_type::eq_int_type(__c, traits_type::eof())) - { - __1buf = traits_type::to_char_type(__c); - if (__always_noconv_) - { - if (fwrite(&__1buf, sizeof(char_type), 1, __file_) != 1) - return traits_type::eof(); - } - else - { - char* __extbe = __extbuf; - codecvt_base::result __r; - char_type* pbase = &__1buf; - char_type* pptr = pbase + 1; - do - { - const char_type* __e; - __r = __cv_->out(*__st_, pbase, pptr, __e, - __extbuf, - __extbuf + sizeof(__extbuf), - __extbe); - if (__e == pbase) - return traits_type::eof(); - if (__r == codecvt_base::noconv) - { - if (fwrite(pbase, 1, 1, __file_) != 1) - return traits_type::eof(); - } - else if (__r == codecvt_base::ok || __r == codecvt_base::partial) - { - size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); - if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) - return traits_type::eof(); - if (__r == codecvt_base::partial) - { - pbase = const_cast<char_type*>(__e); - } - } - else - return traits_type::eof(); - } while (__r == codecvt_base::partial); - } - } - return traits_type::not_eof(__c); -} - -template <class _CharT> -streamsize -__stdoutbuf<_CharT>::xsputn(const char_type* __s, streamsize __n) -{ - if (__always_noconv_) - return fwrite(__s, sizeof(char_type), __n, __file_); - streamsize __i = 0; - for (; __i < __n; ++__i, ++__s) - if (overflow(traits_type::to_int_type(*__s)) == traits_type::eof()) - break; - return __i; -} - -template <class _CharT> -int -__stdoutbuf<_CharT>::sync() -{ - char __extbuf[__limit]; - codecvt_base::result __r; - do - { - char* __extbe; - __r = __cv_->unshift(*__st_, __extbuf, - __extbuf + sizeof(__extbuf), - __extbe); - size_t __nmemb = static_cast<size_t>(__extbe - __extbuf); - if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) - return -1; - } while (__r == codecvt_base::partial); - if (__r == codecvt_base::error) - return -1; - if (fflush(__file_)) - return -1; - return 0; -} - -template <class _CharT> -void -__stdoutbuf<_CharT>::imbue(const locale& __loc) -{ - sync(); - __cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc); - __always_noconv_ = __cv_->always_noconv(); -} - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS - -#endif // _LIBCPP___STD_STREAM diff --git a/libcxx/include/__stop_token/atomic_unique_lock.h b/libcxx/include/__stop_token/atomic_unique_lock.h new file mode 100644 index 000000000000..6c63a254eab9 --- /dev/null +++ b/libcxx/include/__stop_token/atomic_unique_lock.h @@ -0,0 +1,139 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___STOP_TOKEN_ATOMIC_UNIQUE_GUARD_H +#define _LIBCPP___STOP_TOKEN_ATOMIC_UNIQUE_GUARD_H + +#include <__bit/popcount.h> +#include <__config> +#include <atomic> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +// This class implements an RAII unique_lock without a mutex. +// It uses std::atomic<State>, +// where State contains a lock bit and might contain other data, +// and LockedBit is the value of State when the lock bit is set, e.g 1 << 2 +template <class _State, _State _LockedBit> +class _LIBCPP_AVAILABILITY_SYNC __atomic_unique_lock { + static_assert(std::popcount(_LockedBit) == 1, "LockedBit must be an integer where only one bit is set"); + + std::atomic<_State>& __state_; + bool __is_locked_; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __atomic_unique_lock(std::atomic<_State>& __state) noexcept + : __state_(__state), __is_locked_(true) { + __lock(); + } + + template <class _Pred> + _LIBCPP_HIDE_FROM_ABI __atomic_unique_lock(std::atomic<_State>& __state, _Pred&& __give_up_locking) noexcept + : __state_(__state), __is_locked_(false) { + __is_locked_ = __lock_impl(__give_up_locking, __set_locked_bit, std::memory_order_acquire); + } + + template <class _Pred, class _UnaryFunction> + _LIBCPP_HIDE_FROM_ABI __atomic_unique_lock( + std::atomic<_State>& __state, + _Pred&& __give_up_locking, + _UnaryFunction&& __state_after_lock, + std::memory_order __locked_ordering) noexcept + : __state_(__state), __is_locked_(false) { + __is_locked_ = __lock_impl(__give_up_locking, __state_after_lock, __locked_ordering); + } + + __atomic_unique_lock(const __atomic_unique_lock&) = delete; + __atomic_unique_lock(__atomic_unique_lock&&) = delete; + __atomic_unique_lock& operator=(const __atomic_unique_lock&) = delete; + __atomic_unique_lock& operator=(__atomic_unique_lock&&) = delete; + + _LIBCPP_HIDE_FROM_ABI ~__atomic_unique_lock() { + if (__is_locked_) { + __unlock(); + } + } + + _LIBCPP_HIDE_FROM_ABI bool __owns_lock() const noexcept { return __is_locked_; } + + _LIBCPP_HIDE_FROM_ABI void __lock() noexcept { + const auto __never_give_up_locking = [](_State) { return false; }; + // std::memory_order_acquire because we'd like to make sure that all the read operations after the lock can read the + // up-to-date values. + __lock_impl(__never_give_up_locking, __set_locked_bit, std::memory_order_acquire); + __is_locked_ = true; + } + + _LIBCPP_HIDE_FROM_ABI void __unlock() noexcept { + // unset the _LockedBit. `memory_order_release` because we need to make sure all the write operations before calling + // `__unlock` will be made visible to other threads + __state_.fetch_and(static_cast<_State>(~_LockedBit), std::memory_order_release); + __state_.notify_all(); + __is_locked_ = false; + } + +private: + template <class _Pred, class _UnaryFunction> + _LIBCPP_HIDE_FROM_ABI bool + __lock_impl(_Pred&& __give_up_locking, // while trying to lock the state, if the predicate returns true, give up + // locking and return + _UnaryFunction&& __state_after_lock, + std::memory_order __locked_ordering) noexcept { + // At this stage, until we exit the inner while loop, other than the atomic state, we are not reading any order + // dependent values that is written on other threads, or writing anything that needs to be seen on other threads. + // Therefore `memory_order_relaxed` is enough. + _State __current_state = __state_.load(std::memory_order_relaxed); + do { + while (true) { + if (__give_up_locking(__current_state)) { + // user provided early return condition. fail to lock + return false; + } else if ((__current_state & _LockedBit) != 0) { + // another thread has locked the state, we need to wait + __state_.wait(__current_state, std::memory_order_relaxed); + // when it is woken up by notifyAll or spuriously, the __state_ + // might have changed. reload the state + // Note that the new state's _LockedBit may or may not equal to 0 + __current_state = __state_.load(std::memory_order_relaxed); + } else { + // at least for now, it is not locked. we can try `compare_exchange_weak` to lock it. + // Note that the variable `__current_state`'s lock bit has to be 0 at this point. + break; + } + } + } while (!__state_.compare_exchange_weak( + __current_state, // if __state_ has the same value of __current_state, lock bit must be zero before exchange and + // we are good to lock/exchange and return. If _state has a different value, because other + // threads locked it between the `break` statement above and this statement, exchange will fail + // and go back to the inner while loop above. + __state_after_lock(__current_state), // state after lock. Usually it should be __current_state | _LockedBit. + // Some use cases need to set other bits at the same time as an atomic + // operation therefore we accept a function + __locked_ordering, // sucessful exchange order. Usually it should be std::memory_order_acquire. + // Some use cases need more strict ordering therefore we accept it as a parameter + std::memory_order_relaxed // fail to exchange order. We don't need any ordering as we are going back to the + // inner while loop + )); + return true; + } + + _LIBCPP_HIDE_FROM_ABI static constexpr auto __set_locked_bit = [](_State __state) { return __state | _LockedBit; }; +}; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___STOP_TOKEN_ATOMIC_UNIQUE_GUARD_H diff --git a/libcxx/include/__stop_token/intrusive_list_view.h b/libcxx/include/__stop_token/intrusive_list_view.h new file mode 100644 index 000000000000..11a3e267e7c6 --- /dev/null +++ b/libcxx/include/__stop_token/intrusive_list_view.h @@ -0,0 +1,85 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___STOP_TOKEN_INTRUSIVE_LIST_VIEW_H +#define _LIBCPP___STOP_TOKEN_INTRUSIVE_LIST_VIEW_H + +#include <__assert> +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <class _Derived> +struct __intrusive_node_base { + _Derived* __next_ = nullptr; + _Derived* __prev_ = nullptr; +}; + +// This class is a view of underlying double-linked list. +// It does not own the nodes. It provides user-friendly +// operations on the linked list. +template <class _Node> +struct __intrusive_list_view { + _LIBCPP_HIDE_FROM_ABI __intrusive_list_view() = default; + _LIBCPP_HIDE_FROM_ABI __intrusive_list_view(__intrusive_list_view const&) = default; + _LIBCPP_HIDE_FROM_ABI __intrusive_list_view(__intrusive_list_view&&) = default; + _LIBCPP_HIDE_FROM_ABI __intrusive_list_view& operator=(__intrusive_list_view const&) = default; + _LIBCPP_HIDE_FROM_ABI __intrusive_list_view& operator=(__intrusive_list_view&&) = default; + _LIBCPP_HIDE_FROM_ABI ~__intrusive_list_view() = default; + + _LIBCPP_HIDE_FROM_ABI bool __empty() const noexcept { return __head_ == nullptr; } + + _LIBCPP_HIDE_FROM_ABI void __push_front(_Node* __node) noexcept { + __node->__next_ = __head_; + if (__head_) { + __head_->__prev_ = __node; + } + __head_ = __node; + } + + _LIBCPP_HIDE_FROM_ABI _Node* __pop_front() noexcept { + _Node* __front = __head_; + __head_ = __head_->__next_; + if (__head_) { + __head_->__prev_ = nullptr; + } + // OK not to set __front->__next_ = nullptr as __front is not part of the list anymore + return __front; + } + + _LIBCPP_HIDE_FROM_ABI void __remove(_Node* __node) noexcept { + if (__node->__prev_) { + // prev exists, set its next to our next to skip __node + __node->__prev_->__next_ = __node->__next_; + if (__node->__next_) { + __node->__next_->__prev_ = __node->__prev_; + } + } else { + _LIBCPP_ASSERT_INTERNAL(__node == __head_, "Node to be removed has no prev node, so it has to be the head"); + __pop_front(); + } + } + + _LIBCPP_HIDE_FROM_ABI bool __is_head(_Node* __node) noexcept { return __node == __head_; } + +private: + _Node* __head_ = nullptr; +}; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___STOP_TOKEN_INTRUSIVE_LIST_VIEW_H diff --git a/libcxx/include/__stop_token/intrusive_shared_ptr.h b/libcxx/include/__stop_token/intrusive_shared_ptr.h new file mode 100644 index 000000000000..f00cea5bc2b6 --- /dev/null +++ b/libcxx/include/__stop_token/intrusive_shared_ptr.h @@ -0,0 +1,134 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___STOP_TOKEN_INTRUSIVE_SHARED_PTR_H +#define _LIBCPP___STOP_TOKEN_INTRUSIVE_SHARED_PTR_H + +#include <__atomic/atomic.h> +#include <__atomic/memory_order.h> +#include <__config> +#include <__type_traits/is_reference.h> +#include <__utility/move.h> +#include <__utility/swap.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +// For intrusive_shared_ptr to work with a type T, specialize __intrusive_shared_ptr_traits<T> and implement +// the following function: +// +// static std::atomic<U>& __get_atomic_ref_count(T&); +// +// where U must be an integral type representing the number of references to the object. +template <class _Tp> +struct __intrusive_shared_ptr_traits; + +// A reference counting shared_ptr for types whose reference counter +// is stored inside the class _Tp itself. +// When the reference count goes to zero, the destructor of _Tp will be called +template <class _Tp> +struct __intrusive_shared_ptr { + _LIBCPP_HIDE_FROM_ABI __intrusive_shared_ptr() = default; + + _LIBCPP_HIDE_FROM_ABI explicit __intrusive_shared_ptr(_Tp* __raw_ptr) : __raw_ptr_(__raw_ptr) { + if (__raw_ptr_) + __increment_ref_count(*__raw_ptr_); + } + + _LIBCPP_HIDE_FROM_ABI __intrusive_shared_ptr(const __intrusive_shared_ptr& __other) noexcept + : __raw_ptr_(__other.__raw_ptr_) { + if (__raw_ptr_) + __increment_ref_count(*__raw_ptr_); + } + + _LIBCPP_HIDE_FROM_ABI __intrusive_shared_ptr(__intrusive_shared_ptr&& __other) noexcept + : __raw_ptr_(__other.__raw_ptr_) { + __other.__raw_ptr_ = nullptr; + } + + _LIBCPP_HIDE_FROM_ABI __intrusive_shared_ptr& operator=(const __intrusive_shared_ptr& __other) noexcept { + if (__other.__raw_ptr_ != __raw_ptr_) { + if (__other.__raw_ptr_) { + __increment_ref_count(*__other.__raw_ptr_); + } + if (__raw_ptr_) { + __decrement_ref_count(*__raw_ptr_); + } + __raw_ptr_ = __other.__raw_ptr_; + } + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __intrusive_shared_ptr& operator=(__intrusive_shared_ptr&& __other) noexcept { + __intrusive_shared_ptr(std::move(__other)).swap(*this); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI ~__intrusive_shared_ptr() { + if (__raw_ptr_) { + __decrement_ref_count(*__raw_ptr_); + } + } + + _LIBCPP_HIDE_FROM_ABI _Tp* operator->() const noexcept { return __raw_ptr_; } + _LIBCPP_HIDE_FROM_ABI _Tp& operator*() const noexcept { return *__raw_ptr_; } + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { return __raw_ptr_ != nullptr; } + + _LIBCPP_HIDE_FROM_ABI void swap(__intrusive_shared_ptr& __other) { std::swap(__raw_ptr_, __other.__raw_ptr_); } + + _LIBCPP_HIDE_FROM_ABI friend void swap(__intrusive_shared_ptr& __lhs, __intrusive_shared_ptr& __rhs) { + __lhs.swap(__rhs); + } + + _LIBCPP_HIDE_FROM_ABI friend bool constexpr + operator==(const __intrusive_shared_ptr&, const __intrusive_shared_ptr&) = default; + + _LIBCPP_HIDE_FROM_ABI friend bool constexpr operator==(const __intrusive_shared_ptr& __ptr, std::nullptr_t) { + return __ptr.__raw_ptr_ == nullptr; + } + +private: + _Tp* __raw_ptr_ = nullptr; + + // the memory order for increment/decrement the counter is the same for shared_ptr + // increment is relaxed and decrement is acq_rel + _LIBCPP_HIDE_FROM_ABI static void __increment_ref_count(_Tp& __obj) { + __get_atomic_ref_count(__obj).fetch_add(1, std::memory_order_relaxed); + } + + _LIBCPP_HIDE_FROM_ABI static void __decrement_ref_count(_Tp& __obj) { + if (__get_atomic_ref_count(__obj).fetch_sub(1, std::memory_order_acq_rel) == 1) { + delete &__obj; + } + } + + _LIBCPP_HIDE_FROM_ABI static decltype(auto) __get_atomic_ref_count(_Tp& __obj) { + using __ret_type = decltype(__intrusive_shared_ptr_traits<_Tp>::__get_atomic_ref_count(__obj)); + static_assert( + std::is_reference_v<__ret_type>, "__get_atomic_ref_count should return a reference to the atomic counter"); + return __intrusive_shared_ptr_traits<_Tp>::__get_atomic_ref_count(__obj); + } +}; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___STOP_TOKEN_INTRUSIVE_SHARED_PTR_H diff --git a/libcxx/include/__stop_token/stop_callback.h b/libcxx/include/__stop_token/stop_callback.h new file mode 100644 index 000000000000..c9dcad3deb91 --- /dev/null +++ b/libcxx/include/__stop_token/stop_callback.h @@ -0,0 +1,99 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H +#define _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H + +#include <__availability> +#include <__concepts/constructible.h> +#include <__concepts/destructible.h> +#include <__concepts/invocable.h> +#include <__config> +#include <__stop_token/intrusive_shared_ptr.h> +#include <__stop_token/stop_state.h> +#include <__stop_token/stop_token.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__utility/forward.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) + +template <class _Callback> +class _LIBCPP_AVAILABILITY_SYNC stop_callback : private __stop_callback_base { + static_assert(invocable<_Callback>, + "Mandates: stop_callback is instantiated with an argument for the template parameter Callback that " + "satisfies invocable."); + static_assert(destructible<_Callback>, + "Mandates: stop_callback is instantiated with an argument for the template parameter Callback that " + "satisfies destructible."); + +public: + using callback_type = _Callback; + + template <class _Cb> + requires constructible_from<_Callback, _Cb> + _LIBCPP_HIDE_FROM_ABI explicit stop_callback(const stop_token& __st, + _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>) + : stop_callback(__private_tag{}, __st.__state_, std::forward<_Cb>(__cb)) {} + + template <class _Cb> + requires constructible_from<_Callback, _Cb> + _LIBCPP_HIDE_FROM_ABI explicit stop_callback(stop_token&& __st, + _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>) + : stop_callback(__private_tag{}, std::move(__st.__state_), std::forward<_Cb>(__cb)) {} + + _LIBCPP_HIDE_FROM_ABI ~stop_callback() { + if (__state_) { + __state_->__remove_callback(this); + } + } + + stop_callback(const stop_callback&) = delete; + stop_callback(stop_callback&&) = delete; + stop_callback& operator=(const stop_callback&) = delete; + stop_callback& operator=(stop_callback&&) = delete; + +private: + _LIBCPP_NO_UNIQUE_ADDRESS _Callback __callback_; + __intrusive_shared_ptr<__stop_state> __state_; + + friend __stop_callback_base; + + struct __private_tag {}; + + template <class _StatePtr, class _Cb> + _LIBCPP_HIDE_FROM_ABI explicit stop_callback(__private_tag, _StatePtr&& __state, _Cb&& __cb) noexcept( + is_nothrow_constructible_v<_Callback, _Cb>) + : __stop_callback_base([](__stop_callback_base* __cb_base) noexcept { + // stop callback is supposed to only be called once + std::forward<_Callback>(static_cast<stop_callback*>(__cb_base)->__callback_)(); + }), + __callback_(std::forward<_Cb>(__cb)), + __state_() { + if (__state && __state->__add_callback(this)) { + // st.stop_requested() was false and this is successfully added to the linked list + __state_ = std::forward<_StatePtr>(__state); + } + } +}; + +template <class _Callback> +_LIBCPP_AVAILABILITY_SYNC stop_callback(stop_token, _Callback) -> stop_callback<_Callback>; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) diff --git a/libcxx/include/__stop_token/stop_source.h b/libcxx/include/__stop_token/stop_source.h new file mode 100644 index 000000000000..9d7ffd3e91e2 --- /dev/null +++ b/libcxx/include/__stop_token/stop_source.h @@ -0,0 +1,92 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___STOP_TOKEN_STOP_SOURCE_H +#define _LIBCPP___STOP_TOKEN_STOP_SOURCE_H + +#include <__availability> +#include <__config> +#include <__stop_token/intrusive_shared_ptr.h> +#include <__stop_token/stop_state.h> +#include <__stop_token/stop_token.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) + +struct nostopstate_t { + explicit nostopstate_t() = default; +}; + +inline constexpr nostopstate_t nostopstate{}; + +class _LIBCPP_AVAILABILITY_SYNC stop_source { +public: + _LIBCPP_HIDE_FROM_ABI stop_source() : __state_(new __stop_state()) { __state_->__increment_stop_source_counter(); } + + _LIBCPP_HIDE_FROM_ABI explicit stop_source(nostopstate_t) noexcept : __state_(nullptr) {} + + _LIBCPP_HIDE_FROM_ABI stop_source(const stop_source& __other) noexcept : __state_(__other.__state_) { + if (__state_) { + __state_->__increment_stop_source_counter(); + } + } + + _LIBCPP_HIDE_FROM_ABI stop_source(stop_source&& __other) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI stop_source& operator=(const stop_source& __other) noexcept { + // increment `__other` first so that we don't hit 0 in case of self-assignment + if (__other.__state_) { + __other.__state_->__increment_stop_source_counter(); + } + if (__state_) { + __state_->__decrement_stop_source_counter(); + } + __state_ = __other.__state_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI stop_source& operator=(stop_source&&) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI ~stop_source() { + if (__state_) { + __state_->__decrement_stop_source_counter(); + } + } + + _LIBCPP_HIDE_FROM_ABI void swap(stop_source& __other) noexcept { __state_.swap(__other.__state_); } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI stop_token get_token() const noexcept { return stop_token(__state_); } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool stop_possible() const noexcept { return __state_ != nullptr; } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool stop_requested() const noexcept { + return __state_ != nullptr && __state_->__stop_requested(); + } + + _LIBCPP_HIDE_FROM_ABI bool request_stop() noexcept { return __state_ && __state_->__request_stop(); } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend bool operator==(const stop_source&, const stop_source&) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI friend void swap(stop_source& __lhs, stop_source& __rhs) noexcept { __lhs.swap(__rhs); } + +private: + __intrusive_shared_ptr<__stop_state> __state_; +}; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) diff --git a/libcxx/include/__stop_token/stop_state.h b/libcxx/include/__stop_token/stop_state.h new file mode 100644 index 000000000000..9103bb196159 --- /dev/null +++ b/libcxx/include/__stop_token/stop_state.h @@ -0,0 +1,236 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___STOP_TOKEN_STOP_STATE_H +#define _LIBCPP___STOP_TOKEN_STOP_STATE_H + +#include <__availability> +#include <__config> +#include <__stop_token/atomic_unique_lock.h> +#include <__stop_token/intrusive_list_view.h> +#include <atomic> +#include <cstdint> +#include <thread> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +struct __stop_callback_base : __intrusive_node_base<__stop_callback_base> { + using __callback_fn_t = void(__stop_callback_base*) noexcept; + _LIBCPP_HIDE_FROM_ABI explicit __stop_callback_base(__callback_fn_t* __callback_fn) : __callback_fn_(__callback_fn) {} + + _LIBCPP_HIDE_FROM_ABI void __invoke() noexcept { __callback_fn_(this); } + + __callback_fn_t* __callback_fn_; + atomic<bool> __completed_ = false; + bool* __destroyed_ = nullptr; +}; + +class __stop_state { + static constexpr uint32_t __stop_requested_bit = 1; + static constexpr uint32_t __callback_list_locked_bit = 1 << 1; + static constexpr uint32_t __stop_source_counter_shift = 2; + + // The "stop_source counter" is not used for lifetime reference counting. + // When the number of stop_source reaches 0, the remaining stop_tokens's + // stop_possible will return false. We need this counter to track this. + // + // The "callback list locked" bit implements the atomic_unique_lock to + // guard the operations on the callback list + // + // 31 - 2 | 1 | 0 | + // stop_source counter | callback list locked | stop_requested | + atomic<uint32_t> __state_ = 0; + + // Reference count for stop_token + stop_callback + stop_source + // When the counter reaches zero, the state is destroyed + // It is used by __intrusive_shared_ptr, but it is stored here for better layout + atomic<uint32_t> __ref_count_ = 0; + + using __state_t = uint32_t; + using __callback_list_lock = __atomic_unique_lock<__state_t, __callback_list_locked_bit>; + using __callback_list = __intrusive_list_view<__stop_callback_base>; + + __callback_list __callback_list_; + thread::id __requesting_thread_; + +public: + _LIBCPP_HIDE_FROM_ABI __stop_state() noexcept = default; + + _LIBCPP_HIDE_FROM_ABI void __increment_stop_source_counter() noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED( + __state_.load(std::memory_order_relaxed) <= static_cast<__state_t>(~(1 << __stop_source_counter_shift)), + "stop_source's counter reaches the maximum. Incrementing the counter will overflow"); + __state_.fetch_add(1 << __stop_source_counter_shift, std::memory_order_relaxed); + } + + // We are not destroying the object after counter decrements to zero, nor do we have + // operations depend on the ordering of decrementing the counter. relaxed is enough. + _LIBCPP_HIDE_FROM_ABI void __decrement_stop_source_counter() noexcept { + _LIBCPP_ASSERT_UNCATEGORIZED( + __state_.load(std::memory_order_relaxed) >= static_cast<__state_t>(1 << __stop_source_counter_shift), + "stop_source's counter is 0. Decrementing the counter will underflow"); + __state_.fetch_sub(1 << __stop_source_counter_shift, std::memory_order_relaxed); + } + + _LIBCPP_HIDE_FROM_ABI bool __stop_requested() const noexcept { + // acquire because [thread.stoptoken.intro] A call to request_stop that returns true + // synchronizes with a call to stop_requested on an associated stop_token or stop_source + // object that returns true. + // request_stop's compare_exchange_weak has release which syncs with this acquire + return (__state_.load(std::memory_order_acquire) & __stop_requested_bit) != 0; + } + + _LIBCPP_HIDE_FROM_ABI bool __stop_possible_for_stop_token() const noexcept { + // [stoptoken.mem] false if "a stop request was not made and there are no associated stop_source objects" + // Todo: Can this be std::memory_order_relaxed as the standard does not say anything except not to introduce data + // race? + __state_t __curent_state = __state_.load(std::memory_order_acquire); + return ((__curent_state & __stop_requested_bit) != 0) || ((__curent_state >> __stop_source_counter_shift) != 0); + } + + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool __request_stop() noexcept { + auto __cb_list_lock = __try_lock_for_request_stop(); + if (!__cb_list_lock.__owns_lock()) { + return false; + } + __requesting_thread_ = this_thread::get_id(); + + while (!__callback_list_.__empty()) { + auto __cb = __callback_list_.__pop_front(); + + // allow other callbacks to be removed while invoking the current callback + __cb_list_lock.__unlock(); + + bool __destroyed = false; + __cb->__destroyed_ = &__destroyed; + + __cb->__invoke(); + + // __cb's invoke function could potentially delete itself. We need to check before accessing __cb's member + if (!__destroyed) { + // needs to set __destroyed_ pointer to nullptr, otherwise it points to a local variable + // which is to be destroyed at the end of the loop + __cb->__destroyed_ = nullptr; + + // [stopcallback.cons] If callback is concurrently executing on another thread, then the return + // from the invocation of callback strongly happens before ([intro.races]) callback is destroyed. + // this release syncs with the acquire in the remove_callback + __cb->__completed_.store(true, std::memory_order_release); + __cb->__completed_.notify_all(); + } + + __cb_list_lock.__lock(); + } + + return true; + } + + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool __add_callback(__stop_callback_base* __cb) noexcept { + // If it is already stop_requested. Do not try to request it again. + const auto __give_up_trying_to_lock_condition = [__cb](__state_t __state) { + if ((__state & __stop_requested_bit) != 0) { + // already stop requested, synchronously run the callback and no need to lock the list again + __cb->__invoke(); + return true; + } + // no stop source. no need to lock the list to add the callback as it can never be invoked + return (__state >> __stop_source_counter_shift) == 0; + }; + + __callback_list_lock __cb_list_lock(__state_, __give_up_trying_to_lock_condition); + + if (!__cb_list_lock.__owns_lock()) { + return false; + } + + __callback_list_.__push_front(__cb); + + return true; + // unlock here: [thread.stoptoken.intro] Registration of a callback synchronizes with the invocation of + // that callback. + // Note: this release sync with the acquire in the request_stop' __try_lock_for_request_stop + } + + // called by the destructor of stop_callback + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __remove_callback(__stop_callback_base* __cb) noexcept { + __callback_list_lock __cb_list_lock(__state_); + + // under below condition, the request_stop call just popped __cb from the list and could execute it now + bool __potentially_executing_now = __cb->__prev_ == nullptr && !__callback_list_.__is_head(__cb); + + if (__potentially_executing_now) { + auto __requested_thread = __requesting_thread_; + __cb_list_lock.__unlock(); + + if (std::this_thread::get_id() != __requested_thread) { + // [stopcallback.cons] If callback is concurrently executing on another thread, then the return + // from the invocation of callback strongly happens before ([intro.races]) callback is destroyed. + __cb->__completed_.wait(false, std::memory_order_acquire); + } else { + // The destructor of stop_callback runs on the same thread of the thread that invokes the callback. + // The callback is potentially invoking its own destuctor. Set the flag to avoid accessing destroyed + // members on the invoking side + if (__cb->__destroyed_) { + *__cb->__destroyed_ = true; + } + } + } else { + __callback_list_.__remove(__cb); + } + } + +private: + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI __callback_list_lock __try_lock_for_request_stop() noexcept { + // If it is already stop_requested, do not try to request stop or lock the list again. + const auto __lock_fail_condition = [](__state_t __state) { return (__state & __stop_requested_bit) != 0; }; + + // set locked and requested bit at the same time + const auto __after_lock_state = [](__state_t __state) { + return __state | __callback_list_locked_bit | __stop_requested_bit; + }; + + // acq because [thread.stoptoken.intro] Registration of a callback synchronizes with the invocation of that + // callback. We are going to invoke the callback after getting the lock, acquire so that we can see the + // registration of a callback (and other writes that happens-before the add_callback) + // Note: the rel (unlock) in the add_callback syncs with this acq + // rel because [thread.stoptoken.intro] A call to request_stop that returns true synchronizes with a call + // to stop_requested on an associated stop_token or stop_source object that returns true. + // We need to make sure that all writes (including user code) before request_stop will be made visible + // to the threads that waiting for `stop_requested == true` + // Note: this rel syncs with the acq in `stop_requested` + const auto __locked_ordering = std::memory_order_acq_rel; + + return __callback_list_lock(__state_, __lock_fail_condition, __after_lock_state, __locked_ordering); + } + + template <class _Tp> + friend struct __intrusive_shared_ptr_traits; +}; + +template <class _Tp> +struct __intrusive_shared_ptr_traits; + +template <> +struct __intrusive_shared_ptr_traits<__stop_state> { + _LIBCPP_HIDE_FROM_ABI static atomic<uint32_t>& __get_atomic_ref_count(__stop_state& __state) { + return __state.__ref_count_; + } +}; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___STOP_TOKEN_STOP_STATE_H diff --git a/libcxx/include/__stop_token/stop_token.h b/libcxx/include/__stop_token/stop_token.h new file mode 100644 index 000000000000..4ec72078226a --- /dev/null +++ b/libcxx/include/__stop_token/stop_token.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___STOP_TOKEN_STOP_TOKEN_H +#define _LIBCPP___STOP_TOKEN_STOP_TOKEN_H + +#include <__availability> +#include <__config> +#include <__stop_token/intrusive_shared_ptr.h> +#include <__stop_token/stop_state.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) + +class _LIBCPP_AVAILABILITY_SYNC stop_token { +public: + _LIBCPP_HIDE_FROM_ABI stop_token() noexcept = default; + + _LIBCPP_HIDE_FROM_ABI stop_token(const stop_token&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI stop_token(stop_token&&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI stop_token& operator=(const stop_token&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI stop_token& operator=(stop_token&&) noexcept = default; + _LIBCPP_HIDE_FROM_ABI ~stop_token() = default; + + _LIBCPP_HIDE_FROM_ABI void swap(stop_token& __other) noexcept { __state_.swap(__other.__state_); } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool stop_requested() const noexcept { + return __state_ != nullptr && __state_->__stop_requested(); + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool stop_possible() const noexcept { + return __state_ != nullptr && __state_->__stop_possible_for_stop_token(); + } + + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend bool operator==(const stop_token&, const stop_token&) noexcept = default; + + _LIBCPP_HIDE_FROM_ABI friend void swap(stop_token& __lhs, stop_token& __rhs) noexcept { __lhs.swap(__rhs); } + +private: + __intrusive_shared_ptr<__stop_state> __state_; + + friend class stop_source; + template <class _Tp> + friend class stop_callback; + + _LIBCPP_HIDE_FROM_ABI explicit stop_token(const __intrusive_shared_ptr<__stop_state>& __state) : __state_(__state) {} +}; + +#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___STOP_TOKEN_STOP_TOKEN_H diff --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h index 622ee224f1a0..c201fc9a1cda 100644 --- a/libcxx/include/__string/char_traits.h +++ b/libcxx/include/__string/char_traits.h @@ -18,11 +18,11 @@ #include <__config> #include <__functional/hash.h> #include <__iterator/iterator_traits.h> +#include <__string/constexpr_c_functions.h> #include <__type_traits/is_constant_evaluated.h> #include <cstddef> #include <cstdint> #include <cstdio> -#include <cstring> #include <iosfwd> #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -73,7 +73,7 @@ exposition-only to document what members a char_traits specialization should pro // // Temporary extension to provide a base template for std::char_traits. -// TODO: Remove in LLVM 18. +// TODO(LLVM-18): Remove this class. // template <class _CharT> struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, char8_t, char16_t or char32_t is non-standard and is provided for a temporary period. It will be removed in LLVM 18, so please migrate off of it.") @@ -85,14 +85,14 @@ struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, cha using pos_type = streampos; using state_type = mbstate_t; - static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17 + static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_HIDE_FROM_ABI assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} - static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {return __c1 == __c2;} - static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {return __c1 < __c2;} - static _LIBCPP_CONSTEXPR_SINCE_CXX17 + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) { for (; __n; --__n, ++__s1, ++__s2) { @@ -120,7 +120,7 @@ struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, cha } return nullptr; } - static _LIBCPP_CONSTEXPR_SINCE_CXX20 + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) { if (__n == 0) return __s1; char_type* __r = __s1; @@ -142,7 +142,8 @@ struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, cha static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) { if (!__libcpp_is_constant_evaluated()) { - _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); + _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES( + __s2 < __s1 || __s2 >= __s1 + __n, "char_traits::copy overlapped range"); } char_type* __r = __s1; for (; __n; --__n, ++__s1, ++__s2) @@ -158,37 +159,18 @@ struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, cha return __r; } - static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {return eq_int_type(__c, eof()) ? ~eof() : __c;} - static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {return char_type(__c);} - static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {return int_type(__c);} - static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {return __c1 == __c2;} - static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT {return int_type(EOF);} }; -template <class _CharT> -_LIBCPP_HIDE_FROM_ABI static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 -_CharT* __char_traits_move(_CharT* __dest, const _CharT* __source, size_t __n) _NOEXCEPT -{ -#ifdef _LIBCPP_COMPILER_GCC - if (__libcpp_is_constant_evaluated()) { - if (__n == 0) - return __dest; - _CharT* __allocation = new _CharT[__n]; - std::copy_n(__source, __n, __allocation); - std::copy_n(static_cast<const _CharT*>(__allocation), __n, __dest); - delete[] __allocation; - return __dest; - } -#endif - ::__builtin_memmove(__dest, __source, __n * sizeof(_CharT)); - return __dest; -} - // char_traits<char> template <> @@ -199,62 +181,83 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char> using off_type = streamoff; using pos_type = streampos; using state_type = mbstate_t; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using comparison_category = strong_ordering; #endif - static inline _LIBCPP_CONSTEXPR_SINCE_CXX17 + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} - static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT + + // TODO: Make this _LIBCPP_HIDE_FROM_ABI + static inline _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {return __c1 == __c2;} - static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {return (unsigned char)__c1 < (unsigned char)__c2;} - static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { - if (__n == 0) - return 0; - return std::__constexpr_memcmp(__s1, __s2, __n); - } + // __constexpr_memcmp requires a trivially lexicographically comparable type, but char is not when char is a signed type + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int + compare(const char_type* __lhs, const char_type* __rhs, size_t __count) _NOEXCEPT { + if (__libcpp_is_constant_evaluated()) { +#ifdef _LIBCPP_COMPILER_CLANG_BASED + return __builtin_memcmp(__lhs, __rhs, __count); +#else + while (__count != 0) { + if (lt(*__lhs, *__rhs)) + return -1; + if (lt(*__rhs, *__lhs)) + return 1; - static inline size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT { - return std::__constexpr_strlen(__s); - } + __count -= sizeof(char_type); + ++__lhs; + ++__rhs; + } + return 0; +#endif // _LIBCPP_COMPILER_CLANG_BASED + } else { + return __builtin_memcmp(__lhs, __rhs, __count); + } + } - static _LIBCPP_CONSTEXPR_SINCE_CXX17 - const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { - if (__n == 0) - return nullptr; - return std::__constexpr_char_memchr(__s, static_cast<int>(__a), __n); - } + static inline _LIBCPP_HIDE_FROM_ABI size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT { + return std::__constexpr_strlen(__s); + } - static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 + const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { + if (__n == 0) + return nullptr; + return std::__constexpr_memchr(__s, __a, __n); + } + + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { - return std::__char_traits_move(__s1, __s2, __n); + return std::__constexpr_memmove(__s1, __s2, __element_count(__n)); } - static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { if (!__libcpp_is_constant_evaluated()) - _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); + _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES( + __s2 < __s1 || __s2 >= __s1 + __n, "char_traits::copy overlapped range"); std::copy_n(__s2, __n, __s1); return __s1; } - static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { std::fill_n(__s, __n, __a); return __s; } - static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {return eq_int_type(__c, eof()) ? ~eof() : __c;} - static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {return char_type(__c);} - static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {return int_type((unsigned char)__c);} - static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {return __c1 == __c2;} - static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT {return int_type(EOF);} }; @@ -269,62 +272,64 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t> using off_type = streamoff; using pos_type = streampos; using state_type = mbstate_t; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using comparison_category = strong_ordering; #endif - static inline _LIBCPP_CONSTEXPR_SINCE_CXX17 + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} - static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {return __c1 == __c2;} - static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {return __c1 < __c2;} - static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int + compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { if (__n == 0) - return 0; + return 0; return std::__constexpr_wmemcmp(__s1, __s2, __n); } - static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT { + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT { return std::__constexpr_wcslen(__s); } - static _LIBCPP_CONSTEXPR_SINCE_CXX17 + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { if (__n == 0) return nullptr; return std::__constexpr_wmemchr(__s, __a, __n); } - static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { - return std::__char_traits_move(__s1, __s2, __n); + return std::__constexpr_memmove(__s1, __s2, __element_count(__n)); } - static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { if (!__libcpp_is_constant_evaluated()) - _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); + _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES( + __s2 < __s1 || __s2 >= __s1 + __n, "char_traits::copy overlapped range"); std::copy_n(__s2, __n, __s1); return __s1; } - static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { std::fill_n(__s, __n, __a); return __s; } - static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {return eq_int_type(__c, eof()) ? ~eof() : __c;} - static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {return char_type(__c);} - static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {return int_type(__c);} - static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {return __c1 == __c2;} - static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT {return int_type(WEOF);} }; #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -339,56 +344,57 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t> using off_type = streamoff; using pos_type = u8streampos; using state_type = mbstate_t; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using comparison_category = strong_ordering; #endif - static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept + static inline _LIBCPP_HIDE_FROM_ABI constexpr void assign(char_type& __c1, const char_type& __c2) noexcept {__c1 = __c2;} - static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept + static inline _LIBCPP_HIDE_FROM_ABI constexpr bool eq(char_type __c1, char_type __c2) noexcept {return __c1 == __c2;} - static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept + static inline _LIBCPP_HIDE_FROM_ABI constexpr bool lt(char_type __c1, char_type __c2) noexcept {return __c1 < __c2;} static _LIBCPP_HIDE_FROM_ABI constexpr int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { - return std::__constexpr_memcmp(__s1, __s2, __n); + return std::__constexpr_memcmp(__s1, __s2, __element_count(__n)); } - static constexpr + static _LIBCPP_HIDE_FROM_ABI constexpr size_t length(const char_type* __s) _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY static constexpr const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; - static _LIBCPP_CONSTEXPR_SINCE_CXX20 + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { - return std::__char_traits_move(__s1, __s2, __n); + return std::__constexpr_memmove(__s1, __s2, __element_count(__n)); } - static _LIBCPP_CONSTEXPR_SINCE_CXX20 + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { if (!__libcpp_is_constant_evaluated()) - _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); + _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES( + __s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); std::copy_n(__s2, __n, __s1); return __s1; } - static _LIBCPP_CONSTEXPR_SINCE_CXX20 + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { std::fill_n(__s, __n, __a); return __s; } - static inline constexpr int_type not_eof(int_type __c) noexcept + static inline _LIBCPP_HIDE_FROM_ABI constexpr int_type not_eof(int_type __c) noexcept {return eq_int_type(__c, eof()) ? ~eof() : __c;} - static inline constexpr char_type to_char_type(int_type __c) noexcept + static inline _LIBCPP_HIDE_FROM_ABI constexpr char_type to_char_type(int_type __c) noexcept {return char_type(__c);} - static inline constexpr int_type to_int_type(char_type __c) noexcept + static inline _LIBCPP_HIDE_FROM_ABI constexpr int_type to_int_type(char_type __c) noexcept {return int_type(__c);} - static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept + static inline _LIBCPP_HIDE_FROM_ABI constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept {return __c1 == __c2;} - static inline constexpr int_type eof() noexcept + static inline _LIBCPP_HIDE_FROM_ABI constexpr int_type eof() noexcept {return int_type(EOF);} }; @@ -427,15 +433,15 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> using off_type = streamoff; using pos_type = u16streampos; using state_type = mbstate_t; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using comparison_category = strong_ordering; #endif - static inline _LIBCPP_CONSTEXPR_SINCE_CXX17 + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} - static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {return __c1 == __c2;} - static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {return __c1 < __c2;} _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 @@ -447,13 +453,14 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { - return std::__char_traits_move(__s1, __s2, __n); + return std::__constexpr_memmove(__s1, __s2, __element_count(__n)); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { if (!__libcpp_is_constant_evaluated()) - _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); + _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES( + __s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); std::copy_n(__s2, __n, __s1); return __s1; } @@ -464,15 +471,15 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> return __s; } - static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {return eq_int_type(__c, eof()) ? ~eof() : __c;} - static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {return char_type(__c);} - static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {return int_type(__c);} - static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {return __c1 == __c2;} - static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT {return int_type(0xFFFF);} }; @@ -521,15 +528,15 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t> using off_type = streamoff; using pos_type = u32streampos; using state_type = mbstate_t; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 using comparison_category = strong_ordering; #endif - static inline _LIBCPP_CONSTEXPR_SINCE_CXX17 + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} - static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {return __c1 == __c2;} - static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {return __c1 < __c2;} _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 @@ -541,7 +548,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { - return std::__char_traits_move(__s1, __s2, __n); + return std::__constexpr_memmove(__s1, __s2, __element_count(__n)); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -556,15 +563,15 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t> return __s; } - static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {return eq_int_type(__c, eof()) ? ~eof() : __c;} - static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {return char_type(__c);} - static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {return int_type(__c);} - static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {return __c1 == __c2;} - static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT {return int_type(0xFFFFFFFF);} }; diff --git a/libcxx/include/__string/constexpr_c_functions.h b/libcxx/include/__string/constexpr_c_functions.h new file mode 100644 index 000000000000..198f0f5e6809 --- /dev/null +++ b/libcxx/include/__string/constexpr_c_functions.h @@ -0,0 +1,219 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___STRING_CONSTEXPR_C_FUNCTIONS_H +#define _LIBCPP___STRING_CONSTEXPR_C_FUNCTIONS_H + +#include <__config> +#include <__memory/addressof.h> +#include <__memory/construct_at.h> +#include <__type_traits/datasizeof.h> +#include <__type_traits/is_always_bitcastable.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_equality_comparable.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_trivially_copyable.h> +#include <__type_traits/is_trivially_lexicographically_comparable.h> +#include <__type_traits/remove_cv.h> +#include <__utility/is_pointer_in_range.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Type used to encode that a function takes an integer that represents a number +// of elements as opposed to a number of bytes. +enum class __element_count : size_t {}; + +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const char* __str) { + // GCC currently doesn't support __builtin_strlen for heap-allocated memory during constant evaluation. + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816 +#ifdef _LIBCPP_COMPILER_GCC + if (__libcpp_is_constant_evaluated()) { + size_t __i = 0; + for (; __str[__i] != '\0'; ++__i) + ; + return __i; + } +#endif + return __builtin_strlen(__str); +} + +// Because of __libcpp_is_trivially_lexicographically_comparable we know that comparing the object representations is +// equivalent to a std::memcmp. Since we have multiple objects contiguously in memory, we can call memcmp once instead +// of invoking it on every object individually. +template <class _Tp, class _Up> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int +__constexpr_memcmp(const _Tp* __lhs, const _Up* __rhs, __element_count __n) { + static_assert(__libcpp_is_trivially_lexicographically_comparable<_Tp, _Up>::value, + "_Tp and _Up have to be trivially lexicographically comparable"); + + auto __count = static_cast<size_t>(__n); + + if (__libcpp_is_constant_evaluated()) { +#ifdef _LIBCPP_COMPILER_CLANG_BASED + if (sizeof(_Tp) == 1 && !is_same<_Tp, bool>::value) + return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)); +#endif + + while (__count != 0) { + if (*__lhs < *__rhs) + return -1; + if (*__rhs < *__lhs) + return 1; + + --__count; + ++__lhs; + ++__rhs; + } + return 0; + } else { + return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)); + } +} + +// Because of __libcpp_is_trivially_equality_comparable we know that comparing the object representations is equivalent +// to a std::memcmp(...) == 0. Since we have multiple objects contiguously in memory, we can call memcmp once instead +// of invoking it on every object individually. +template <class _Tp, class _Up> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool +__constexpr_memcmp_equal(const _Tp* __lhs, const _Up* __rhs, __element_count __n) { + static_assert(__libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, + "_Tp and _Up have to be trivially equality comparable"); + + auto __count = static_cast<size_t>(__n); + + if (__libcpp_is_constant_evaluated()) { +#ifdef _LIBCPP_COMPILER_CLANG_BASED + if (sizeof(_Tp) == 1 && is_integral<_Tp>::value && !is_same<_Tp, bool>::value) + return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)) == 0; +#endif + while (__count != 0) { + if (*__lhs != *__rhs) + return false; + + --__count; + ++__lhs; + ++__rhs; + } + return true; + } else { + return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp)) == 0; + } +} + +template <class _Tp, class _Up> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __constexpr_memchr(_Tp* __str, _Up __value, size_t __count) { + static_assert(sizeof(_Tp) == 1 && __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value, + "Calling memchr on non-trivially equality comparable types is unsafe."); + + if (__libcpp_is_constant_evaluated()) { +// use __builtin_char_memchr to optimize constexpr evaluation if we can +#if _LIBCPP_STD_VER >= 17 && __has_builtin(__builtin_char_memchr) + if constexpr (is_same_v<remove_cv_t<_Tp>, char> && is_same_v<remove_cv_t<_Up>, char>) + return __builtin_char_memchr(__str, __value, __count); +#endif + + for (; __count; --__count) { + if (*__str == __value) + return __str; + ++__str; + } + return nullptr; + } else { + char __value_buffer = 0; + __builtin_memcpy(&__value_buffer, &__value, sizeof(char)); + return static_cast<_Tp*>(__builtin_memchr(__str, __value_buffer, __count)); + } +} + +// This function performs an assignment to an existing, already alive TriviallyCopyable object +// from another TriviallyCopyable object. +// +// It basically works around the fact that TriviallyCopyable objects are not required to be +// syntactically copy/move constructible or copy/move assignable. Technically, only one of the +// four operations is required to be syntactically valid -- but at least one definitely has to +// be valid. +// +// This is necessary in order to implement __constexpr_memmove below in a way that mirrors as +// closely as possible what the compiler's __builtin_memmove is able to do. +template <class _Tp, class _Up, __enable_if_t<is_assignable<_Tp&, _Up const&>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up const& __src) { + __dest = __src; + return __dest; +} + +// clang-format off +template <class _Tp, class _Up, __enable_if_t<!is_assignable<_Tp&, _Up const&>::value && + is_assignable<_Tp&, _Up&&>::value, int> = 0> +// clang-format on +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up& __src) { + __dest = + static_cast<_Up&&>(__src); // this is safe, we're not actually moving anything since the assignment is trivial + return __dest; +} + +// clang-format off +template <class _Tp, class _Up, __enable_if_t<!is_assignable<_Tp&, _Up const&>::value && + !is_assignable<_Tp&, _Up&&>::value && + is_constructible<_Tp, _Up const&>::value, int> = 0> +// clang-format on +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up const& __src) { + // _Tp is trivially destructible, so we don't need to call its destructor to end the lifetime of the object + // that was there previously + std::__construct_at(std::addressof(__dest), __src); + return __dest; +} + +// clang-format off +template <class _Tp, class _Up, __enable_if_t<!is_assignable<_Tp&, _Up const&>::value && + !is_assignable<_Tp&, _Up&&>::value && + !is_constructible<_Tp, _Up const&>::value && + is_constructible<_Tp, _Up&&>::value, int> = 0> +// clang-format on +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __assign_trivially_copyable(_Tp& __dest, _Up& __src) { + // _Tp is trivially destructible, so we don't need to call its destructor to end the lifetime of the object + // that was there previously + std::__construct_at( + std::addressof(__dest), + static_cast<_Up&&>(__src)); // this is safe, we're not actually moving anything since the constructor is trivial + return __dest; +} + +template <class _Tp, class _Up, __enable_if_t<__is_always_bitcastable<_Up, _Tp>::value, int> = 0> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* +__constexpr_memmove(_Tp* __dest, _Up* __src, __element_count __n) { + size_t __count = static_cast<size_t>(__n); + if (__libcpp_is_constant_evaluated()) { +#ifdef _LIBCPP_COMPILER_CLANG_BASED + if (is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >::value) { + ::__builtin_memmove(__dest, __src, __count * sizeof(_Tp)); + return __dest; + } +#endif + if (std::__is_pointer_in_range(__src, __src + __count, __dest)) { + for (; __count > 0; --__count) + std::__assign_trivially_copyable(__dest[__count - 1], __src[__count - 1]); + } else { + for (size_t __i = 0; __i != __count; ++__i) + std::__assign_trivially_copyable(__dest[__i], __src[__i]); + } + } else if (__count > 0) { + ::__builtin_memmove(__dest, __src, (__count - 1) * sizeof(_Tp) + __libcpp_datasizeof<_Tp>::value); + } + return __dest; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___STRING_CONSTEXPR_C_FUNCTIONS_H diff --git a/libcxx/include/__string/extern_template_lists.h b/libcxx/include/__string/extern_template_lists.h index edbda7cbd004..a833c000a289 100644 --- a/libcxx/include/__string/extern_template_lists.h +++ b/libcxx/include/__string/extern_template_lists.h @@ -28,104 +28,103 @@ // functions supporting new c++ version / API changes. Typically entries // must never be removed from the stable list. #define _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_Func, _CharType) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, allocator<_CharType> const&)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS const _CharType& basic_string<_CharType>::at(size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, size_type, size_type, allocator<_CharType> const&)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::erase(size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \ - _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \ - _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type)) + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::basic_string(basic_string const&)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::basic_string(basic_string const&, allocator<_CharType> const&)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::~basic_string()) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__init(value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI const _CharType& basic_string<_CharType>::at(size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::reserve(size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::basic_string(basic_string const&, size_type, size_type, allocator<_CharType> const&)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__init(size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::push_back(value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::erase(size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI int basic_string<_CharType>::compare(value_type const*) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI _CharType& basic_string<_CharType>::at(size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::resize(size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type)) #define _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_Func, _CharType) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init_copy_ctor_external(value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS const _CharType& basic_string<_CharType>::at(size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, size_type, size_type, allocator<_CharType> const&)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<false>(value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<true>(value_type const*, size_type)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__erase_external_with_move(size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \ - _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \ - _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \ - _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type)) + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::~basic_string()) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__init(value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__init_copy_ctor_external(value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI const _CharType& basic_string<_CharType>::at(size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::reserve(size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::basic_string(basic_string const&, size_type, size_type, allocator<_CharType> const&)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__init(size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<false>(value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<true>(value_type const*, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::push_back(value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::__erase_external_with_move(size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI int basic_string<_CharType>::compare(value_type const*) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI _CharType& basic_string<_CharType>::at(size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::resize(size_type, value_type)) \ + _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type)) #endif // _LIBCPP___STRING_EXTERN_TEMPLATE_LISTS_H diff --git a/libcxx/include/__errc b/libcxx/include/__system_error/errc.h index 17bbe0e2afce..17bbe0e2afce 100644 --- a/libcxx/include/__errc +++ b/libcxx/include/__system_error/errc.h diff --git a/libcxx/include/__system_error/error_category.h b/libcxx/include/__system_error/error_category.h new file mode 100644 index 000000000000..11c920e32657 --- /dev/null +++ b/libcxx/include/__system_error/error_category.h @@ -0,0 +1,75 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___SYSTEM_ERROR_ERROR_CATEGORY_H +#define _LIBCPP___SYSTEM_ERROR_ERROR_CATEGORY_H + +#include <__compare/ordering.h> +#include <__config> +#include <string> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_EXPORTED_FROM_ABI error_condition; +class _LIBCPP_EXPORTED_FROM_ABI error_code; + +class _LIBCPP_HIDDEN __do_message; + +class _LIBCPP_EXPORTED_FROM_ABI error_category { +public: + virtual ~error_category() _NOEXCEPT; + +#if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS) + error_category() noexcept; +#else + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 error_category() _NOEXCEPT = default; +#endif + error_category(const error_category&) = delete; + error_category& operator=(const error_category&) = delete; + + virtual const char* name() const _NOEXCEPT = 0; + virtual error_condition default_error_condition(int __ev) const _NOEXCEPT; + virtual bool equivalent(int __code, const error_condition& __condition) const _NOEXCEPT; + virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT; + virtual string message(int __ev) const = 0; + + _LIBCPP_HIDE_FROM_ABI bool operator==(const error_category& __rhs) const _NOEXCEPT { return this == &__rhs; } + +#if _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const error_category& __rhs) const noexcept { + return compare_three_way()(this, std::addressof(__rhs)); + } + +#else // _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI bool operator!=(const error_category& __rhs) const _NOEXCEPT { return !(*this == __rhs); } + + _LIBCPP_HIDE_FROM_ABI bool operator<(const error_category& __rhs) const _NOEXCEPT { return this < &__rhs; } + +#endif // _LIBCPP_STD_VER >= 20 + + friend class _LIBCPP_HIDDEN __do_message; +}; + +class _LIBCPP_HIDDEN __do_message : public error_category { +public: + string message(int __ev) const override; +}; + +_LIBCPP_EXPORTED_FROM_ABI const error_category& generic_category() _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI const error_category& system_category() _NOEXCEPT; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___SYSTEM_ERROR_ERROR_CATEGORY_H diff --git a/libcxx/include/__system_error/error_code.h b/libcxx/include/__system_error/error_code.h new file mode 100644 index 000000000000..d05e68529faf --- /dev/null +++ b/libcxx/include/__system_error/error_code.h @@ -0,0 +1,145 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___SYSTEM_ERROR_ERROR_CODE_H +#define _LIBCPP___SYSTEM_ERROR_ERROR_CODE_H + +#include <__compare/ordering.h> +#include <__config> +#include <__functional/hash.h> +#include <__functional/unary_function.h> +#include <__system_error/errc.h> +#include <__system_error/error_category.h> +#include <__system_error/error_condition.h> +#include <cstddef> +#include <string> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_error_code_enum : public false_type {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_error_code_enum_v = is_error_code_enum<_Tp>::value; +#endif + +namespace __adl_only { +// Those cause ADL to trigger but they are not viable candidates, +// so they are never actually selected. +void make_error_code() = delete; +} // namespace __adl_only + +class _LIBCPP_EXPORTED_FROM_ABI error_code { + int __val_; + const error_category* __cat_; + +public: + _LIBCPP_HIDE_FROM_ABI error_code() _NOEXCEPT : __val_(0), __cat_(&system_category()) {} + + _LIBCPP_HIDE_FROM_ABI error_code(int __val, const error_category& __cat) _NOEXCEPT : __val_(__val), __cat_(&__cat) {} + + template <class _Ep> + _LIBCPP_HIDE_FROM_ABI + error_code(_Ep __e, typename enable_if<is_error_code_enum<_Ep>::value>::type* = nullptr) _NOEXCEPT { + using __adl_only::make_error_code; + *this = make_error_code(__e); + } + + _LIBCPP_HIDE_FROM_ABI void assign(int __val, const error_category& __cat) _NOEXCEPT { + __val_ = __val; + __cat_ = &__cat; + } + + template <class _Ep> + _LIBCPP_HIDE_FROM_ABI typename enable_if< is_error_code_enum<_Ep>::value, error_code& >::type + operator=(_Ep __e) _NOEXCEPT { + using __adl_only::make_error_code; + *this = make_error_code(__e); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { + __val_ = 0; + __cat_ = &system_category(); + } + + _LIBCPP_HIDE_FROM_ABI int value() const _NOEXCEPT { return __val_; } + + _LIBCPP_HIDE_FROM_ABI const error_category& category() const _NOEXCEPT { return *__cat_; } + + _LIBCPP_HIDE_FROM_ABI error_condition default_error_condition() const _NOEXCEPT { + return __cat_->default_error_condition(__val_); + } + + string message() const; + + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __val_ != 0; } +}; + +inline _LIBCPP_HIDE_FROM_ABI error_code make_error_code(errc __e) _NOEXCEPT { + return error_code(static_cast<int>(__e), generic_category()); +} + +inline _LIBCPP_HIDE_FROM_ABI bool operator==(const error_code& __x, const error_code& __y) _NOEXCEPT { + return __x.category() == __y.category() && __x.value() == __y.value(); +} + +inline _LIBCPP_HIDE_FROM_ABI bool operator==(const error_code& __x, const error_condition& __y) _NOEXCEPT { + return __x.category().equivalent(__x.value(), __y) || __y.category().equivalent(__x, __y.value()); +} + +#if _LIBCPP_STD_VER <= 17 +inline _LIBCPP_HIDE_FROM_ABI bool operator==(const error_condition& __x, const error_code& __y) _NOEXCEPT { + return __y == __x; +} +#endif + +#if _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const error_code& __x, const error_code& __y) _NOEXCEPT { + return !(__x == __y); +} + +inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const error_code& __x, const error_condition& __y) _NOEXCEPT { + return !(__x == __y); +} + +inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const error_condition& __x, const error_code& __y) _NOEXCEPT { + return !(__x == __y); +} + +inline _LIBCPP_HIDE_FROM_ABI bool operator<(const error_code& __x, const error_code& __y) _NOEXCEPT { + return __x.category() < __y.category() || (__x.category() == __y.category() && __x.value() < __y.value()); +} + +#else // _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const error_code& __x, const error_code& __y) noexcept { + if (auto __c = __x.category() <=> __y.category(); __c != 0) + return __c; + return __x.value() <=> __y.value(); +} + +#endif // _LIBCPP_STD_VER <= 17 + +template <> +struct _LIBCPP_TEMPLATE_VIS hash<error_code> : public __unary_function<error_code, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(const error_code& __ec) const _NOEXCEPT { + return static_cast<size_t>(__ec.value()); + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___SYSTEM_ERROR_ERROR_CODE_H diff --git a/libcxx/include/__system_error/error_condition.h b/libcxx/include/__system_error/error_condition.h new file mode 100644 index 000000000000..a43a73cdc260 --- /dev/null +++ b/libcxx/include/__system_error/error_condition.h @@ -0,0 +1,132 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___SYSTEM_ERROR_ERROR_CONDITION_H +#define _LIBCPP___SYSTEM_ERROR_ERROR_CONDITION_H + +#include <__compare/ordering.h> +#include <__config> +#include <__functional/hash.h> +#include <__functional/unary_function.h> +#include <__system_error/errc.h> +#include <__system_error/error_category.h> +#include <cstddef> +#include <string> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum : public false_type {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_error_condition_enum_v = is_error_condition_enum<_Tp>::value; +#endif + +template <> +struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum<errc> : true_type {}; + +#ifdef _LIBCPP_CXX03_LANG +template <> +struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum<errc::__lx> : true_type {}; +#endif + +namespace __adl_only { +// Those cause ADL to trigger but they are not viable candidates, +// so they are never actually selected. +void make_error_condition() = delete; +} // namespace __adl_only + +class _LIBCPP_EXPORTED_FROM_ABI error_condition { + int __val_; + const error_category* __cat_; + +public: + _LIBCPP_HIDE_FROM_ABI error_condition() _NOEXCEPT : __val_(0), __cat_(&generic_category()) {} + + _LIBCPP_HIDE_FROM_ABI error_condition(int __val, const error_category& __cat) _NOEXCEPT + : __val_(__val), + __cat_(&__cat) {} + + template <class _Ep> + _LIBCPP_HIDE_FROM_ABI + error_condition(_Ep __e, typename enable_if<is_error_condition_enum<_Ep>::value>::type* = nullptr) _NOEXCEPT { + using __adl_only::make_error_condition; + *this = make_error_condition(__e); + } + + _LIBCPP_HIDE_FROM_ABI void assign(int __val, const error_category& __cat) _NOEXCEPT { + __val_ = __val; + __cat_ = &__cat; + } + + template <class _Ep> + _LIBCPP_HIDE_FROM_ABI typename enable_if< is_error_condition_enum<_Ep>::value, error_condition& >::type + operator=(_Ep __e) _NOEXCEPT { + using __adl_only::make_error_condition; + *this = make_error_condition(__e); + return *this; + } + + _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { + __val_ = 0; + __cat_ = &generic_category(); + } + + _LIBCPP_HIDE_FROM_ABI int value() const _NOEXCEPT { return __val_; } + + _LIBCPP_HIDE_FROM_ABI const error_category& category() const _NOEXCEPT { return *__cat_; } + string message() const; + + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __val_ != 0; } +}; + +inline _LIBCPP_HIDE_FROM_ABI error_condition make_error_condition(errc __e) _NOEXCEPT { + return error_condition(static_cast<int>(__e), generic_category()); +} + +inline _LIBCPP_HIDE_FROM_ABI bool operator==(const error_condition& __x, const error_condition& __y) _NOEXCEPT { + return __x.category() == __y.category() && __x.value() == __y.value(); +} + +#if _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const error_condition& __x, const error_condition& __y) _NOEXCEPT { + return !(__x == __y); +} + +inline _LIBCPP_HIDE_FROM_ABI bool operator<(const error_condition& __x, const error_condition& __y) _NOEXCEPT { + return __x.category() < __y.category() || (__x.category() == __y.category() && __x.value() < __y.value()); +} + +#else // _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_HIDE_FROM_ABI strong_ordering +operator<=>(const error_condition& __x, const error_condition& __y) noexcept { + if (auto __c = __x.category() <=> __y.category(); __c != 0) + return __c; + return __x.value() <=> __y.value(); +} + +#endif // _LIBCPP_STD_VER <= 17 + +template <> +struct _LIBCPP_TEMPLATE_VIS hash<error_condition> : public __unary_function<error_condition, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t operator()(const error_condition& __ec) const _NOEXCEPT { + return static_cast<size_t>(__ec.value()); + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___SYSTEM_ERROR_ERROR_CONDITION_H diff --git a/libcxx/include/__system_error/system_error.h b/libcxx/include/__system_error/system_error.h new file mode 100644 index 000000000000..bc829491a493 --- /dev/null +++ b/libcxx/include/__system_error/system_error.h @@ -0,0 +1,48 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___SYSTEM_ERROR_SYSTEM_ERROR_H +#define _LIBCPP___SYSTEM_ERROR_SYSTEM_ERROR_H + +#include <__config> +#include <__system_error/error_category.h> +#include <__system_error/error_code.h> +#include <stdexcept> +#include <string> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_EXPORTED_FROM_ABI system_error : public runtime_error { + error_code __ec_; + +public: + system_error(error_code __ec, const string& __what_arg); + system_error(error_code __ec, const char* __what_arg); + system_error(error_code __ec); + system_error(int __ev, const error_category& __ecat, const string& __what_arg); + system_error(int __ev, const error_category& __ecat, const char* __what_arg); + system_error(int __ev, const error_category& __ecat); + _LIBCPP_HIDE_FROM_ABI system_error(const system_error&) _NOEXCEPT = default; + ~system_error() _NOEXCEPT override; + + _LIBCPP_HIDE_FROM_ABI const error_code& code() const _NOEXCEPT { return __ec_; } + +private: + static string __init(const error_code&, string); +}; + +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_system_error(int __ev, const char* __what_arg); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___SYSTEM_ERROR_SYSTEM_ERROR_H diff --git a/libcxx/include/__thread/formatter.h b/libcxx/include/__thread/formatter.h new file mode 100644 index 000000000000..0e3a11c514e1 --- /dev/null +++ b/libcxx/include/__thread/formatter.h @@ -0,0 +1,80 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___THREAD_FORMATTER_H +#define _LIBCPP___THREAD_FORMATTER_H + +#include <__concepts/arithmetic.h> +#include <__config> +#include <__format/concepts.h> +#include <__format/format_parse_context.h> +#include <__format/formatter.h> +#include <__format/formatter_integral.h> +#include <__format/parser_std_format_spec.h> +#include <__thread/id.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_same.h> +#include <cstdint> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_THREADS + +template <__fmt_char_type _CharT> +struct _LIBCPP_TEMPLATE_VIS formatter<__thread_id, _CharT> { + public: + template <class _ParseContext> + _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { + return __parser_.__parse(__ctx, __format_spec::__fields_fill_align_width); + } + + template <class _FormatContext> + _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(__thread_id __id, _FormatContext& __ctx) const { + // In __threading_support __libcpp_thread_id is either a + // unsigned long long or a pthread_t. + // + // The type of pthread_t is left unspecified in POSIX so it can be any + // type. The most logical types are an integral or pointer. + // On Linux systems pthread_t is an unsigned long long. + // On Apple systems pthread_t is a pointer type. + // + // Note the output should match what the stream operator does. Since + // the ostream operator has been shipped years before this formatter + // was added to the Standard, this formatter does what the stream + // operator does. This may require platform specific changes. + + using _Tp = decltype(__get_underlying_id(__id)); + using _Cp = conditional_t<integral<_Tp>, _Tp, conditional_t<is_pointer_v<_Tp>, uintptr_t, void>>; + static_assert(!is_same_v<_Cp, void>, "unsupported thread::id type, please file a bug report"); + + __format_spec::__parsed_specifications<_CharT> __specs = __parser_.__get_parsed_std_specifications(__ctx); + if constexpr (is_pointer_v<_Tp>) { + __specs.__std_.__alternate_form_ = true; + __specs.__std_.__type_ = __format_spec::__type::__hexadecimal_lower_case; + } + return __formatter::__format_integer(reinterpret_cast<_Cp>(__get_underlying_id(__id)), __ctx, __specs); + } + + __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__right}; +}; + +#endif // !_LIBCPP_HAS_NO_THREADS + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +#endif // _LIBCPP___THREAD_FORMATTER_H diff --git a/libcxx/include/__thread/id.h b/libcxx/include/__thread/id.h new file mode 100644 index 000000000000..fd6e6dffafa9 --- /dev/null +++ b/libcxx/include/__thread/id.h @@ -0,0 +1,121 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___THREAD_ID_H +#define _LIBCPP___THREAD_ID_H + +#include <__compare/ordering.h> +#include <__config> +#include <__fwd/hash.h> +#include <__threading_support> +#include <iosfwd> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_THREADS +class _LIBCPP_EXPORTED_FROM_ABI __thread_id; + +namespace this_thread { + +_LIBCPP_HIDE_FROM_ABI __thread_id get_id() _NOEXCEPT; + +} // namespace this_thread + +template <> +struct hash<__thread_id>; + +class _LIBCPP_TEMPLATE_VIS __thread_id { + // FIXME: pthread_t is a pointer on Darwin but a long on Linux. + // NULL is the no-thread value on Darwin. Someone needs to check + // on other platforms. We assume 0 works everywhere for now. + __libcpp_thread_id __id_; + + static _LIBCPP_HIDE_FROM_ABI bool + __lt_impl(__thread_id __x, __thread_id __y) _NOEXCEPT { // id==0 is always less than any other thread_id + if (__x.__id_ == 0) + return __y.__id_ != 0; + if (__y.__id_ == 0) + return false; + return __libcpp_thread_id_less(__x.__id_, __y.__id_); + } + +public: + _LIBCPP_HIDE_FROM_ABI __thread_id() _NOEXCEPT : __id_(0) {} + + _LIBCPP_HIDE_FROM_ABI void __reset() { __id_ = 0; } + + friend _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT; +# if _LIBCPP_STD_VER <= 17 + friend _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT; +# else // _LIBCPP_STD_VER <= 17 + friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept; +# endif // _LIBCPP_STD_VER <= 17 + + template <class _CharT, class _Traits> + friend _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); + +private: + _LIBCPP_HIDE_FROM_ABI __thread_id(__libcpp_thread_id __id) : __id_(__id) {} + + _LIBCPP_HIDE_FROM_ABI friend __libcpp_thread_id __get_underlying_id(const __thread_id __id) { return __id.__id_; } + + friend __thread_id this_thread::get_id() _NOEXCEPT; + friend class _LIBCPP_EXPORTED_FROM_ABI thread; + friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; +}; + +inline _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT { + // Don't pass id==0 to underlying routines + if (__x.__id_ == 0) + return __y.__id_ == 0; + if (__y.__id_ == 0) + return false; + return __libcpp_thread_id_equal(__x.__id_, __y.__id_); +} + +# if _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_HIDE_FROM_ABI bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x == __y); } + +inline _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT { + return __thread_id::__lt_impl(__x.__id_, __y.__id_); +} + +inline _LIBCPP_HIDE_FROM_ABI bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__y < __x); } +inline _LIBCPP_HIDE_FROM_ABI bool operator>(__thread_id __x, __thread_id __y) _NOEXCEPT { return __y < __x; } +inline _LIBCPP_HIDE_FROM_ABI bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x < __y); } + +# else // _LIBCPP_STD_VER <= 17 + +inline _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept { + if (__x == __y) + return strong_ordering::equal; + if (__thread_id::__lt_impl(__x, __y)) + return strong_ordering::less; + return strong_ordering::greater; +} + +# endif // _LIBCPP_STD_VER <= 17 + +namespace this_thread { + +inline _LIBCPP_HIDE_FROM_ABI __thread_id get_id() _NOEXCEPT { return __libcpp_thread_get_current_id(); } + +} // namespace this_thread + +#endif // !_LIBCPP_HAS_NO_THREADS + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___THREAD_ID_H diff --git a/libcxx/include/__thread/this_thread.h b/libcxx/include/__thread/this_thread.h new file mode 100644 index 000000000000..b79065eeedae --- /dev/null +++ b/libcxx/include/__thread/this_thread.h @@ -0,0 +1,87 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___THREAD_THIS_THREAD_H +#define _LIBCPP___THREAD_THIS_THREAD_H + +#include <__chrono/steady_clock.h> +#include <__chrono/time_point.h> +#include <__condition_variable/condition_variable.h> +#include <__config> +#include <__mutex/mutex.h> +#include <__mutex/unique_lock.h> +#include <__threading_support> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace this_thread +{ + +_LIBCPP_EXPORTED_FROM_ABI void sleep_for(const chrono::nanoseconds& __ns); + +template <class _Rep, class _Period> +_LIBCPP_HIDE_FROM_ABI void +sleep_for(const chrono::duration<_Rep, _Period>& __d) +{ + if (__d > chrono::duration<_Rep, _Period>::zero()) + { + // The standard guarantees a 64bit signed integer resolution for nanoseconds, + // so use INT64_MAX / 1e9 as cut-off point. Use a constant to avoid <climits> + // and issues with long double folding on PowerPC with GCC. + _LIBCPP_CONSTEXPR chrono::duration<long double> __max = + chrono::duration<long double>(9223372036.0L); + chrono::nanoseconds __ns; + if (__d < __max) + { + __ns = chrono::duration_cast<chrono::nanoseconds>(__d); + if (__ns < __d) + ++__ns; + } + else + __ns = chrono::nanoseconds::max(); + this_thread::sleep_for(__ns); + } +} + +template <class _Clock, class _Duration> +_LIBCPP_HIDE_FROM_ABI void +sleep_until(const chrono::time_point<_Clock, _Duration>& __t) +{ + mutex __mut; + condition_variable __cv; + unique_lock<mutex> __lk(__mut); + while (_Clock::now() < __t) + __cv.wait_until(__lk, __t); +} + +template <class _Duration> +inline _LIBCPP_INLINE_VISIBILITY +void +sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) +{ + this_thread::sleep_for(__t - chrono::steady_clock::now()); +} + +inline _LIBCPP_INLINE_VISIBILITY +void yield() _NOEXCEPT {__libcpp_thread_yield();} + +} // namespace this_thread + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___THREAD_THIS_THREAD_H diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h new file mode 100644 index 000000000000..a1861e494888 --- /dev/null +++ b/libcxx/include/__thread/thread.h @@ -0,0 +1,297 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___THREAD_THREAD_H +#define _LIBCPP___THREAD_THREAD_H + +#include <__condition_variable/condition_variable.h> +#include <__config> +#include <__exception/terminate.h> +#include <__functional/hash.h> +#include <__functional/unary_function.h> +#include <__memory/unique_ptr.h> +#include <__mutex/mutex.h> +#include <__system_error/system_error.h> +#include <__thread/id.h> +#include <__threading_support> +#include <__utility/forward.h> +#include <iosfwd> +#include <tuple> + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +# include <locale> +# include <sstream> +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp> class __thread_specific_ptr; +class _LIBCPP_EXPORTED_FROM_ABI __thread_struct; +class _LIBCPP_HIDDEN __thread_struct_imp; +class __assoc_sub_state; + +_LIBCPP_EXPORTED_FROM_ABI __thread_specific_ptr<__thread_struct>& __thread_local_data(); + +class _LIBCPP_EXPORTED_FROM_ABI __thread_struct +{ + __thread_struct_imp* __p_; + + __thread_struct(const __thread_struct&); + __thread_struct& operator=(const __thread_struct&); +public: + __thread_struct(); + ~__thread_struct(); + + void notify_all_at_thread_exit(condition_variable*, mutex*); + void __make_ready_at_thread_exit(__assoc_sub_state*); +}; + +template <class _Tp> +class __thread_specific_ptr +{ + __libcpp_tls_key __key_; + + // Only __thread_local_data() may construct a __thread_specific_ptr + // and only with _Tp == __thread_struct. + static_assert((is_same<_Tp, __thread_struct>::value), ""); + __thread_specific_ptr(); + friend _LIBCPP_EXPORTED_FROM_ABI __thread_specific_ptr<__thread_struct>& __thread_local_data(); + + __thread_specific_ptr(const __thread_specific_ptr&); + __thread_specific_ptr& operator=(const __thread_specific_ptr&); + + _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*); + +public: + typedef _Tp* pointer; + + ~__thread_specific_ptr(); + + _LIBCPP_INLINE_VISIBILITY + pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));} + _LIBCPP_INLINE_VISIBILITY + pointer operator*() const {return *get();} + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const {return get();} + void set_pointer(pointer __p); +}; + +template <class _Tp> +void _LIBCPP_TLS_DESTRUCTOR_CC +__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) +{ + delete static_cast<pointer>(__p); +} + +template <class _Tp> +__thread_specific_ptr<_Tp>::__thread_specific_ptr() +{ + int __ec = + __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit); + if (__ec) + __throw_system_error(__ec, "__thread_specific_ptr construction failed"); +} + +template <class _Tp> +__thread_specific_ptr<_Tp>::~__thread_specific_ptr() +{ + // __thread_specific_ptr is only created with a static storage duration + // so this destructor is only invoked during program termination. Invoking + // pthread_key_delete(__key_) may prevent other threads from deleting their + // thread local data. For this reason we leak the key. +} + +template <class _Tp> +void +__thread_specific_ptr<_Tp>::set_pointer(pointer __p) +{ + _LIBCPP_ASSERT_UNCATEGORIZED(get() == nullptr, + "Attempting to overwrite thread local data"); + std::__libcpp_tls_set(__key_, __p); +} + +template<> +struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> + : public __unary_function<__thread_id, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(__thread_id __v) const _NOEXCEPT + { + return hash<__libcpp_thread_id>()(__v.__id_); + } +}; + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +template <class _CharT, class _Traits> +_LIBCPP_INLINE_VISIBILITY basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) { + // [thread.thread.id]/9 + // Effects: Inserts the text representation for charT of id into out. + // + // [thread.thread.id]/2 + // The text representation for the character type charT of an + // object of type thread::id is an unspecified sequence of charT + // such that, for two objects of type thread::id x and y, if + // x == y is true, the thread::id objects have the same text + // representation, and if x != y is true, the thread::id objects + // have distinct text representations. + // + // Since various flags in the output stream can affect how the + // thread id is represented (e.g. numpunct or showbase), we + // use a temporary stream instead and just output the thread + // id representation as a string. + + basic_ostringstream<_CharT, _Traits> __sstr; + __sstr.imbue(locale::classic()); + __sstr << __id.__id_; + return __os << __sstr.str(); +} +#endif // _LIBCPP_HAS_NO_LOCALIZATION + +class _LIBCPP_EXPORTED_FROM_ABI thread +{ + __libcpp_thread_t __t_; + + thread(const thread&); + thread& operator=(const thread&); +public: + typedef __thread_id id; + typedef __libcpp_thread_t native_handle_type; + + _LIBCPP_INLINE_VISIBILITY + thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} +#ifndef _LIBCPP_CXX03_LANG + template <class _Fp, class ..._Args, + class = __enable_if_t<!is_same<__remove_cvref_t<_Fp>, thread>::value> > + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + explicit thread(_Fp&& __f, _Args&&... __args); +#else // _LIBCPP_CXX03_LANG + template <class _Fp> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + explicit thread(_Fp __f); +#endif + ~thread(); + + _LIBCPP_INLINE_VISIBILITY + thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { + __t.__t_ = _LIBCPP_NULL_THREAD; + } + + _LIBCPP_INLINE_VISIBILITY + thread& operator=(thread&& __t) _NOEXCEPT { + if (!__libcpp_thread_isnull(&__t_)) + terminate(); + __t_ = __t.__t_; + __t.__t_ = _LIBCPP_NULL_THREAD; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} + + _LIBCPP_INLINE_VISIBILITY + bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);} + void join(); + void detach(); + _LIBCPP_INLINE_VISIBILITY + id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);} + _LIBCPP_INLINE_VISIBILITY + native_handle_type native_handle() _NOEXCEPT {return __t_;} + + static unsigned hardware_concurrency() _NOEXCEPT; +}; + +#ifndef _LIBCPP_CXX03_LANG + +template <class _TSp, class _Fp, class ..._Args, size_t ..._Indices> +inline _LIBCPP_INLINE_VISIBILITY +void +__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) +{ + _VSTD::__invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); +} + +template <class _Fp> +_LIBCPP_INLINE_VISIBILITY +void* __thread_proxy(void* __vp) +{ + // _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...> + unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); + __thread_local_data().set_pointer(_VSTD::get<0>(*__p.get()).release()); + typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index; + _VSTD::__thread_execute(*__p.get(), _Index()); + return nullptr; +} + +template <class _Fp, class ..._Args, + class + > +thread::thread(_Fp&& __f, _Args&&... __args) +{ + typedef unique_ptr<__thread_struct> _TSPtr; + _TSPtr __tsp(new __thread_struct); + typedef tuple<_TSPtr, __decay_t<_Fp>, __decay_t<_Args>...> _Gp; + unique_ptr<_Gp> __p( + new _Gp(_VSTD::move(__tsp), + _VSTD::forward<_Fp>(__f), + _VSTD::forward<_Args>(__args)...)); + int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); + if (__ec == 0) + __p.release(); + else + __throw_system_error(__ec, "thread constructor failed"); +} + +#else // _LIBCPP_CXX03_LANG + +template <class _Fp> +struct __thread_invoke_pair { + // This type is used to pass memory for thread local storage and a functor + // to a newly created thread because std::pair doesn't work with + // std::unique_ptr in C++03. + _LIBCPP_HIDE_FROM_ABI __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} + unique_ptr<__thread_struct> __tsp_; + _Fp __fn_; +}; + +template <class _Fp> +_LIBCPP_HIDE_FROM_ABI void* __thread_proxy_cxx03(void* __vp) +{ + unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); + __thread_local_data().set_pointer(__p->__tsp_.release()); + (__p->__fn_)(); + return nullptr; +} + +template <class _Fp> +thread::thread(_Fp __f) +{ + + typedef __thread_invoke_pair<_Fp> _InvokePair; + typedef unique_ptr<_InvokePair> _PairPtr; + _PairPtr __pp(new _InvokePair(__f)); + int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); + if (__ec == 0) + __pp.release(); + else + __throw_system_error(__ec, "thread constructor failed"); +} + +#endif // _LIBCPP_CXX03_LANG + +inline _LIBCPP_INLINE_VISIBILITY +void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___THREAD_THREAD_H diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support index dcf2763ad646..fcc2ed39a143 100644 --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -13,13 +13,9 @@ #include <__availability> #include <__chrono/convert_to_timespec.h> #include <__chrono/duration.h> -#include <__compare/ordering.h> #include <__config> -#include <__fwd/hash.h> #include <__thread/poll_with_backoff.h> #include <errno.h> -#include <iosfwd> -#include <limits> #ifdef __MVS__ # include <__support/ibm/nanosleep.h> @@ -34,26 +30,26 @@ #elif !defined(_LIBCPP_HAS_NO_THREADS) #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +// Some platforms require <bits/atomic_wide_counter.h> in order for +// PTHREAD_COND_INITIALIZER to be expanded. Normally that would come +// in via <pthread.h>, but it's a non-modular header on those platforms, +// so libc++'s <math.h> usually absorbs atomic_wide_counter.h into the +// module with <math.h> and makes atomic_wide_counter.h invisible. +// Include <math.h> here to work around that. +# include <math.h> + # include <pthread.h> # include <sched.h> #elif defined(_LIBCPP_HAS_THREAD_API_C11) # include <threads.h> #endif -#if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ - defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ - defined(_LIBCPP_HAS_THREAD_API_WIN32) -#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_FUNC_VIS +#if defined(_LIBCPP_HAS_THREAD_API_WIN32) +#define _LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_EXPORTED_FROM_ABI #else #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY #endif -#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis) -#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis)) -#else -#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS -#endif - typedef ::timespec __libcpp_timespec_t; #endif // !defined(_LIBCPP_HAS_NO_THREADS) @@ -252,28 +248,25 @@ int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); #endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) -#if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ - defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) - #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) { - pthread_mutexattr_t attr; - int __ec = pthread_mutexattr_init(&attr); + pthread_mutexattr_t __attr; + int __ec = pthread_mutexattr_init(&__attr); if (__ec) return __ec; - __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + __ec = pthread_mutexattr_settype(&__attr, PTHREAD_MUTEX_RECURSIVE); if (__ec) { - pthread_mutexattr_destroy(&attr); + pthread_mutexattr_destroy(&__attr); return __ec; } - __ec = pthread_mutex_init(__m, &attr); + __ec = pthread_mutex_init(__m, &__attr); if (__ec) { - pthread_mutexattr_destroy(&attr); + pthread_mutexattr_destroy(&__attr); return __ec; } - __ec = pthread_mutexattr_destroy(&attr); + __ec = pthread_mutexattr_destroy(&__attr); if (__ec) { pthread_mutex_destroy(__m); return __ec; @@ -380,8 +373,8 @@ int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), __libcpp_thread_id __libcpp_thread_get_current_id() { - const __libcpp_thread_t thread = pthread_self(); - return __libcpp_thread_get_id(&thread); + const __libcpp_thread_t __current_thread = pthread_self(); + return __libcpp_thread_get_id(&__current_thread); } __libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) @@ -589,116 +582,6 @@ int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) #endif - -#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL - -class _LIBCPP_TYPE_VIS thread; -class _LIBCPP_TYPE_VIS __thread_id; - -namespace this_thread -{ - -_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; - -} // namespace this_thread - -template<> struct hash<__thread_id>; - -class _LIBCPP_TEMPLATE_VIS __thread_id -{ - // FIXME: pthread_t is a pointer on Darwin but a long on Linux. - // NULL is the no-thread value on Darwin. Someone needs to check - // on other platforms. We assume 0 works everywhere for now. - __libcpp_thread_id __id_; - - static _LIBCPP_HIDE_FROM_ABI - bool __lt_impl(__thread_id __x, __thread_id __y) _NOEXCEPT - { // id==0 is always less than any other thread_id - if (__x.__id_ == 0) return __y.__id_ != 0; - if (__y.__id_ == 0) return false; - return __libcpp_thread_id_less(__x.__id_, __y.__id_); - } - -public: - _LIBCPP_INLINE_VISIBILITY - __thread_id() _NOEXCEPT : __id_(0) {} - - _LIBCPP_INLINE_VISIBILITY - void __reset() { __id_ = 0; } - - friend _LIBCPP_HIDE_FROM_ABI bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT; -#if _LIBCPP_STD_VER <= 17 - friend _LIBCPP_HIDE_FROM_ABI bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT; -#else // _LIBCPP_STD_VER <= 17 - friend _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept; -#endif // _LIBCPP_STD_VER <= 17 - - template<class _CharT, class _Traits> - friend - _LIBCPP_INLINE_VISIBILITY - basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); - -private: - _LIBCPP_INLINE_VISIBILITY - __thread_id(__libcpp_thread_id __id) : __id_(__id) {} - - friend __thread_id this_thread::get_id() _NOEXCEPT; - friend class _LIBCPP_TYPE_VIS thread; - friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; -}; - -inline _LIBCPP_HIDE_FROM_ABI -bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT { - // Don't pass id==0 to underlying routines - if (__x.__id_ == 0) - return __y.__id_ == 0; - if (__y.__id_ == 0) - return false; - return __libcpp_thread_id_equal(__x.__id_, __y.__id_); -} - -#if _LIBCPP_STD_VER <= 17 - -inline _LIBCPP_HIDE_FROM_ABI -bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT { - return !(__x == __y); -} - -inline _LIBCPP_HIDE_FROM_ABI -bool operator<(__thread_id __x, __thread_id __y) _NOEXCEPT { - return __thread_id::__lt_impl(__x.__id_, __y.__id_); -} - -inline _LIBCPP_HIDE_FROM_ABI bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__y < __x); } -inline _LIBCPP_HIDE_FROM_ABI bool operator>(__thread_id __x, __thread_id __y) _NOEXCEPT { return __y < __x; } -inline _LIBCPP_HIDE_FROM_ABI bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT { return !(__x < __y); } - -#else // _LIBCPP_STD_VER <= 17 - -inline _LIBCPP_HIDE_FROM_ABI -strong_ordering operator<=>(__thread_id __x, __thread_id __y) noexcept { - if (__x == __y) - return strong_ordering::equal; - if (__thread_id::__lt_impl(__x, __y)) - return strong_ordering::less; - return strong_ordering::greater; -} - -#endif // _LIBCPP_STD_VER <= 17 - -namespace this_thread -{ - -inline _LIBCPP_INLINE_VISIBILITY -__thread_id -get_id() _NOEXCEPT -{ - return __libcpp_thread_get_current_id(); -} - -} // namespace this_thread - #endif // !_LIBCPP_HAS_NO_THREADS _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__tree b/libcxx/include/__tree index f5d9d595b4b2..58d4a97c0403 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -13,11 +13,11 @@ #include <__algorithm/min.h> #include <__assert> #include <__config> -#include <__debug> #include <__functional/invoke.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> +#include <__memory/addressof.h> #include <__memory/allocator_traits.h> #include <__memory/compressed_pair.h> #include <__memory/pointer_traits.h> @@ -26,6 +26,7 @@ #include <__type_traits/can_extract_key.h> #include <__type_traits/conditional.h> #include <__type_traits/is_const.h> +#include <__type_traits/is_copy_constructible.h> #include <__type_traits/is_nothrow_copy_constructible.h> #include <__type_traits/is_nothrow_default_constructible.h> #include <__type_traits/is_nothrow_move_assignable.h> @@ -167,7 +168,7 @@ inline _LIBCPP_INLINE_VISIBILITY _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT { - _LIBCPP_ASSERT(__x != nullptr, "Root node shouldn't be null"); + _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Root node shouldn't be null"); while (__x->__left_ != nullptr) __x = __x->__left_; return __x; @@ -179,7 +180,7 @@ inline _LIBCPP_INLINE_VISIBILITY _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT { - _LIBCPP_ASSERT(__x != nullptr, "Root node shouldn't be null"); + _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Root node shouldn't be null"); while (__x->__right_ != nullptr) __x = __x->__right_; return __x; @@ -190,7 +191,7 @@ template <class _NodePtr> _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT { - _LIBCPP_ASSERT(__x != nullptr, "node shouldn't be null"); + _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); if (__x->__right_ != nullptr) return _VSTD::__tree_min(__x->__right_); while (!_VSTD::__tree_is_left_child(__x)) @@ -203,7 +204,7 @@ inline _LIBCPP_INLINE_VISIBILITY _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEPT { - _LIBCPP_ASSERT(__x != nullptr, "node shouldn't be null"); + _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); if (__x->__right_ != nullptr) return static_cast<_EndNodePtr>(_VSTD::__tree_min(__x->__right_)); while (!_VSTD::__tree_is_left_child(__x)) @@ -218,7 +219,7 @@ inline _LIBCPP_INLINE_VISIBILITY _NodePtr __tree_prev_iter(_EndNodePtr __x) _NOEXCEPT { - _LIBCPP_ASSERT(__x != nullptr, "node shouldn't be null"); + _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); if (__x->__left_ != nullptr) return _VSTD::__tree_max(__x->__left_); _NodePtr __xx = static_cast<_NodePtr>(__x); @@ -232,7 +233,7 @@ template <class _NodePtr> _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT { - _LIBCPP_ASSERT(__x != nullptr, "node shouldn't be null"); + _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); while (true) { if (__x->__left_ != nullptr) @@ -256,8 +257,8 @@ template <class _NodePtr> _LIBCPP_HIDE_FROM_ABI void __tree_left_rotate(_NodePtr __x) _NOEXCEPT { - _LIBCPP_ASSERT(__x != nullptr, "node shouldn't be null"); - _LIBCPP_ASSERT(__x->__right_ != nullptr, "node should have a right child"); + _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); + _LIBCPP_ASSERT_INTERNAL(__x->__right_ != nullptr, "node should have a right child"); _NodePtr __y = __x->__right_; __x->__right_ = __y->__left_; if (__x->__right_ != nullptr) @@ -277,8 +278,8 @@ template <class _NodePtr> _LIBCPP_HIDE_FROM_ABI void __tree_right_rotate(_NodePtr __x) _NOEXCEPT { - _LIBCPP_ASSERT(__x != nullptr, "node shouldn't be null"); - _LIBCPP_ASSERT(__x->__left_ != nullptr, "node should have a left child"); + _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null"); + _LIBCPP_ASSERT_INTERNAL(__x->__left_ != nullptr, "node should have a left child"); _NodePtr __y = __x->__left_; __x->__left_ = __y->__right_; if (__x->__left_ != nullptr) @@ -303,8 +304,8 @@ template <class _NodePtr> _LIBCPP_HIDE_FROM_ABI void __tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT { - _LIBCPP_ASSERT(__root != nullptr, "Root of the tree shouldn't be null"); - _LIBCPP_ASSERT(__x != nullptr, "Can't attach null node to a leaf"); + _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root of the tree shouldn't be null"); + _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Can't attach null node to a leaf"); __x->__is_black_ = __x == __root; while (__x != __root && !__x->__parent_unsafe()->__is_black_) { @@ -373,9 +374,9 @@ template <class _NodePtr> _LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT { - _LIBCPP_ASSERT(__root != nullptr, "Root node should not be null"); - _LIBCPP_ASSERT(__z != nullptr, "The node to remove should not be null"); - _LIBCPP_DEBUG_ASSERT(__tree_invariant(__root), "The tree invariants should hold"); + _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root node should not be null"); + _LIBCPP_ASSERT_INTERNAL(__z != nullptr, "The node to remove should not be null"); + _LIBCPP_ASSERT_INTERNAL(std::__tree_invariant(__root), "The tree invariants should hold"); // __z will be removed from the tree. Client still needs to destruct/deallocate it // __y is either __z, or if __z has two children, __tree_next(__z). // __y will have at most one child. @@ -797,7 +798,7 @@ public: bool __value_constructed; - __tree_node_destructor(const __tree_node_destructor &) = default; + _LIBCPP_HIDE_FROM_ABI __tree_node_destructor(const __tree_node_destructor &) = default; __tree_node_destructor& operator=(const __tree_node_destructor&) = delete; _LIBCPP_INLINE_VISIBILITY @@ -818,7 +819,7 @@ public: template <class> friend class __map_node_destructor; }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _NodeType, class _Alloc> struct __generic_container_node_destructor; template <class _Tp, class _VoidPtr, class _Alloc> @@ -849,7 +850,7 @@ public: typedef typename _NodeTypes::__node_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __tree_iterator() _NOEXCEPT -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 : __ptr_(nullptr) #endif {} @@ -922,7 +923,7 @@ public: typedef typename _NodeTypes::__const_node_value_type_pointer pointer; _LIBCPP_INLINE_VISIBILITY __tree_const_iterator() _NOEXCEPT -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 : __ptr_(nullptr) #endif {} @@ -1100,36 +1101,36 @@ public: __node_pointer __root() const _NOEXCEPT {return static_cast<__node_pointer>(__end_node()->__left_);} - __node_base_pointer* __root_ptr() const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI __node_base_pointer* __root_ptr() const _NOEXCEPT { return _VSTD::addressof(__end_node()->__left_); } typedef __tree_iterator<value_type, __node_pointer, difference_type> iterator; typedef __tree_const_iterator<value_type, __node_pointer, difference_type> const_iterator; - explicit __tree(const value_compare& __comp) + _LIBCPP_HIDE_FROM_ABI explicit __tree(const value_compare& __comp) _NOEXCEPT_( is_nothrow_default_constructible<__node_allocator>::value && is_nothrow_copy_constructible<value_compare>::value); - explicit __tree(const allocator_type& __a); - __tree(const value_compare& __comp, const allocator_type& __a); - __tree(const __tree& __t); - __tree& operator=(const __tree& __t); + _LIBCPP_HIDE_FROM_ABI explicit __tree(const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI __tree(const value_compare& __comp, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI __tree(const __tree& __t); + _LIBCPP_HIDE_FROM_ABI __tree& operator=(const __tree& __t); template <class _ForwardIterator> - void __assign_unique(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_HIDE_FROM_ABI void __assign_unique(_ForwardIterator __first, _ForwardIterator __last); template <class _InputIterator> - void __assign_multi(_InputIterator __first, _InputIterator __last); - __tree(__tree&& __t) + _LIBCPP_HIDE_FROM_ABI void __assign_multi(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI __tree(__tree&& __t) _NOEXCEPT_( is_nothrow_move_constructible<__node_allocator>::value && is_nothrow_move_constructible<value_compare>::value); - __tree(__tree&& __t, const allocator_type& __a); - __tree& operator=(__tree&& __t) + _LIBCPP_HIDE_FROM_ABI __tree(__tree&& __t, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI __tree& operator=(__tree&& __t) _NOEXCEPT_( __node_traits::propagate_on_container_move_assignment::value && is_nothrow_move_assignable<value_compare>::value && is_nothrow_move_assignable<__node_allocator>::value); - ~__tree(); + _LIBCPP_HIDE_FROM_ABI ~__tree(); _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return iterator(__begin_node());} @@ -1146,9 +1147,9 @@ public: __node_traits::max_size(__node_alloc()), numeric_limits<difference_type >::max());} - void clear() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT; - void swap(__tree& __t) + _LIBCPP_HIDE_FROM_ABI void swap(__tree& __t) #if _LIBCPP_STD_VER <= 11 _NOEXCEPT_( __is_nothrow_swappable<value_compare>::value @@ -1160,23 +1161,23 @@ public: #endif template <class _Key, class ..._Args> - pair<iterator, bool> + _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_key_args(_Key const&, _Args&&... __args); template <class _Key, class ..._Args> - pair<iterator, bool> + _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&&...); template <class... _Args> - pair<iterator, bool> __emplace_unique_impl(_Args&&... __args); + _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_impl(_Args&&... __args); template <class... _Args> - iterator __emplace_hint_unique_impl(const_iterator __p, _Args&&... __args); + _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_unique_impl(const_iterator __p, _Args&&... __args); template <class... _Args> - iterator __emplace_multi(_Args&&... __args); + _LIBCPP_HIDE_FROM_ABI iterator __emplace_multi(_Args&&... __args); template <class... _Args> - iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); + _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); template <class _Pp> _LIBCPP_INLINE_VISIBILITY @@ -1331,7 +1332,7 @@ public: _LIBCPP_INLINE_VISIBILITY iterator __remove_node_pointer(__node_pointer) _NOEXCEPT; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _NodeHandle, class _InsertReturnType> _LIBCPP_INLINE_VISIBILITY _InsertReturnType __node_handle_insert_unique(_NodeHandle&&); @@ -1361,33 +1362,33 @@ public: _NodeHandle __node_handle_extract(const_iterator); #endif - iterator erase(const_iterator __p); - iterator erase(const_iterator __f, const_iterator __l); + _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p); + _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l); template <class _Key> - size_type __erase_unique(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI size_type __erase_unique(const _Key& __k); template <class _Key> - size_type __erase_multi(const _Key& __k); + _LIBCPP_HIDE_FROM_ABI size_type __erase_multi(const _Key& __k); - void __insert_node_at(__parent_pointer __parent, + _LIBCPP_HIDE_FROM_ABI void __insert_node_at(__parent_pointer __parent, __node_base_pointer& __child, __node_base_pointer __new_node) _NOEXCEPT; template <class _Key> - iterator find(const _Key& __v); + _LIBCPP_HIDE_FROM_ABI iterator find(const _Key& __v); template <class _Key> - const_iterator find(const _Key& __v) const; + _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Key& __v) const; template <class _Key> - size_type __count_unique(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI size_type __count_unique(const _Key& __k) const; template <class _Key> - size_type __count_multi(const _Key& __k) const; + _LIBCPP_HIDE_FROM_ABI size_type __count_multi(const _Key& __k) const; template <class _Key> _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const _Key& __v) {return __lower_bound(__v, __root(), __end_node());} template <class _Key> - iterator __lower_bound(const _Key& __v, + _LIBCPP_HIDE_FROM_ABI iterator __lower_bound(const _Key& __v, __node_pointer __root, __iter_pointer __result); template <class _Key> @@ -1395,7 +1396,7 @@ public: const_iterator lower_bound(const _Key& __v) const {return __lower_bound(__v, __root(), __end_node());} template <class _Key> - const_iterator __lower_bound(const _Key& __v, + _LIBCPP_HIDE_FROM_ABI const_iterator __lower_bound(const _Key& __v, __node_pointer __root, __iter_pointer __result) const; template <class _Key> @@ -1403,7 +1404,7 @@ public: iterator upper_bound(const _Key& __v) {return __upper_bound(__v, __root(), __end_node());} template <class _Key> - iterator __upper_bound(const _Key& __v, + _LIBCPP_HIDE_FROM_ABI iterator __upper_bound(const _Key& __v, __node_pointer __root, __iter_pointer __result); template <class _Key> @@ -1411,55 +1412,52 @@ public: const_iterator upper_bound(const _Key& __v) const {return __upper_bound(__v, __root(), __end_node());} template <class _Key> - const_iterator __upper_bound(const _Key& __v, + _LIBCPP_HIDE_FROM_ABI const_iterator __upper_bound(const _Key& __v, __node_pointer __root, __iter_pointer __result) const; template <class _Key> - pair<iterator, iterator> + _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_unique(const _Key& __k); template <class _Key> - pair<const_iterator, const_iterator> + _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> __equal_range_unique(const _Key& __k) const; template <class _Key> - pair<iterator, iterator> + _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_multi(const _Key& __k); template <class _Key> - pair<const_iterator, const_iterator> + _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> __equal_range_multi(const _Key& __k) const; typedef __tree_node_destructor<__node_allocator> _Dp; typedef unique_ptr<__node, _Dp> __node_holder; - __node_holder remove(const_iterator __p) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI __node_holder remove(const_iterator __p) _NOEXCEPT; private: - __node_base_pointer& - __find_leaf_low(__parent_pointer& __parent, const key_type& __v); - __node_base_pointer& - __find_leaf_high(__parent_pointer& __parent, const key_type& __v); - __node_base_pointer& - __find_leaf(const_iterator __hint, - __parent_pointer& __parent, const key_type& __v); + _LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_leaf_low(__parent_pointer& __parent, const key_type& __v); + _LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_leaf_high(__parent_pointer& __parent, const key_type& __v); + _LIBCPP_HIDE_FROM_ABI __node_base_pointer& + __find_leaf(const_iterator __hint, __parent_pointer& __parent, const key_type& __v); // FIXME: Make this function const qualified. Unfortunately doing so // breaks existing code which uses non-const callable comparators. template <class _Key> - __node_base_pointer& - __find_equal(__parent_pointer& __parent, const _Key& __v); + _LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_equal(__parent_pointer& __parent, const _Key& __v); template <class _Key> _LIBCPP_INLINE_VISIBILITY __node_base_pointer& __find_equal(__parent_pointer& __parent, const _Key& __v) const { return const_cast<__tree*>(this)->__find_equal(__parent, __v); } template <class _Key> - __node_base_pointer& + _LIBCPP_HIDE_FROM_ABI __node_base_pointer& __find_equal(const_iterator __hint, __parent_pointer& __parent, __node_base_pointer& __dummy, const _Key& __v); template <class ..._Args> - __node_holder __construct_node(_Args&& ...__args); + _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&& ...__args); - void destroy(__node_pointer __nd) _NOEXCEPT; + // TODO: Make this _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDDEN void destroy(__node_pointer __nd) _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __tree& __t) @@ -1476,8 +1474,8 @@ private: _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __tree&, false_type) {} - void __move_assign(__tree& __t, false_type); - void __move_assign(__tree& __t, true_type) + _LIBCPP_HIDE_FROM_ABI void __move_assign(__tree& __t, false_type); + _LIBCPP_HIDE_FROM_ABI void __move_assign(__tree& __t, true_type) _NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value && is_nothrow_move_assignable<__node_allocator>::value); @@ -1640,7 +1638,7 @@ __tree<_Tp, _Compare, _Allocator>::__assign_unique(_ForwardIterator __first, _Fo typedef typename _ITraits::value_type _ItValueType; static_assert((is_same<_ItValueType, __container_value_type>::value), "__assign_unique may only be called with the containers value type"); - static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value, + static_assert(__has_forward_iterator_category<_ForwardIterator>::value, "__assign_unique requires a forward iterator"); if (size() != 0) { @@ -2265,7 +2263,7 @@ __tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr) _ return __r; } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp, class _Compare, class _Allocator> template <class _NodeHandle, class _InsertReturnType> _LIBCPP_INLINE_VISIBILITY @@ -2422,7 +2420,7 @@ __tree<_Tp, _Compare, _Allocator>::__node_handle_merge_multi(_Tree& __source) } } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 template <class _Tp, class _Compare, class _Allocator> typename __tree<_Tp, _Compare, _Allocator>::iterator diff --git a/libcxx/include/__tuple_dir/make_tuple_types.h b/libcxx/include/__tuple/make_tuple_types.h index 913ff9bbd60c..aee2bde89c7f 100644 --- a/libcxx/include/__tuple_dir/make_tuple_types.h +++ b/libcxx/include/__tuple/make_tuple_types.h @@ -12,11 +12,11 @@ #include <__config> #include <__fwd/array.h> #include <__fwd/tuple.h> -#include <__tuple_dir/apply_cv.h> -#include <__tuple_dir/tuple_element.h> -#include <__tuple_dir/tuple_indices.h> -#include <__tuple_dir/tuple_size.h> -#include <__tuple_dir/tuple_types.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_indices.h> +#include <__tuple/tuple_size.h> +#include <__tuple/tuple_types.h> +#include <__type_traits/apply_cv.h> #include <__type_traits/remove_cv.h> #include <__type_traits/remove_reference.h> #include <cstddef> @@ -40,20 +40,16 @@ struct __make_tuple_types_flat; 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 _LIBCPP_NODEBUG = __tuple_types< - typename _ApplyFn::template __apply<__type_pack_element<_Idx, _Types...>>... - >; + template <class _Tp> + using __apply_quals _LIBCPP_NODEBUG = __tuple_types<__apply_cv_t<_Tp, __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...>> { template <size_t> using __value_type = _Vt; - template <class _Tp, class _ApplyFn = __apply_cv_t<_Tp>> - using __apply_quals = __tuple_types< - typename _ApplyFn::template __apply<__value_type<_Idx>>... - >; + template <class _Tp> + using __apply_quals = __tuple_types<__apply_cv_t<_Tp, __value_type<_Idx>>...>; }; template <class _Tp, size_t _Ep = tuple_size<__libcpp_remove_reference_t<_Tp> >::value, diff --git a/libcxx/include/__tuple_dir/pair_like.h b/libcxx/include/__tuple/pair_like.h index 87407ad95b6f..192682dc7eb5 100644 --- a/libcxx/include/__tuple_dir/pair_like.h +++ b/libcxx/include/__tuple/pair_like.h @@ -10,8 +10,8 @@ #define _LIBCPP___TUPLE_PAIR_LIKE_H #include <__config> -#include <__tuple_dir/tuple_like.h> -#include <__tuple_dir/tuple_size.h> +#include <__tuple/tuple_like.h> +#include <__tuple/tuple_size.h> #include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__tuple_dir/sfinae_helpers.h b/libcxx/include/__tuple/sfinae_helpers.h index fcd65a0817be..2fffac9efda1 100644 --- a/libcxx/include/__tuple_dir/sfinae_helpers.h +++ b/libcxx/include/__tuple/sfinae_helpers.h @@ -11,11 +11,11 @@ #include <__config> #include <__fwd/tuple.h> -#include <__tuple_dir/make_tuple_types.h> -#include <__tuple_dir/tuple_element.h> -#include <__tuple_dir/tuple_like_ext.h> -#include <__tuple_dir/tuple_size.h> -#include <__tuple_dir/tuple_types.h> +#include <__tuple/make_tuple_types.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_like_ext.h> +#include <__tuple/tuple_size.h> +#include <__tuple/tuple_types.h> #include <__type_traits/enable_if.h> #include <__type_traits/integral_constant.h> #include <__type_traits/is_assignable.h> @@ -108,33 +108,20 @@ struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, tuple<_Tp...> > typedef _LIBCPP_NODEBUG typename tuple_element<_Ip, __tuple_types<_Tp...> >::type type; }; -template <bool _IsTuple, class _SizeTrait, size_t _Expected> -struct __tuple_like_with_size_imp : false_type {}; +struct _LIBCPP_EXPORTED_FROM_ABI __check_tuple_constructor_fail { -template <class _SizeTrait, size_t _Expected> -struct __tuple_like_with_size_imp<true, _SizeTrait, _Expected> - : integral_constant<bool, _SizeTrait::value == _Expected> {}; - -template <class _Tuple, size_t _ExpectedSize, class _RawTuple = __libcpp_remove_reference_t<_Tuple> > -using __tuple_like_with_size _LIBCPP_NODEBUG = __tuple_like_with_size_imp< - __tuple_like_ext<_RawTuple>::value, - tuple_size<_RawTuple>, _ExpectedSize - >; - -struct _LIBCPP_TYPE_VIS __check_tuple_constructor_fail { - - static constexpr bool __enable_explicit_default() { return false; } - static constexpr bool __enable_implicit_default() { return false; } + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_explicit_default() { return false; } + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit_default() { return false; } template <class ...> - static constexpr bool __enable_explicit() { return false; } + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_explicit() { return false; } template <class ...> - static constexpr bool __enable_implicit() { return false; } + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit() { return false; } template <class ...> - static constexpr bool __enable_assign() { return false; } + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_assign() { return false; } }; #endif // !defined(_LIBCPP_CXX03_LANG) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <bool _CanCopy, bool _CanMove> struct __sfinae_ctor_base {}; @@ -189,7 +176,7 @@ struct __sfinae_assign_base<false, true> { __sfinae_assign_base& operator=(__sfinae_assign_base const&) = delete; __sfinae_assign_base& operator=(__sfinae_assign_base&&) = default; }; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__tuple_dir/tuple_element.h b/libcxx/include/__tuple/tuple_element.h index 06f49bf500fb..478dd089d46c 100644 --- a/libcxx/include/__tuple_dir/tuple_element.h +++ b/libcxx/include/__tuple/tuple_element.h @@ -10,8 +10,8 @@ #define _LIBCPP___TUPLE_TUPLE_ELEMENT_H #include <__config> -#include <__tuple_dir/tuple_indices.h> -#include <__tuple_dir/tuple_types.h> +#include <__tuple/tuple_indices.h> +#include <__tuple/tuple_types.h> #include <__type_traits/add_const.h> #include <__type_traits/add_cv.h> #include <__type_traits/add_volatile.h> @@ -81,7 +81,7 @@ struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, __tuple_types<_Types...> > typedef _LIBCPP_NODEBUG __type_pack_element<_Ip, _Types...> type; }; -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <size_t _Ip, class ..._Tp> using tuple_element_t _LIBCPP_NODEBUG = typename tuple_element <_Ip, _Tp...>::type; #endif diff --git a/libcxx/include/__tuple_dir/tuple_indices.h b/libcxx/include/__tuple/tuple_indices.h index 18666d5948c9..18666d5948c9 100644 --- a/libcxx/include/__tuple_dir/tuple_indices.h +++ b/libcxx/include/__tuple/tuple_indices.h diff --git a/libcxx/include/__tuple_dir/tuple_like.h b/libcxx/include/__tuple/tuple_like.h index dab395be616b..dab395be616b 100644 --- a/libcxx/include/__tuple_dir/tuple_like.h +++ b/libcxx/include/__tuple/tuple_like.h diff --git a/libcxx/include/__tuple_dir/tuple_like_ext.h b/libcxx/include/__tuple/tuple_like_ext.h index bf9869611273..36f5c4896ffe 100644 --- a/libcxx/include/__tuple_dir/tuple_like_ext.h +++ b/libcxx/include/__tuple/tuple_like_ext.h @@ -13,7 +13,7 @@ #include <__fwd/array.h> #include <__fwd/pair.h> #include <__fwd/tuple.h> -#include <__tuple_dir/tuple_types.h> +#include <__tuple/tuple_types.h> #include <__type_traits/integral_constant.h> #include <cstddef> diff --git a/libcxx/include/__tuple_dir/tuple_size.h b/libcxx/include/__tuple/tuple_size.h index d551b2258cba..26f9d9725d31 100644 --- a/libcxx/include/__tuple_dir/tuple_size.h +++ b/libcxx/include/__tuple/tuple_size.h @@ -11,7 +11,7 @@ #include <__config> #include <__fwd/tuple.h> -#include <__tuple_dir/tuple_types.h> +#include <__tuple/tuple_types.h> #include <__type_traits/is_const.h> #include <__type_traits/is_volatile.h> #include <cstddef> diff --git a/libcxx/include/__tuple_dir/tuple_types.h b/libcxx/include/__tuple/tuple_types.h index c5be81cce801..c5be81cce801 100644 --- a/libcxx/include/__tuple_dir/tuple_types.h +++ b/libcxx/include/__tuple/tuple_types.h diff --git a/libcxx/include/__tuple_dir/apply_cv.h b/libcxx/include/__tuple_dir/apply_cv.h deleted file mode 100644 index 296755a1d52d..000000000000 --- a/libcxx/include/__tuple_dir/apply_cv.h +++ /dev/null @@ -1,70 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TUPLE_APPLY_CV_H -#define _LIBCPP___TUPLE_APPLY_CV_H - -#include <__config> -#include <__type_traits/is_const.h> -#include <__type_traits/is_reference.h> -#include <__type_traits/is_volatile.h> -#include <__type_traits/remove_reference.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#ifndef _LIBCPP_CXX03_LANG - -_LIBCPP_BEGIN_NAMESPACE_STD - -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 _LIBCPP_NODEBUG = const _Tp; -}; -template <> -struct __apply_cv_mf<false, false, true> { - template <class _Tp> using __apply _LIBCPP_NODEBUG = volatile _Tp; -}; -template <> -struct __apply_cv_mf<false, true, true> { - template <class _Tp> using __apply _LIBCPP_NODEBUG = const volatile _Tp; -}; -template <> -struct __apply_cv_mf<true, false, false> { - template <class _Tp> using __apply _LIBCPP_NODEBUG = _Tp&; -}; -template <> -struct __apply_cv_mf<true, true, false> { - template <class _Tp> using __apply _LIBCPP_NODEBUG = const _Tp&; -}; -template <> -struct __apply_cv_mf<true, false, true> { - template <class _Tp> using __apply _LIBCPP_NODEBUG = volatile _Tp&; -}; -template <> -struct __apply_cv_mf<true, true, true> { - template <class _Tp> using __apply _LIBCPP_NODEBUG = const volatile _Tp&; -}; -template <class _Tp, class _RawTp = __libcpp_remove_reference_t<_Tp> > -using __apply_cv_t _LIBCPP_NODEBUG = __apply_cv_mf< - is_lvalue_reference<_Tp>::value, - is_const<_RawTp>::value, - is_volatile<_RawTp>::value>; - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP_CXX03_LANG - -#endif // _LIBCPP___TUPLE_APPLY_CV_H diff --git a/libcxx/include/__type_traits/add_const.h b/libcxx/include/__type_traits/add_const.h index c616a13f8408..9a6f1c10299f 100644 --- a/libcxx/include/__type_traits/add_const.h +++ b/libcxx/include/__type_traits/add_const.h @@ -17,12 +17,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS add_const { +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS add_const { typedef _LIBCPP_NODEBUG const _Tp type; }; -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using add_const_t = typename add_const<_Tp>::type; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using add_const_t = typename add_const<_Tp>::type; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/add_cv.h b/libcxx/include/__type_traits/add_cv.h index 8a85353f16c0..9e23e5ceb7a3 100644 --- a/libcxx/include/__type_traits/add_cv.h +++ b/libcxx/include/__type_traits/add_cv.h @@ -17,12 +17,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS add_cv { +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS add_cv { typedef _LIBCPP_NODEBUG const volatile _Tp type; }; -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using add_cv_t = typename add_cv<_Tp>::type; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using add_cv_t = typename add_cv<_Tp>::type; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/add_lvalue_reference.h b/libcxx/include/__type_traits/add_lvalue_reference.h index daa5cb9e7dff..a633e3904532 100644 --- a/libcxx/include/__type_traits/add_lvalue_reference.h +++ b/libcxx/include/__type_traits/add_lvalue_reference.h @@ -44,8 +44,9 @@ struct add_lvalue_reference { using type _LIBCPP_NODEBUG = __add_lvalue_reference_t<_Tp>; }; -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using add_lvalue_reference_t = __add_lvalue_reference_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using add_lvalue_reference_t = __add_lvalue_reference_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/add_pointer.h b/libcxx/include/__type_traits/add_pointer.h index 9d0c2010077b..358e3cbd2384 100644 --- a/libcxx/include/__type_traits/add_pointer.h +++ b/libcxx/include/__type_traits/add_pointer.h @@ -22,32 +22,34 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__add_pointer) +#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer) template <class _Tp> using __add_pointer_t = __add_pointer(_Tp); #else -template <class _Tp, - bool = __libcpp_is_referenceable<_Tp>::value || is_void<_Tp>::value> +template <class _Tp, bool = __libcpp_is_referenceable<_Tp>::value || is_void<_Tp>::value> struct __add_pointer_impl { typedef _LIBCPP_NODEBUG __libcpp_remove_reference_t<_Tp>* type; }; -template <class _Tp> struct __add_pointer_impl<_Tp, false> - {typedef _LIBCPP_NODEBUG _Tp type;}; +template <class _Tp> +struct __add_pointer_impl<_Tp, false> { + typedef _LIBCPP_NODEBUG _Tp type; +}; template <class _Tp> using __add_pointer_t = typename __add_pointer_impl<_Tp>::type; -#endif // __has_builtin(__add_pointer) +#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer) template <class _Tp> struct add_pointer { using type _LIBCPP_NODEBUG = __add_pointer_t<_Tp>; }; -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using add_pointer_t = __add_pointer_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using add_pointer_t = __add_pointer_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/add_rvalue_reference.h b/libcxx/include/__type_traits/add_rvalue_reference.h index 098e84c0722c..a54aae7ec8de 100644 --- a/libcxx/include/__type_traits/add_rvalue_reference.h +++ b/libcxx/include/__type_traits/add_rvalue_reference.h @@ -44,7 +44,7 @@ struct add_rvalue_reference { using type = __add_rvalue_reference_t<_Tp>; }; -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp> using add_rvalue_reference_t = __add_rvalue_reference_t<_Tp>; #endif diff --git a/libcxx/include/__type_traits/add_volatile.h b/libcxx/include/__type_traits/add_volatile.h index 73b1cb8418fe..56b7dfaac026 100644 --- a/libcxx/include/__type_traits/add_volatile.h +++ b/libcxx/include/__type_traits/add_volatile.h @@ -17,12 +17,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS add_volatile { +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS add_volatile { typedef _LIBCPP_NODEBUG volatile _Tp type; }; -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using add_volatile_t = typename add_volatile<_Tp>::type; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using add_volatile_t = typename add_volatile<_Tp>::type; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/aligned_storage.h b/libcxx/include/__type_traits/aligned_storage.h index c564d582452d..46aae12832f8 100644 --- a/libcxx/include/__type_traits/aligned_storage.h +++ b/libcxx/include/__type_traits/aligned_storage.h @@ -23,59 +23,63 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> -struct __align_type -{ - static const size_t value = _LIBCPP_PREFERRED_ALIGNOF(_Tp); - typedef _Tp type; +struct __align_type { + static const size_t value = _LIBCPP_PREFERRED_ALIGNOF(_Tp); + typedef _Tp type; }; -struct __struct_double {long double __lx;}; -struct __struct_double4 {double __lx[4];}; - -typedef - __type_list<__align_type<unsigned char>, - __type_list<__align_type<unsigned short>, - __type_list<__align_type<unsigned int>, - __type_list<__align_type<unsigned long>, - __type_list<__align_type<unsigned long long>, - __type_list<__align_type<double>, - __type_list<__align_type<long double>, - __type_list<__align_type<__struct_double>, - __type_list<__align_type<__struct_double4>, - __type_list<__align_type<int*>, - __nat - > > > > > > > > > > __all_types; +struct __struct_double { + long double __lx; +}; +struct __struct_double4 { + double __lx[4]; +}; + +// clang-format off +typedef __type_list<__align_type<unsigned char>, + __type_list<__align_type<unsigned short>, + __type_list<__align_type<unsigned int>, + __type_list<__align_type<unsigned long>, + __type_list<__align_type<unsigned long long>, + __type_list<__align_type<double>, + __type_list<__align_type<long double>, + __type_list<__align_type<__struct_double>, + __type_list<__align_type<__struct_double4>, + __type_list<__align_type<int*>, + __nat + > > > > > > > > > > __all_types; +// clang-format on template <size_t _Align> struct _ALIGNAS(_Align) __fallback_overaligned {}; -template <class _TL, size_t _Align> struct __find_pod; +template <class _TL, size_t _Align> +struct __find_pod; template <class _Hp, size_t _Align> -struct __find_pod<__type_list<_Hp, __nat>, _Align> -{ - typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, __fallback_overaligned<_Align> > type; +struct __find_pod<__type_list<_Hp, __nat>, _Align> { + typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, __fallback_overaligned<_Align> > type; }; template <class _Hp, class _Tp, size_t _Align> -struct __find_pod<__type_list<_Hp, _Tp>, _Align> -{ - typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, typename __find_pod<_Tp, _Align>::type> type; +struct __find_pod<__type_list<_Hp, _Tp>, _Align> { + typedef __conditional_t<_Align == _Hp::value, typename _Hp::type, typename __find_pod<_Tp, _Align>::type> type; }; -template <class _TL, size_t _Len> struct __find_max_align; +template <class _TL, size_t _Len> +struct __find_max_align; template <class _Hp, size_t _Len> struct __find_max_align<__type_list<_Hp, __nat>, _Len> : public integral_constant<size_t, _Hp::value> {}; template <size_t _Len, size_t _A1, size_t _A2> -struct __select_align -{ +struct __select_align { private: - static const size_t __min = _A2 < _A1 ? _A2 : _A1; - static const size_t __max = _A1 < _A2 ? _A2 : _A1; + static const size_t __min = _A2 < _A1 ? _A2 : _A1; + static const size_t __max = _A1 < _A2 ? _A2 : _A1; + public: - static const size_t value = _Len < __max ? __min : __max; + static const size_t value = _Len < __max ? __min : __max; }; template <class _Hp, class _Tp, size_t _Len> @@ -83,34 +87,30 @@ struct __find_max_align<__type_list<_Hp, _Tp>, _Len> : public integral_constant<size_t, __select_align<_Len, _Hp::value, __find_max_align<_Tp, _Len>::value>::value> {}; template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value> -struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage -{ - typedef typename __find_pod<__all_types, _Align>::type _Aligner; - union type - { - _Aligner __align; - unsigned char __data[(_Len + _Align - 1)/_Align * _Align]; - }; +struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage { + typedef typename __find_pod<__all_types, _Align>::type _Aligner; + union type { + _Aligner __align; + unsigned char __data[(_Len + _Align - 1) / _Align * _Align]; + }; }; -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 - _LIBCPP_SUPPRESS_DEPRECATED_PUSH +_LIBCPP_SUPPRESS_DEPRECATED_PUSH template <size_t _Len, size_t _Align = __find_max_align<__all_types, _Len>::value> - using aligned_storage_t _LIBCPP_DEPRECATED_IN_CXX23 = typename aligned_storage<_Len, _Align>::type; - _LIBCPP_SUPPRESS_DEPRECATED_POP +using aligned_storage_t _LIBCPP_DEPRECATED_IN_CXX23 = typename aligned_storage<_Len, _Align>::type; +_LIBCPP_SUPPRESS_DEPRECATED_POP #endif -#define _CREATE_ALIGNED_STORAGE_SPECIALIZATION(n) \ -template <size_t _Len>\ -struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage<_Len, n>\ -{\ - struct _ALIGNAS(n) type\ - {\ - unsigned char __lx[(_Len + n - 1)/n * n];\ - };\ -} +#define _CREATE_ALIGNED_STORAGE_SPECIALIZATION(n) \ + template <size_t _Len> \ + struct _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_TEMPLATE_VIS aligned_storage<_Len, n> { \ + struct _ALIGNAS(n) type { \ + unsigned char __lx[(_Len + n - 1) / n * n]; \ + }; \ + } _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x1); _CREATE_ALIGNED_STORAGE_SPECIALIZATION(0x2); diff --git a/libcxx/include/__type_traits/aligned_union.h b/libcxx/include/__type_traits/aligned_union.h index 2c64130da307..005ed9a096ea 100644 --- a/libcxx/include/__type_traits/aligned_union.h +++ b/libcxx/include/__type_traits/aligned_union.h @@ -20,33 +20,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <size_t _I0, size_t ..._In> +template <size_t _I0, size_t... _In> struct __static_max; template <size_t _I0> -struct __static_max<_I0> -{ - static const size_t value = _I0; +struct __static_max<_I0> { + static const size_t value = _I0; }; -template <size_t _I0, size_t _I1, size_t ..._In> -struct __static_max<_I0, _I1, _In...> -{ - static const size_t value = _I0 >= _I1 ? __static_max<_I0, _In...>::value : - __static_max<_I1, _In...>::value; +template <size_t _I0, size_t _I1, size_t... _In> +struct __static_max<_I0, _I1, _In...> { + static const size_t value = _I0 >= _I1 ? __static_max<_I0, _In...>::value : __static_max<_I1, _In...>::value; }; -template <size_t _Len, class _Type0, class ..._Types> -struct _LIBCPP_DEPRECATED_IN_CXX23 aligned_union -{ - static const size_t alignment_value = __static_max<_LIBCPP_PREFERRED_ALIGNOF(_Type0), - _LIBCPP_PREFERRED_ALIGNOF(_Types)...>::value; - static const size_t __len = __static_max<_Len, sizeof(_Type0), - sizeof(_Types)...>::value; - typedef typename aligned_storage<__len, alignment_value>::type type; +template <size_t _Len, class _Type0, class... _Types> +struct _LIBCPP_DEPRECATED_IN_CXX23 aligned_union { + static const size_t alignment_value = + __static_max<_LIBCPP_PREFERRED_ALIGNOF(_Type0), _LIBCPP_PREFERRED_ALIGNOF(_Types)...>::value; + static const size_t __len = __static_max<_Len, sizeof(_Type0), sizeof(_Types)...>::value; + typedef typename aligned_storage<__len, alignment_value>::type type; }; -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <size_t _Len, class... _Types> using aligned_union_t _LIBCPP_DEPRECATED_IN_CXX23 = typename aligned_union<_Len, _Types...>::type; #endif diff --git a/libcxx/include/__type_traits/alignment_of.h b/libcxx/include/__type_traits/alignment_of.h index 45b4cbcc2d7d..f2d069bf2488 100644 --- a/libcxx/include/__type_traits/alignment_of.h +++ b/libcxx/include/__type_traits/alignment_of.h @@ -19,10 +19,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS alignment_of - : public integral_constant<size_t, _LIBCPP_ALIGNOF(_Tp)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS alignment_of : public integral_constant<size_t, _LIBCPP_ALIGNOF(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr size_t alignment_of_v = _LIBCPP_ALIGNOF(_Tp); #endif diff --git a/libcxx/include/__type_traits/apply_cv.h b/libcxx/include/__type_traits/apply_cv.h index 680ff6ac7d91..7c6aabec8344 100644 --- a/libcxx/include/__type_traits/apply_cv.h +++ b/libcxx/include/__type_traits/apply_cv.h @@ -13,7 +13,6 @@ #include <__type_traits/is_const.h> #include <__type_traits/is_volatile.h> #include <__type_traits/remove_reference.h> -#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -21,55 +20,59 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp, class _Up, bool = is_const<__libcpp_remove_reference_t<_Tp> >::value, - bool = is_volatile<__libcpp_remove_reference_t<_Tp> >::value> -struct __apply_cv -{ - typedef _LIBCPP_NODEBUG _Up type; +template <class _Tp, + bool = is_const<__libcpp_remove_reference_t<_Tp> >::value, + bool = is_volatile<__libcpp_remove_reference_t<_Tp> >::value> +struct __apply_cv_impl { + template <class _Up> + using __apply _LIBCPP_NODEBUG = _Up; }; -template <class _Tp, class _Up> -struct __apply_cv<_Tp, _Up, true, false> -{ - typedef _LIBCPP_NODEBUG const _Up type; +template <class _Tp> +struct __apply_cv_impl<_Tp, true, false> { + template <class _Up> + using __apply _LIBCPP_NODEBUG = const _Up; }; -template <class _Tp, class _Up> -struct __apply_cv<_Tp, _Up, false, true> -{ - typedef volatile _Up type; +template <class _Tp> +struct __apply_cv_impl<_Tp, false, true> { + template <class _Up> + using __apply _LIBCPP_NODEBUG = volatile _Up; }; -template <class _Tp, class _Up> -struct __apply_cv<_Tp, _Up, true, true> -{ - typedef const volatile _Up type; +template <class _Tp> +struct __apply_cv_impl<_Tp, true, true> { + template <class _Up> + using __apply _LIBCPP_NODEBUG = const volatile _Up; }; -template <class _Tp, class _Up> -struct __apply_cv<_Tp&, _Up, false, false> -{ - typedef _Up& type; +template <class _Tp> +struct __apply_cv_impl<_Tp&, false, false> { + template <class _Up> + using __apply _LIBCPP_NODEBUG = _Up&; }; -template <class _Tp, class _Up> -struct __apply_cv<_Tp&, _Up, true, false> -{ - typedef const _Up& type; +template <class _Tp> +struct __apply_cv_impl<_Tp&, true, false> { + template <class _Up> + using __apply _LIBCPP_NODEBUG = const _Up&; }; -template <class _Tp, class _Up> -struct __apply_cv<_Tp&, _Up, false, true> -{ - typedef volatile _Up& type; +template <class _Tp> +struct __apply_cv_impl<_Tp&, false, true> { + template <class _Up> + using __apply _LIBCPP_NODEBUG = volatile _Up&; }; -template <class _Tp, class _Up> -struct __apply_cv<_Tp&, _Up, true, true> -{ - typedef const volatile _Up& type; +template <class _Tp> +struct __apply_cv_impl<_Tp&, true, true> { + template <class _Up> + using __apply _LIBCPP_NODEBUG = const volatile _Up&; }; +template <class _Tp, class _Up> +using __apply_cv_t _LIBCPP_NODEBUG = typename __apply_cv_impl<_Tp>::template __apply<_Up>; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_APPLY_CV_H diff --git a/libcxx/include/__type_traits/can_extract_key.h b/libcxx/include/__type_traits/can_extract_key.h index 454c56bfae9d..b8359d070881 100644 --- a/libcxx/include/__type_traits/can_extract_key.h +++ b/libcxx/include/__type_traits/can_extract_key.h @@ -40,16 +40,13 @@ struct __can_extract_key<_Pair, _Key, pair<_First, _Second> > // __can_extract_map_key uses true_type/false_type instead of the tags. // It returns true if _Key != _ContainerValueTy (the container is a map not a set) // and _ValTy == _Key. -template <class _ValTy, class _Key, class _ContainerValueTy, - class _RawValTy = __remove_const_ref_t<_ValTy> > -struct __can_extract_map_key - : integral_constant<bool, _IsSame<_RawValTy, _Key>::value> {}; +template <class _ValTy, class _Key, class _ContainerValueTy, class _RawValTy = __remove_const_ref_t<_ValTy> > +struct __can_extract_map_key : integral_constant<bool, _IsSame<_RawValTy, _Key>::value> {}; // This specialization returns __extract_key_fail_tag for non-map containers // because _Key == _ContainerValueTy template <class _ValTy, class _Key, class _RawValTy> -struct __can_extract_map_key<_ValTy, _Key, _Key, _RawValTy> - : false_type {}; +struct __can_extract_map_key<_ValTy, _Key, _Key, _RawValTy> : false_type {}; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/common_reference.h b/libcxx/include/__type_traits/common_reference.h index f9195865c89e..c802902eb19f 100644 --- a/libcxx/include/__type_traits/common_reference.h +++ b/libcxx/include/__type_traits/common_reference.h @@ -27,11 +27,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD // common_reference -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // Let COND_RES(X, Y) be: template <class _Xp, class _Yp> -using __cond_res = - decltype(false ? std::declval<_Xp(&)()>()() : std::declval<_Yp(&)()>()()); +using __cond_res = decltype(false ? std::declval<_Xp (&)()>()() : std::declval<_Yp (&)()>()()); // Let `XREF(A)` denote a unary alias template `T` such that `T<U>` denotes the same type as `U` // with the addition of `A`'s cv and reference qualifiers, for a non-reference cv-unqualified type @@ -39,47 +38,49 @@ using __cond_res = // [Note: `XREF(A)` is `__xref<A>::template __apply`] template <class _Tp> struct __xref { - template<class _Up> + template <class _Up> using __apply = __copy_cvref_t<_Tp, _Up>; }; // Given types A and B, let X be remove_reference_t<A>, let Y be remove_reference_t<B>, // and let COMMON-REF(A, B) be: -template<class _Ap, class _Bp, class _Xp = remove_reference_t<_Ap>, class _Yp = remove_reference_t<_Bp>> +template <class _Ap, class _Bp, class _Xp = remove_reference_t<_Ap>, class _Yp = remove_reference_t<_Bp>> struct __common_ref; -template<class _Xp, class _Yp> +template <class _Xp, class _Yp> using __common_ref_t = typename __common_ref<_Xp, _Yp>::__type; -template<class _Xp, class _Yp> +template <class _Xp, class _Yp> using __cv_cond_res = __cond_res<__copy_cv_t<_Xp, _Yp>&, __copy_cv_t<_Yp, _Xp>&>; - // If A and B are both lvalue reference types, COMMON-REF(A, B) is // COND-RES(COPYCV(X, Y)&, COPYCV(Y, X)&) if that type exists and is a reference type. -template<class _Ap, class _Bp, class _Xp, class _Yp> -requires requires { typename __cv_cond_res<_Xp, _Yp>; } && is_reference_v<__cv_cond_res<_Xp, _Yp>> -struct __common_ref<_Ap&, _Bp&, _Xp, _Yp> -{ - using __type = __cv_cond_res<_Xp, _Yp>; +// clang-format off +template <class _Ap, class _Bp, class _Xp, class _Yp> + requires + requires { typename __cv_cond_res<_Xp, _Yp>; } && + is_reference_v<__cv_cond_res<_Xp, _Yp>> +struct __common_ref<_Ap&, _Bp&, _Xp, _Yp> { + using __type = __cv_cond_res<_Xp, _Yp>; }; +// clang-format on // Otherwise, let C be remove_reference_t<COMMON-REF(X&, Y&)>&&. ... template <class _Xp, class _Yp> using __common_ref_C = remove_reference_t<__common_ref_t<_Xp&, _Yp&>>&&; - // .... If A and B are both rvalue reference types, C is well-formed, and // is_convertible_v<A, C> && is_convertible_v<B, C> is true, then COMMON-REF(A, B) is C. -template<class _Ap, class _Bp, class _Xp, class _Yp> -requires - requires { typename __common_ref_C<_Xp, _Yp>; } && - is_convertible_v<_Ap&&, __common_ref_C<_Xp, _Yp>> && - is_convertible_v<_Bp&&, __common_ref_C<_Xp, _Yp>> -struct __common_ref<_Ap&&, _Bp&&, _Xp, _Yp> -{ - using __type = __common_ref_C<_Xp, _Yp>; +// clang-format off +template <class _Ap, class _Bp, class _Xp, class _Yp> + requires + requires { typename __common_ref_C<_Xp, _Yp>; } && + is_convertible_v<_Ap&&, __common_ref_C<_Xp, _Yp>> && + is_convertible_v<_Bp&&, __common_ref_C<_Xp, _Yp>> +struct __common_ref<_Ap&&, _Bp&&, _Xp, _Yp> { + using __type = __common_ref_C<_Xp, _Yp>; }; +// clang-format on // Otherwise, let D be COMMON-REF(const X&, Y&). ... template <class _Tp, class _Up> @@ -87,21 +88,23 @@ using __common_ref_D = __common_ref_t<const _Tp&, _Up&>; // ... If A is an rvalue reference and B is an lvalue reference and D is well-formed and // is_convertible_v<A, D> is true, then COMMON-REF(A, B) is D. -template<class _Ap, class _Bp, class _Xp, class _Yp> -requires requires { typename __common_ref_D<_Xp, _Yp>; } && - is_convertible_v<_Ap&&, __common_ref_D<_Xp, _Yp>> -struct __common_ref<_Ap&&, _Bp&, _Xp, _Yp> -{ - using __type = __common_ref_D<_Xp, _Yp>; +// clang-format off +template <class _Ap, class _Bp, class _Xp, class _Yp> + requires + requires { typename __common_ref_D<_Xp, _Yp>; } && + is_convertible_v<_Ap&&, __common_ref_D<_Xp, _Yp>> +struct __common_ref<_Ap&&, _Bp&, _Xp, _Yp> { + using __type = __common_ref_D<_Xp, _Yp>; }; +// clang-format on // Otherwise, if A is an lvalue reference and B is an rvalue reference, then // COMMON-REF(A, B) is COMMON-REF(B, A). -template<class _Ap, class _Bp, class _Xp, class _Yp> +template <class _Ap, class _Bp, class _Xp, class _Yp> struct __common_ref<_Ap&, _Bp&&, _Xp, _Yp> : __common_ref<_Bp&&, _Ap&> {}; // Otherwise, COMMON-REF(A, B) is ill-formed. -template<class _Ap, class _Bp, class _Xp, class _Yp> +template <class _Ap, class _Bp, class _Xp, class _Yp> struct __common_ref {}; // Note C: For the common_reference trait applied to a parameter pack [...] @@ -113,75 +116,77 @@ template <class... _Types> using common_reference_t = typename common_reference<_Types...>::type; // bullet 1 - sizeof...(T) == 0 -template<> +template <> struct common_reference<> {}; // bullet 2 - sizeof...(T) == 1 template <class _Tp> -struct common_reference<_Tp> -{ - using type = _Tp; +struct common_reference<_Tp> { + using type = _Tp; }; // bullet 3 - sizeof...(T) == 2 -template <class _Tp, class _Up> struct __common_reference_sub_bullet3; -template <class _Tp, class _Up> struct __common_reference_sub_bullet2 : __common_reference_sub_bullet3<_Tp, _Up> {}; -template <class _Tp, class _Up> struct __common_reference_sub_bullet1 : __common_reference_sub_bullet2<_Tp, _Up> {}; +template <class _Tp, class _Up> +struct __common_reference_sub_bullet3; +template <class _Tp, class _Up> +struct __common_reference_sub_bullet2 : __common_reference_sub_bullet3<_Tp, _Up> {}; +template <class _Tp, class _Up> +struct __common_reference_sub_bullet1 : __common_reference_sub_bullet2<_Tp, _Up> {}; // sub-bullet 1 - If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, then // the member typedef `type` denotes that type. -template <class _Tp, class _Up> struct common_reference<_Tp, _Up> : __common_reference_sub_bullet1<_Tp, _Up> {}; +template <class _Tp, class _Up> +struct common_reference<_Tp, _Up> : __common_reference_sub_bullet1<_Tp, _Up> {}; template <class _Tp, class _Up> -requires is_reference_v<_Tp> && is_reference_v<_Up> && requires { typename __common_ref_t<_Tp, _Up>; } -struct __common_reference_sub_bullet1<_Tp, _Up> -{ - using type = __common_ref_t<_Tp, _Up>; + requires is_reference_v<_Tp> && is_reference_v<_Up> && requires { typename __common_ref_t<_Tp, _Up>; } +struct __common_reference_sub_bullet1<_Tp, _Up> { + using type = __common_ref_t<_Tp, _Up>; }; // sub-bullet 2 - Otherwise, if basic_common_reference<remove_cvref_t<T1>, remove_cvref_t<T2>, XREF(T1), XREF(T2)>::type // is well-formed, then the member typedef `type` denotes that type. -template <class, class, template <class> class, template <class> class> struct basic_common_reference {}; +template <class, class, template <class> class, template <class> class> +struct basic_common_reference {}; template <class _Tp, class _Up> -using __basic_common_reference_t = typename basic_common_reference< - remove_cvref_t<_Tp>, remove_cvref_t<_Up>, - __xref<_Tp>::template __apply, __xref<_Up>::template __apply>::type; +using __basic_common_reference_t = + typename basic_common_reference<remove_cvref_t<_Tp>, + remove_cvref_t<_Up>, + __xref<_Tp>::template __apply, + __xref<_Up>::template __apply>::type; template <class _Tp, class _Up> -requires requires { typename __basic_common_reference_t<_Tp, _Up>; } -struct __common_reference_sub_bullet2<_Tp, _Up> -{ - using type = __basic_common_reference_t<_Tp, _Up>; + requires requires { typename __basic_common_reference_t<_Tp, _Up>; } +struct __common_reference_sub_bullet2<_Tp, _Up> { + using type = __basic_common_reference_t<_Tp, _Up>; }; // sub-bullet 3 - Otherwise, if COND-RES(T1, T2) is well-formed, // then the member typedef `type` denotes that type. template <class _Tp, class _Up> -requires requires { typename __cond_res<_Tp, _Up>; } -struct __common_reference_sub_bullet3<_Tp, _Up> -{ - using type = __cond_res<_Tp, _Up>; + requires requires { typename __cond_res<_Tp, _Up>; } +struct __common_reference_sub_bullet3<_Tp, _Up> { + using type = __cond_res<_Tp, _Up>; }; - // sub-bullet 4 & 5 - Otherwise, if common_type_t<T1, T2> is well-formed, // then the member typedef `type` denotes that type. // - Otherwise, there shall be no member `type`. -template <class _Tp, class _Up> struct __common_reference_sub_bullet3 : common_type<_Tp, _Up> {}; +template <class _Tp, class _Up> +struct __common_reference_sub_bullet3 : common_type<_Tp, _Up> {}; // bullet 4 - If there is such a type `C`, the member typedef type shall denote the same type, if // any, as `common_reference_t<C, Rest...>`. template <class _Tp, class _Up, class _Vp, class... _Rest> -requires requires { typename common_reference_t<_Tp, _Up>; } -struct common_reference<_Tp, _Up, _Vp, _Rest...> - : common_reference<common_reference_t<_Tp, _Up>, _Vp, _Rest...> -{}; + requires requires { typename common_reference_t<_Tp, _Up>; } +struct common_reference<_Tp, _Up, _Vp, _Rest...> : common_reference<common_reference_t<_Tp, _Up>, _Vp, _Rest...> {}; // bullet 5 - Otherwise, there shall be no member `type`. -template <class...> struct common_reference {}; +template <class...> +struct common_reference {}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/common_type.h b/libcxx/include/__type_traits/common_type.h index 6d2df6c9b3e4..7f86fcaaace4 100644 --- a/libcxx/include/__type_traits/common_type.h +++ b/libcxx/include/__type_traits/common_type.h @@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // Let COND_RES(X, Y) be: template <class _Tp, class _Up> using __cond_type = decltype(false ? std::declval<_Tp>() : std::declval<_Up>()); @@ -33,9 +33,8 @@ struct __common_type3 {}; // sub-bullet 4 - "if COND_RES(CREF(D1), CREF(D2)) denotes a type..." template <class _Tp, class _Up> -struct __common_type3<_Tp, _Up, void_t<__cond_type<const _Tp&, const _Up&>>> -{ - using type = remove_cvref_t<__cond_type<const _Tp&, const _Up&>>; +struct __common_type3<_Tp, _Up, void_t<__cond_type<const _Tp&, const _Up&>>> { + using type = remove_cvref_t<__cond_type<const _Tp&, const _Up&>>; }; template <class _Tp, class _Up, class = void> @@ -47,50 +46,26 @@ struct __common_type2_imp {}; // sub-bullet 3 - "if decay_t<decltype(false ? declval<D1>() : declval<D2>())> ..." template <class _Tp, class _Up> -struct __common_type2_imp<_Tp, _Up, __void_t<decltype(true ? std::declval<_Tp>() : std::declval<_Up>())> > -{ - typedef _LIBCPP_NODEBUG typename decay<decltype( - true ? std::declval<_Tp>() : std::declval<_Up>() - )>::type type; +struct __common_type2_imp<_Tp, _Up, __void_t<decltype(true ? std::declval<_Tp>() : std::declval<_Up>())> > { + typedef _LIBCPP_NODEBUG __decay_t<decltype(true ? std::declval<_Tp>() : std::declval<_Up>())> type; }; template <class, class = void> struct __common_type_impl {}; -// Clang provides variadic templates in C++03 as an extension. -#if !defined(_LIBCPP_CXX03_LANG) || defined(__clang__) -# define _LIBCPP_OPTIONAL_PACK(...) , __VA_ARGS__ template <class... _Tp> struct __common_types; template <class... _Tp> struct _LIBCPP_TEMPLATE_VIS common_type; -#else -# define _LIBCPP_OPTIONAL_PACK(...) -struct __no_arg; -template <class _Tp, class _Up, class = __no_arg> -struct __common_types; -template <class _Tp = __no_arg, class _Up = __no_arg, class _Vp = __no_arg, - class _Unused = __no_arg> -struct common_type { - static_assert(sizeof(_Unused) == 0, - "common_type accepts at most 3 arguments in C++03"); -}; -#endif // _LIBCPP_CXX03_LANG template <class _Tp, class _Up> -struct __common_type_impl< - __common_types<_Tp, _Up>, __void_t<typename common_type<_Tp, _Up>::type> > -{ +struct __common_type_impl< __common_types<_Tp, _Up>, __void_t<typename common_type<_Tp, _Up>::type> > { typedef typename common_type<_Tp, _Up>::type type; }; -template <class _Tp, class _Up, class _Vp _LIBCPP_OPTIONAL_PACK(class... _Rest)> -struct __common_type_impl< - __common_types<_Tp, _Up, _Vp _LIBCPP_OPTIONAL_PACK(_Rest...)>, - __void_t<typename common_type<_Tp, _Up>::type> > - : __common_type_impl<__common_types<typename common_type<_Tp, _Up>::type, - _Vp _LIBCPP_OPTIONAL_PACK(_Rest...)> > { -}; +template <class _Tp, class _Up, class _Vp, class... _Rest> +struct __common_type_impl<__common_types<_Tp, _Up, _Vp, _Rest...>, __void_t<typename common_type<_Tp, _Up>::type> > + : __common_type_impl<__common_types<typename common_type<_Tp, _Up>::type, _Vp, _Rest...> > {}; // bullet 1 - sizeof...(Tp) == 0 @@ -100,33 +75,26 @@ struct _LIBCPP_TEMPLATE_VIS common_type<> {}; // bullet 2 - sizeof...(Tp) == 1 template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS common_type<_Tp> - : public common_type<_Tp, _Tp> {}; +struct _LIBCPP_TEMPLATE_VIS common_type<_Tp> : public common_type<_Tp, _Tp> {}; // bullet 3 - sizeof...(Tp) == 2 // sub-bullet 1 - "If is_same_v<T1, D1> is false or ..." template <class _Tp, class _Up> struct _LIBCPP_TEMPLATE_VIS common_type<_Tp, _Up> - : conditional< - _IsSame<_Tp, typename decay<_Tp>::type>::value && _IsSame<_Up, typename decay<_Up>::type>::value, - __common_type2_imp<_Tp, _Up>, - common_type<typename decay<_Tp>::type, typename decay<_Up>::type> - >::type -{}; + : conditional<_IsSame<_Tp, __decay_t<_Tp> >::value && _IsSame<_Up, __decay_t<_Up> >::value, + __common_type2_imp<_Tp, _Up>, + common_type<__decay_t<_Tp>, __decay_t<_Up> > >::type {}; // bullet 4 - sizeof...(Tp) > 2 -template <class _Tp, class _Up, class _Vp _LIBCPP_OPTIONAL_PACK(class... _Rest)> -struct _LIBCPP_TEMPLATE_VIS - common_type<_Tp, _Up, _Vp _LIBCPP_OPTIONAL_PACK(_Rest...)> - : __common_type_impl< - __common_types<_Tp, _Up, _Vp _LIBCPP_OPTIONAL_PACK(_Rest...)> > {}; - -#undef _LIBCPP_OPTIONAL_PACK +template <class _Tp, class _Up, class _Vp, class... _Rest> +struct _LIBCPP_TEMPLATE_VIS common_type<_Tp, _Up, _Vp, _Rest...> + : __common_type_impl<__common_types<_Tp, _Up, _Vp, _Rest...> > {}; -#if _LIBCPP_STD_VER > 11 -template <class ..._Tp> using common_type_t = typename common_type<_Tp...>::type; +#if _LIBCPP_STD_VER >= 14 +template <class... _Tp> +using common_type_t = typename common_type<_Tp...>::type; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/conditional.h b/libcxx/include/__type_traits/conditional.h index 6249812a1114..5b5445a83742 100644 --- a/libcxx/include/__type_traits/conditional.h +++ b/libcxx/include/__type_traits/conditional.h @@ -44,7 +44,7 @@ struct _LIBCPP_TEMPLATE_VIS conditional<false, _If, _Then> { using type _LIBCPP_NODEBUG = _Then; }; -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <bool _Bp, class _IfRes, class _ElseRes> using conditional_t _LIBCPP_NODEBUG = typename conditional<_Bp, _IfRes, _ElseRes>::type; #endif diff --git a/libcxx/include/__type_traits/conjunction.h b/libcxx/include/__type_traits/conjunction.h index 0d95347e9988..4bfa5a27300d 100644 --- a/libcxx/include/__type_traits/conjunction.h +++ b/libcxx/include/__type_traits/conjunction.h @@ -37,7 +37,7 @@ false_type __and_helper(...); template <class... _Pred> using _And _LIBCPP_NODEBUG = decltype(std::__and_helper<_Pred...>(0)); -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class...> struct conjunction : true_type {}; @@ -51,7 +51,7 @@ struct conjunction<_Arg, _Args...> : conditional_t<!bool(_Arg::value), _Arg, con template <class... _Args> inline constexpr bool conjunction_v = conjunction<_Args...>::value; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/copy_cv.h b/libcxx/include/__type_traits/copy_cv.h index 8e9bfe0a522f..3c4ee857f7bc 100644 --- a/libcxx/include/__type_traits/copy_cv.h +++ b/libcxx/include/__type_traits/copy_cv.h @@ -23,27 +23,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Let COPYCV(FROM, TO) be an alias for type TO with the addition of FROM's // top-level cv-qualifiers. template <class _From, class _To> -struct __copy_cv -{ - using type = _To; +struct __copy_cv { + using type = _To; }; template <class _From, class _To> -struct __copy_cv<const _From, _To> -{ - using type = typename add_const<_To>::type; +struct __copy_cv<const _From, _To> { + using type = typename add_const<_To>::type; }; template <class _From, class _To> -struct __copy_cv<volatile _From, _To> -{ - using type = typename add_volatile<_To>::type; +struct __copy_cv<volatile _From, _To> { + using type = typename add_volatile<_To>::type; }; template <class _From, class _To> -struct __copy_cv<const volatile _From, _To> -{ - using type = typename add_cv<_To>::type; +struct __copy_cv<const volatile _From, _To> { + using type = typename add_cv<_To>::type; }; template <class _From, class _To> diff --git a/libcxx/include/__type_traits/copy_cvref.h b/libcxx/include/__type_traits/copy_cvref.h index 8ec59b95a0ad..8bbf8efdf44d 100644 --- a/libcxx/include/__type_traits/copy_cvref.h +++ b/libcxx/include/__type_traits/copy_cvref.h @@ -21,21 +21,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _From, class _To> -struct __copy_cvref -{ - using type = __copy_cv_t<_From, _To>; +struct __copy_cvref { + using type = __copy_cv_t<_From, _To>; }; template <class _From, class _To> -struct __copy_cvref<_From&, _To> -{ - using type = __add_lvalue_reference_t<__copy_cv_t<_From, _To> >; +struct __copy_cvref<_From&, _To> { + using type = __add_lvalue_reference_t<__copy_cv_t<_From, _To> >; }; template <class _From, class _To> -struct __copy_cvref<_From&&, _To> -{ - using type = __add_rvalue_reference_t<__copy_cv_t<_From, _To> >; +struct __copy_cvref<_From&&, _To> { + using type = __add_rvalue_reference_t<__copy_cv_t<_From, _To> >; }; template <class _From, class _To> diff --git a/libcxx/include/__type_traits/datasizeof.h b/libcxx/include/__type_traits/datasizeof.h new file mode 100644 index 000000000000..019099a9cf18 --- /dev/null +++ b/libcxx/include/__type_traits/datasizeof.h @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_DATASIZEOF_H +#define _LIBCPP___TYPE_TRAITS_DATASIZEOF_H + +#include <__config> +#include <__type_traits/is_class.h> +#include <__type_traits/is_final.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// This trait provides the size of a type excluding any tail padding. +// +// It is useful in contexts where performing an operation using the full size of the class (including padding) may +// have unintended side effects, such as overwriting a derived class' member when writing the tail padding of a class +// through a pointer-to-base. + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp> +struct __libcpp_datasizeof { +#if __has_cpp_attribute(__no_unique_address__) + template <class = char> + struct _FirstPaddingByte { + [[__no_unique_address__]] _Tp __v_; + char __first_padding_byte_; + }; +#else + template <bool = __libcpp_is_final<_Tp>::value || !is_class<_Tp>::value> + struct _FirstPaddingByte : _Tp { + char __first_padding_byte_; + }; + + template <> + struct _FirstPaddingByte<true> { + _Tp __v_; + char __first_padding_byte_; + }; +#endif + + static const size_t value = offsetof(_FirstPaddingByte<>, __first_padding_byte_); +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_DATASIZEOF_H diff --git a/libcxx/include/__type_traits/decay.h b/libcxx/include/__type_traits/decay.h index f45d33b8fb4b..95dccaa29cbe 100644 --- a/libcxx/include/__type_traits/decay.h +++ b/libcxx/include/__type_traits/decay.h @@ -27,43 +27,45 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__decay) template <class _Tp> +using __decay_t _LIBCPP_NODEBUG = __decay(_Tp); + +template <class _Tp> struct decay { - using type _LIBCPP_NODEBUG = __decay(_Tp); + using type _LIBCPP_NODEBUG = __decay_t<_Tp>; }; + #else template <class _Up, bool> struct __decay { - typedef _LIBCPP_NODEBUG __remove_cv_t<_Up> type; + typedef _LIBCPP_NODEBUG __remove_cv_t<_Up> type; }; template <class _Up> struct __decay<_Up, true> { public: - typedef _LIBCPP_NODEBUG typename conditional - < - is_array<_Up>::value, - __add_pointer_t<__remove_extent_t<_Up> >, - typename conditional - < - is_function<_Up>::value, - typename add_pointer<_Up>::type, - __remove_cv_t<_Up> - >::type - >::type type; + typedef _LIBCPP_NODEBUG typename conditional< + is_array<_Up>::value, + __add_pointer_t<__remove_extent_t<_Up> >, + typename conditional<is_function<_Up>::value, typename add_pointer<_Up>::type, __remove_cv_t<_Up> >::type >::type + type; }; template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS decay -{ +struct _LIBCPP_TEMPLATE_VIS decay { private: - typedef _LIBCPP_NODEBUG __libcpp_remove_reference_t<_Tp> _Up; + typedef _LIBCPP_NODEBUG __libcpp_remove_reference_t<_Tp> _Up; + public: typedef _LIBCPP_NODEBUG typename __decay<_Up, __libcpp_is_referenceable<_Up>::value>::type type; }; + +template <class _Tp> +using __decay_t = typename decay<_Tp>::type; #endif // __has_builtin(__decay) -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using decay_t = typename decay<_Tp>::type; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using decay_t = __decay_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/disjunction.h b/libcxx/include/__type_traits/disjunction.h index 125f168acc3a..2c89528d9f2f 100644 --- a/libcxx/include/__type_traits/disjunction.h +++ b/libcxx/include/__type_traits/disjunction.h @@ -43,7 +43,7 @@ struct _OrImpl<false> { template <class... _Args> using _Or _LIBCPP_NODEBUG = typename _OrImpl<sizeof...(_Args) != 0>::template _Result<false_type, _Args...>; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class... _Args> struct disjunction : _Or<_Args...> {}; @@ -51,7 +51,7 @@ struct disjunction : _Or<_Args...> {}; template <class... _Args> inline constexpr bool disjunction_v = _Or<_Args...>::value; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/enable_if.h b/libcxx/include/__type_traits/enable_if.h index c5e8df45ea58..77da9622ca28 100644 --- a/libcxx/include/__type_traits/enable_if.h +++ b/libcxx/include/__type_traits/enable_if.h @@ -17,13 +17,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <bool, class _Tp = void> struct _LIBCPP_TEMPLATE_VIS enable_if {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS enable_if<true, _Tp> {typedef _Tp type;}; - -template <bool _Bp, class _Tp = void> using __enable_if_t _LIBCPP_NODEBUG = typename enable_if<_Bp, _Tp>::type; - -#if _LIBCPP_STD_VER > 11 -template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp, _Tp>::type; +template <bool, class _Tp = void> +struct _LIBCPP_TEMPLATE_VIS enable_if {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS enable_if<true, _Tp> { + typedef _Tp type; +}; + +template <bool _Bp, class _Tp = void> +using __enable_if_t _LIBCPP_NODEBUG = typename enable_if<_Bp, _Tp>::type; + +#if _LIBCPP_STD_VER >= 14 +template <bool _Bp, class _Tp = void> +using enable_if_t = typename enable_if<_Bp, _Tp>::type; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/extent.h b/libcxx/include/__type_traits/extent.h index 0a4d84e05e23..bab03fe997eb 100644 --- a/libcxx/include/__type_traits/extent.h +++ b/libcxx/include/__type_traits/extent.h @@ -21,32 +21,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__array_extent) -template<class _Tp, size_t _Dim = 0> -struct _LIBCPP_TEMPLATE_VIS extent - : integral_constant<size_t, __array_extent(_Tp, _Dim)> { }; +template <class _Tp, size_t _Dim = 0> +struct _LIBCPP_TEMPLATE_VIS extent : integral_constant<size_t, __array_extent(_Tp, _Dim)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp, unsigned _Ip = 0> inline constexpr size_t extent_v = __array_extent(_Tp, _Ip); -#endif +# endif #else // __has_builtin(__array_extent) -template <class _Tp, unsigned _Ip = 0> struct _LIBCPP_TEMPLATE_VIS extent - : public integral_constant<size_t, 0> {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS extent<_Tp[], 0> - : public integral_constant<size_t, 0> {}; -template <class _Tp, unsigned _Ip> struct _LIBCPP_TEMPLATE_VIS extent<_Tp[], _Ip> - : public integral_constant<size_t, extent<_Tp, _Ip-1>::value> {}; -template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS extent<_Tp[_Np], 0> - : public integral_constant<size_t, _Np> {}; -template <class _Tp, size_t _Np, unsigned _Ip> struct _LIBCPP_TEMPLATE_VIS extent<_Tp[_Np], _Ip> - : public integral_constant<size_t, extent<_Tp, _Ip-1>::value> {}; - -#if _LIBCPP_STD_VER > 14 +template <class _Tp, unsigned _Ip = 0> +struct _LIBCPP_TEMPLATE_VIS extent : public integral_constant<size_t, 0> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS extent<_Tp[], 0> : public integral_constant<size_t, 0> {}; +template <class _Tp, unsigned _Ip> +struct _LIBCPP_TEMPLATE_VIS extent<_Tp[], _Ip> : public integral_constant<size_t, extent<_Tp, _Ip - 1>::value> {}; +template <class _Tp, size_t _Np> +struct _LIBCPP_TEMPLATE_VIS extent<_Tp[_Np], 0> : public integral_constant<size_t, _Np> {}; +template <class _Tp, size_t _Np, unsigned _Ip> +struct _LIBCPP_TEMPLATE_VIS extent<_Tp[_Np], _Ip> : public integral_constant<size_t, extent<_Tp, _Ip - 1>::value> {}; + +# if _LIBCPP_STD_VER >= 17 template <class _Tp, unsigned _Ip = 0> inline constexpr size_t extent_v = extent<_Tp, _Ip>::value; -#endif +# endif #endif // __has_builtin(__array_extent) diff --git a/libcxx/include/__type_traits/has_unique_object_representation.h b/libcxx/include/__type_traits/has_unique_object_representation.h index d6f75c9ce5c9..c0ada5618f0e 100644 --- a/libcxx/include/__type_traits/has_unique_object_representation.h +++ b/libcxx/include/__type_traits/has_unique_object_representation.h @@ -20,11 +20,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS has_unique_object_representations - : public integral_constant<bool, - __has_unique_object_representations(remove_cv_t<remove_all_extents_t<_Tp>>)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS has_unique_object_representations + : public integral_constant<bool, __has_unique_object_representations(remove_cv_t<remove_all_extents_t<_Tp>>)> {}; template <class _Tp> inline constexpr bool has_unique_object_representations_v = has_unique_object_representations<_Tp>::value; diff --git a/libcxx/include/__type_traits/has_virtual_destructor.h b/libcxx/include/__type_traits/has_virtual_destructor.h index e73a2b280cb0..4ce96e649e67 100644 --- a/libcxx/include/__type_traits/has_virtual_destructor.h +++ b/libcxx/include/__type_traits/has_virtual_destructor.h @@ -18,10 +18,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS has_virtual_destructor - : public integral_constant<bool, __has_virtual_destructor(_Tp)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS has_virtual_destructor : public integral_constant<bool, __has_virtual_destructor(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool has_virtual_destructor_v = __has_virtual_destructor(_Tp); #endif diff --git a/libcxx/include/__type_traits/integral_constant.h b/libcxx/include/__type_traits/integral_constant.h index 2449d1a906e8..a3f4fd34057c 100644 --- a/libcxx/include/__type_traits/integral_constant.h +++ b/libcxx/include/__type_traits/integral_constant.h @@ -18,29 +18,26 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp, _Tp __v> -struct _LIBCPP_TEMPLATE_VIS integral_constant -{ - static _LIBCPP_CONSTEXPR const _Tp value = __v; - typedef _Tp value_type; +struct _LIBCPP_TEMPLATE_VIS integral_constant { + static _LIBCPP_CONSTEXPR const _Tp value = __v; + typedef _Tp value_type; typedef integral_constant type; - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR operator value_type() const _NOEXCEPT {return value;} -#if _LIBCPP_STD_VER > 11 - _LIBCPP_INLINE_VISIBILITY - constexpr value_type operator ()() const _NOEXCEPT {return value;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator value_type() const _NOEXCEPT { return value; } +#if _LIBCPP_STD_VER >= 14 + _LIBCPP_INLINE_VISIBILITY constexpr value_type operator()() const _NOEXCEPT { return value; } #endif }; template <class _Tp, _Tp __v> _LIBCPP_CONSTEXPR const _Tp integral_constant<_Tp, __v>::value; -typedef integral_constant<bool, true> true_type; +typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, false> false_type; template <bool _Val> using _BoolConstant _LIBCPP_NODEBUG = integral_constant<bool, _Val>; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <bool __b> using bool_constant = integral_constant<bool, __b>; #endif diff --git a/libcxx/include/__type_traits/invoke.h b/libcxx/include/__type_traits/invoke.h new file mode 100644 index 000000000000..f3c00e7ede7c --- /dev/null +++ b/libcxx/include/__type_traits/invoke.h @@ -0,0 +1,461 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_INVOKE_H +#define _LIBCPP___TYPE_TRAITS_INVOKE_H + +#include <__config> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/apply_cv.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_base_of.h> +#include <__type_traits/is_core_convertible.h> +#include <__type_traits/is_member_function_pointer.h> +#include <__type_traits/is_member_object_pointer.h> +#include <__type_traits/is_reference_wrapper.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_void.h> +#include <__type_traits/nat.h> +#include <__type_traits/remove_cv.h> +#include <__utility/declval.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __any { + __any(...); +}; + +template <class _MP, bool _IsMemberFunctionPtr, bool _IsMemberObjectPtr> +struct __member_pointer_traits_imp {}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...), true, false> { + typedef _Class _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...), true, false> { + typedef _Class _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const, true, false> { + typedef _Class const _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const, true, false> { + typedef _Class const _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile, true, false> { + typedef _Class volatile _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile, true, false> { + typedef _Class volatile _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile, true, false> { + typedef _Class const volatile _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile, true, false> { + typedef _Class const volatile _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...)&, true, false> { + typedef _Class& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...)&, true, false> { + typedef _Class& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&, true, false> { + typedef _Class const& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&, true, false> { + typedef _Class const& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&, true, false> { + typedef _Class volatile& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&, true, false> { + typedef _Class volatile& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&, true, false> { + typedef _Class const volatile& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&, true, false> { + typedef _Class const volatile& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...)&&, true, false> { + typedef _Class&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...)&&, true, false> { + typedef _Class&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&&, true, false> { + typedef _Class const&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&&, true, false> { + typedef _Class const&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&&, true, false> { + typedef _Class volatile&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&&, true, false> { + typedef _Class volatile&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&&, true, false> { + typedef _Class const volatile&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param...); +}; + +template <class _Rp, class _Class, class... _Param> +struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&&, true, false> { + typedef _Class const volatile&& _ClassType; + typedef _Rp _ReturnType; + typedef _Rp(_FnType)(_Param..., ...); +}; + +template <class _Rp, class _Class> +struct __member_pointer_traits_imp<_Rp _Class::*, false, true> { + typedef _Class _ClassType; + typedef _Rp _ReturnType; +}; + +template <class _MP> +struct __member_pointer_traits + : public __member_pointer_traits_imp<__remove_cv_t<_MP>, + is_member_function_pointer<_MP>::value, + is_member_object_pointer<_MP>::value> { + // typedef ... _ClassType; + // typedef ... _ReturnType; + // typedef ... _FnType; +}; + +template <class _DecayedFp> +struct __member_pointer_class_type {}; + +template <class _Ret, class _ClassType> +struct __member_pointer_class_type<_Ret _ClassType::*> { + typedef _ClassType type; +}; + +template <class _Fp, + class _A0, + class _DecayFp = __decay_t<_Fp>, + class _DecayA0 = __decay_t<_A0>, + class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> +using __enable_if_bullet1 = + typename enable_if<is_member_function_pointer<_DecayFp>::value && is_base_of<_ClassT, _DecayA0>::value >::type; + +template <class _Fp, class _A0, class _DecayFp = __decay_t<_Fp>, class _DecayA0 = __decay_t<_A0> > +using __enable_if_bullet2 = + typename enable_if<is_member_function_pointer<_DecayFp>::value && __is_reference_wrapper<_DecayA0>::value >::type; + +template <class _Fp, + class _A0, + class _DecayFp = __decay_t<_Fp>, + class _DecayA0 = __decay_t<_A0>, + class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> +using __enable_if_bullet3 = + typename enable_if<is_member_function_pointer<_DecayFp>::value && !is_base_of<_ClassT, _DecayA0>::value && + !__is_reference_wrapper<_DecayA0>::value >::type; + +template <class _Fp, + class _A0, + class _DecayFp = __decay_t<_Fp>, + class _DecayA0 = __decay_t<_A0>, + class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> +using __enable_if_bullet4 = + typename enable_if<is_member_object_pointer<_DecayFp>::value && is_base_of<_ClassT, _DecayA0>::value >::type; + +template <class _Fp, class _A0, class _DecayFp = __decay_t<_Fp>, class _DecayA0 = __decay_t<_A0> > +using __enable_if_bullet5 = + typename enable_if<is_member_object_pointer<_DecayFp>::value && __is_reference_wrapper<_DecayA0>::value >::type; + +template <class _Fp, + class _A0, + class _DecayFp = __decay_t<_Fp>, + class _DecayA0 = __decay_t<_A0>, + class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> +using __enable_if_bullet6 = + typename enable_if<is_member_object_pointer<_DecayFp>::value && !is_base_of<_ClassT, _DecayA0>::value && + !__is_reference_wrapper<_DecayA0>::value >::type; + +// __invoke forward declarations + +// fall back - none of the bullets + +template <class... _Args> +__nat __invoke(__any, _Args&&... __args); + +// bullets 1, 2 and 3 + +// clang-format off +template <class _Fp, class _A0, class... _Args, class = __enable_if_bullet1<_Fp, _A0> > +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +decltype((std::declval<_A0>().*std::declval<_Fp>())(std::declval<_Args>()...)) +__invoke(_Fp&& __f, _A0&& __a0, _Args&&... __args) + _NOEXCEPT_(noexcept((static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...))) + { return (static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...); } + +template <class _Fp, class _A0, class... _Args, class = __enable_if_bullet2<_Fp, _A0> > +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +decltype((std::declval<_A0>().get().*std::declval<_Fp>())(std::declval<_Args>()...)) +__invoke(_Fp&& __f, _A0&& __a0, _Args&&... __args) + _NOEXCEPT_(noexcept((__a0.get().*__f)(static_cast<_Args&&>(__args)...))) + { return (__a0.get().*__f)(static_cast<_Args&&>(__args)...); } + +template <class _Fp, class _A0, class... _Args, class = __enable_if_bullet3<_Fp, _A0> > +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +decltype(((*std::declval<_A0>()).*std::declval<_Fp>())(std::declval<_Args>()...)) +__invoke(_Fp&& __f, _A0&& __a0, _Args&&... __args) + _NOEXCEPT_(noexcept(((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...))) + { return ((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...); } + +// bullets 4, 5 and 6 + +template <class _Fp, class _A0, class = __enable_if_bullet4<_Fp, _A0> > +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +decltype(std::declval<_A0>().*std::declval<_Fp>()) +__invoke(_Fp&& __f, _A0&& __a0) + _NOEXCEPT_(noexcept(static_cast<_A0&&>(__a0).*__f)) + { return static_cast<_A0&&>(__a0).*__f; } + +template <class _Fp, class _A0, class = __enable_if_bullet5<_Fp, _A0> > +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +decltype(std::declval<_A0>().get().*std::declval<_Fp>()) +__invoke(_Fp&& __f, _A0&& __a0) + _NOEXCEPT_(noexcept(__a0.get().*__f)) + { return __a0.get().*__f; } + +template <class _Fp, class _A0, class = __enable_if_bullet6<_Fp, _A0> > +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +decltype((*std::declval<_A0>()).*std::declval<_Fp>()) +__invoke(_Fp&& __f, _A0&& __a0) + _NOEXCEPT_(noexcept((*static_cast<_A0&&>(__a0)).*__f)) + { return (*static_cast<_A0&&>(__a0)).*__f; } + +// bullet 7 + +template <class _Fp, class... _Args> +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +decltype(std::declval<_Fp>()(std::declval<_Args>()...)) +__invoke(_Fp&& __f, _Args&&... __args) + _NOEXCEPT_(noexcept(static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...))) + { return static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...); } +// clang-format on + +// __invokable +template <class _Ret, class _Fp, class... _Args> +struct __invokable_r { + template <class _XFp, class... _XArgs> + static decltype(std::__invoke(std::declval<_XFp>(), std::declval<_XArgs>()...)) __try_call(int); + template <class _XFp, class... _XArgs> + static __nat __try_call(...); + + // FIXME: Check that _Ret, _Fp, and _Args... are all complete types, cv void, + // or incomplete array types as required by the standard. + using _Result = decltype(__try_call<_Fp, _Args...>(0)); + + using type = __conditional_t<_IsNotSame<_Result, __nat>::value, + __conditional_t<is_void<_Ret>::value, true_type, __is_core_convertible<_Result, _Ret> >, + false_type>; + static const bool value = type::value; +}; +template <class _Fp, class... _Args> +using __invokable = __invokable_r<void, _Fp, _Args...>; + +template <bool _IsInvokable, bool _IsCVVoid, class _Ret, class _Fp, class... _Args> +struct __nothrow_invokable_r_imp { + static const bool value = false; +}; + +template <class _Ret, class _Fp, class... _Args> +struct __nothrow_invokable_r_imp<true, false, _Ret, _Fp, _Args...> { + typedef __nothrow_invokable_r_imp _ThisT; + + template <class _Tp> + static void __test_noexcept(_Tp) _NOEXCEPT; + +#ifdef _LIBCPP_CXX03_LANG + static const bool value = false; +#else + static const bool value = + noexcept(_ThisT::__test_noexcept<_Ret>(_VSTD::__invoke(std::declval<_Fp>(), std::declval<_Args>()...))); +#endif +}; + +template <class _Ret, class _Fp, class... _Args> +struct __nothrow_invokable_r_imp<true, true, _Ret, _Fp, _Args...> { +#ifdef _LIBCPP_CXX03_LANG + static const bool value = false; +#else + static const bool value = noexcept(_VSTD::__invoke(std::declval<_Fp>(), std::declval<_Args>()...)); +#endif +}; + +template <class _Ret, class _Fp, class... _Args> +using __nothrow_invokable_r = + __nothrow_invokable_r_imp<__invokable_r<_Ret, _Fp, _Args...>::value, is_void<_Ret>::value, _Ret, _Fp, _Args...>; + +template <class _Fp, class... _Args> +using __nothrow_invokable = __nothrow_invokable_r_imp<__invokable<_Fp, _Args...>::value, true, void, _Fp, _Args...>; + +template <class _Fp, class... _Args> +struct __invoke_of + : public enable_if<__invokable<_Fp, _Args...>::value, typename __invokable_r<void, _Fp, _Args...>::_Result> {}; + +template <class _Ret, bool = is_void<_Ret>::value> +struct __invoke_void_return_wrapper { + template <class... _Args> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static _Ret __call(_Args&&... __args) { + return std::__invoke(std::forward<_Args>(__args)...); + } +}; + +template <class _Ret> +struct __invoke_void_return_wrapper<_Ret, true> { + template <class... _Args> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __call(_Args&&... __args) { + std::__invoke(std::forward<_Args>(__args)...); + } +}; + +#if _LIBCPP_STD_VER >= 17 + +// is_invocable + +template <class _Fn, class... _Args> +struct _LIBCPP_TEMPLATE_VIS is_invocable : integral_constant<bool, __invokable<_Fn, _Args...>::value> {}; + +template <class _Ret, class _Fn, class... _Args> +struct _LIBCPP_TEMPLATE_VIS is_invocable_r : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {}; + +template <class _Fn, class... _Args> +inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; + +template <class _Ret, class _Fn, class... _Args> +inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value; + +// is_nothrow_invocable + +template <class _Fn, class... _Args> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable : integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value> { +}; + +template <class _Ret, class _Fn, class... _Args> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r + : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {}; + +template <class _Fn, class... _Args> +inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value; + +template <class _Ret, class _Fn, class... _Args> +inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; + +template <class _Fn, class... _Args> +struct _LIBCPP_TEMPLATE_VIS invoke_result : __invoke_of<_Fn, _Args...> {}; + +template <class _Fn, class... _Args> +using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; + +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_INVOKE_H diff --git a/libcxx/include/__type_traits/is_abstract.h b/libcxx/include/__type_traits/is_abstract.h index c74b3284f75d..4aa456be1c48 100644 --- a/libcxx/include/__type_traits/is_abstract.h +++ b/libcxx/include/__type_traits/is_abstract.h @@ -18,10 +18,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_abstract - : public integral_constant<bool, __is_abstract(_Tp)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_abstract : public integral_constant<bool, __is_abstract(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_abstract_v = __is_abstract(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_aggregate.h b/libcxx/include/__type_traits/is_aggregate.h index ea9de84f96d0..4e0988071ade 100644 --- a/libcxx/include/__type_traits/is_aggregate.h +++ b/libcxx/include/__type_traits/is_aggregate.h @@ -18,15 +18,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS -is_aggregate : public integral_constant<bool, __is_aggregate(_Tp)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_aggregate : public integral_constant<bool, __is_aggregate(_Tp)> {}; template <class _Tp> inline constexpr bool is_aggregate_v = __is_aggregate(_Tp); -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_allocator.h b/libcxx/include/__type_traits/is_allocator.h index ee4154d7e4a4..144ffac4d7ce 100644 --- a/libcxx/include/__type_traits/is_allocator.h +++ b/libcxx/include/__type_traits/is_allocator.h @@ -21,15 +21,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template<typename _Alloc, typename = void, typename = void> +template <typename _Alloc, typename = void, typename = void> struct __is_allocator : false_type {}; -template<typename _Alloc> +template <typename _Alloc> struct __is_allocator<_Alloc, - __void_t<typename _Alloc::value_type>, - __void_t<decltype(std::declval<_Alloc&>().allocate(size_t(0)))> - > - : true_type {}; + __void_t<typename _Alloc::value_type>, + __void_t<decltype(std::declval<_Alloc&>().allocate(size_t(0)))> > : true_type {}; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_always_bitcastable.h b/libcxx/include/__type_traits/is_always_bitcastable.h index 63304eb492b7..5bc650b41358 100644 --- a/libcxx/include/__type_traits/is_always_bitcastable.h +++ b/libcxx/include/__type_traits/is_always_bitcastable.h @@ -32,49 +32,52 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _From, class _To> struct __is_always_bitcastable { using _UnqualFrom = __remove_cv_t<_From>; - using _UnqualTo = __remove_cv_t<_To>; + using _UnqualTo = __remove_cv_t<_To>; + // clang-format off static const bool value = - // First, the simple case -- `From` and `To` are the same object type. - (is_same<_UnqualFrom, _UnqualTo>::value && is_trivially_copyable<_UnqualFrom>::value) || + // First, the simple case -- `From` and `To` are the same object type. + (is_same<_UnqualFrom, _UnqualTo>::value && is_trivially_copyable<_UnqualFrom>::value) || - // Beyond the simple case, we say that one type is "always bit-castable" to another if: - // - (1) `From` and `To` have the same value representation, and in addition every possible value of `From` has - // a corresponding value in the `To` type (in other words, the set of values of `To` is a superset of the set of - // values of `From`); - // - (2) When the corresponding values are not the same value (as, for example, between an unsigned and a signed - // integer, where a large positive value of the unsigned integer corresponds to a negative value in the signed - // integer type), the value of `To` that results from a bitwise copy of `From` is the same what would be produced - // by the built-in assignment (if it were defined for the two types, to which there are minor exceptions, e.g. - // built-in arrays). - // - // In practice, that means: - // - all integral types (except `bool`, see below) -- that is, character types and `int` types, both signed and - // unsigned... - // - as well as arrays of such types... - // - ...that have the same size. - // - // Other trivially-copyable types can't be validly bit-cast outside of their own type: - // - floating-point types normally have different sizes and thus aren't bit-castable between each other (fails #1); - // - integral types and floating-point types use different representations, so for example bit-casting an integral - // `1` to `float` results in a very small less-than-one value, unlike built-in assignment that produces `1.0` - // (fails #2); - // - booleans normally use only a single bit of their object representation; bit-casting an integer to a boolean - // will result in a boolean object with an incorrect representation, which is undefined behavior (fails #2). - // Bit-casting from a boolean into an integer, however, is valid; - // - enumeration types may have different ranges of possible values (fails #1); - // - for pointers, it is not guaranteed that pointers to different types use the same set of values to represent - // addresses, and the conversion results are explicitly unspecified for types with different alignments - // (fails #1); - // - for structs and unions it is impossible to determine whether the set of values of one of them is a subset of - // the other (fails #1); - // - there is no need to consider `nullptr_t` for practical purposes. - ( - sizeof(_From) == sizeof(_To) && - is_integral<_From>::value && - is_integral<_To>::value && - !is_same<_UnqualTo, bool>::value - ); + // Beyond the simple case, we say that one type is "always bit-castable" to another if: + // - (1) `From` and `To` have the same value representation, and in addition every possible value of `From` has + // a corresponding value in the `To` type (in other words, the set of values of `To` is a superset of the set of + // values of `From`); + // - (2) When the corresponding values are not the same value (as, for example, between an unsigned and a signed + // integer, where a large positive value of the unsigned integer corresponds to a negative value in the signed + // integer type), the value of `To` that results from a bitwise copy of `From` is the same what would be + // produced by the built-in assignment (if it were defined for the two types, to which there are minor + // exceptions, e.g. built-in arrays). + // + // In practice, that means: + // - all integral types (except `bool`, see below) -- that is, character types and `int` types, both signed and + // unsigned... + // - as well as arrays of such types... + // - ...that have the same size. + // + // Other trivially-copyable types can't be validly bit-cast outside of their own type: + // - floating-point types normally have different sizes and thus aren't bit-castable between each other (fails + // #1); + // - integral types and floating-point types use different representations, so for example bit-casting an integral + // `1` to `float` results in a very small less-than-one value, unlike built-in assignment that produces `1.0` + // (fails #2); + // - booleans normally use only a single bit of their object representation; bit-casting an integer to a boolean + // will result in a boolean object with an incorrect representation, which is undefined behavior (fails #2). + // Bit-casting from a boolean into an integer, however, is valid; + // - enumeration types may have different ranges of possible values (fails #1); + // - for pointers, it is not guaranteed that pointers to different types use the same set of values to represent + // addresses, and the conversion results are explicitly unspecified for types with different alignments + // (fails #1); + // - for structs and unions it is impossible to determine whether the set of values of one of them is a subset of + // the other (fails #1); + // - there is no need to consider `nullptr_t` for practical purposes. + ( + sizeof(_From) == sizeof(_To) && + is_integral<_From>::value && + is_integral<_To>::value && + !is_same<_UnqualTo, bool>::value + ); + // clang-format on }; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_arithmetic.h b/libcxx/include/__type_traits/is_arithmetic.h index 6d631f41c7d4..c9713e1840a7 100644 --- a/libcxx/include/__type_traits/is_arithmetic.h +++ b/libcxx/include/__type_traits/is_arithmetic.h @@ -20,11 +20,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_arithmetic - : public integral_constant<bool, is_integral<_Tp>::value || - is_floating_point<_Tp>::value> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_arithmetic + : public integral_constant<bool, is_integral<_Tp>::value || is_floating_point<_Tp>::value> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_array.h b/libcxx/include/__type_traits/is_array.h index bc105908982c..5b0e0e6f46b8 100644 --- a/libcxx/include/__type_traits/is_array.h +++ b/libcxx/include/__type_traits/is_array.h @@ -24,26 +24,26 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_array) && 0 template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_array : _BoolConstant<__is_array(_Tp)> { }; +struct _LIBCPP_TEMPLATE_VIS is_array : _BoolConstant<__is_array(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_array_v = __is_array(_Tp); -#endif +# endif #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_array - : public false_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_array<_Tp[]> - : public true_type {}; -template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS is_array<_Tp[_Np]> - : public true_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_array : public false_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_array<_Tp[]> : public true_type {}; +template <class _Tp, size_t _Np> +struct _LIBCPP_TEMPLATE_VIS is_array<_Tp[_Np]> : public true_type {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_array_v = is_array<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_array) diff --git a/libcxx/include/__type_traits/is_assignable.h b/libcxx/include/__type_traits/is_assignable.h index 13cd682f53cb..11134b1c1aba 100644 --- a/libcxx/include/__type_traits/is_assignable.h +++ b/libcxx/include/__type_traits/is_assignable.h @@ -18,10 +18,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template<class _Tp, class _Up> -struct _LIBCPP_TEMPLATE_VIS is_assignable : _BoolConstant<__is_assignable(_Tp, _Up)> { }; +template <class _Tp, class _Up> +struct _LIBCPP_TEMPLATE_VIS is_assignable : _BoolConstant<__is_assignable(_Tp, _Up)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp, class _Arg> inline constexpr bool is_assignable_v = __is_assignable(_Tp, _Arg); #endif diff --git a/libcxx/include/__type_traits/is_base_of.h b/libcxx/include/__type_traits/is_base_of.h index 0e6dec0b5ee0..090abeeb54dc 100644 --- a/libcxx/include/__type_traits/is_base_of.h +++ b/libcxx/include/__type_traits/is_base_of.h @@ -19,10 +19,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Bp, class _Dp> -struct _LIBCPP_TEMPLATE_VIS is_base_of - : public integral_constant<bool, __is_base_of(_Bp, _Dp)> {}; +struct _LIBCPP_TEMPLATE_VIS is_base_of : public integral_constant<bool, __is_base_of(_Bp, _Dp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Bp, class _Dp> inline constexpr bool is_base_of_v = __is_base_of(_Bp, _Dp); #endif diff --git a/libcxx/include/__type_traits/is_bounded_array.h b/libcxx/include/__type_traits/is_bounded_array.h index 27de9dfd3864..211403d638d0 100644 --- a/libcxx/include/__type_traits/is_bounded_array.h +++ b/libcxx/include/__type_traits/is_bounded_array.h @@ -19,17 +19,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class> struct _LIBCPP_TEMPLATE_VIS __libcpp_is_bounded_array : false_type {}; -template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS __libcpp_is_bounded_array<_Tp[_Np]> : true_type {}; +template <class> +struct _LIBCPP_TEMPLATE_VIS __libcpp_is_bounded_array : false_type {}; +template <class _Tp, size_t _Np> +struct _LIBCPP_TEMPLATE_VIS __libcpp_is_bounded_array<_Tp[_Np]> : true_type {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 -template <class> struct _LIBCPP_TEMPLATE_VIS is_bounded_array : false_type {}; -template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS is_bounded_array<_Tp[_Np]> : true_type {}; +template <class> +struct _LIBCPP_TEMPLATE_VIS is_bounded_array : false_type {}; +template <class _Tp, size_t _Np> +struct _LIBCPP_TEMPLATE_VIS is_bounded_array<_Tp[_Np]> : true_type {}; template <class _Tp> -inline constexpr -bool is_bounded_array_v = is_bounded_array<_Tp>::value; +inline constexpr bool is_bounded_array_v = is_bounded_array<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_callable.h b/libcxx/include/__type_traits/is_callable.h index 445373c43b9d..49724fe892ee 100644 --- a/libcxx/include/__type_traits/is_callable.h +++ b/libcxx/include/__type_traits/is_callable.h @@ -19,12 +19,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template<class _Func, class... _Args, class = decltype(std::declval<_Func>()(std::declval<_Args>()...))> +template <class _Func, class... _Args, class = decltype(std::declval<_Func>()(std::declval<_Args>()...))> true_type __is_callable_helper(int); -template<class...> +template <class...> false_type __is_callable_helper(...); -template<class _Func, class... _Args> +template <class _Func, class... _Args> struct __is_callable : decltype(std::__is_callable_helper<_Func, _Args...>(0)) {}; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_class.h b/libcxx/include/__type_traits/is_class.h index 031430f6654d..034f76a7865e 100644 --- a/libcxx/include/__type_traits/is_class.h +++ b/libcxx/include/__type_traits/is_class.h @@ -18,10 +18,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_class - : public integral_constant<bool, __is_class(_Tp)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_class : public integral_constant<bool, __is_class(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_class_v = __is_class(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_compound.h b/libcxx/include/__type_traits/is_compound.h index 1395ed8d417f..cd208ceab288 100644 --- a/libcxx/include/__type_traits/is_compound.h +++ b/libcxx/include/__type_traits/is_compound.h @@ -21,23 +21,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_compound) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_compound : _BoolConstant<__is_compound(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_compound : _BoolConstant<__is_compound(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_compound_v = __is_compound(_Tp); -#endif +# endif #else // __has_builtin(__is_compound) -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_compound - : public integral_constant<bool, !is_fundamental<_Tp>::value> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_compound : public integral_constant<bool, !is_fundamental<_Tp>::value> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_compound_v = is_compound<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_compound) diff --git a/libcxx/include/__type_traits/is_const.h b/libcxx/include/__type_traits/is_const.h index 42b892c58d50..47ef70872b79 100644 --- a/libcxx/include/__type_traits/is_const.h +++ b/libcxx/include/__type_traits/is_const.h @@ -21,22 +21,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_const) template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_const : _BoolConstant<__is_const(_Tp)> { }; +struct _LIBCPP_TEMPLATE_VIS is_const : _BoolConstant<__is_const(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_const_v = __is_const(_Tp); -#endif +# endif #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_const : public false_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_const<_Tp const> : public true_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_const : public false_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_const<_Tp const> : public true_type {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_const_v = is_const<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_const) diff --git a/libcxx/include/__type_traits/is_constant_evaluated.h b/libcxx/include/__type_traits/is_constant_evaluated.h index ae903da3487a..d7af462486e1 100644 --- a/libcxx/include/__type_traits/is_constant_evaluated.h +++ b/libcxx/include/__type_traits/is_constant_evaluated.h @@ -17,15 +17,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 -_LIBCPP_INLINE_VISIBILITY -inline constexpr bool is_constant_evaluated() noexcept { +#if _LIBCPP_STD_VER >= 20 +_LIBCPP_INLINE_VISIBILITY inline constexpr bool is_constant_evaluated() noexcept { return __builtin_is_constant_evaluated(); } #endif -_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR -bool __libcpp_is_constant_evaluated() _NOEXCEPT { return __builtin_is_constant_evaluated(); } +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR bool __libcpp_is_constant_evaluated() _NOEXCEPT { + return __builtin_is_constant_evaluated(); +} _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_constructible.h b/libcxx/include/__type_traits/is_constructible.h index cbe61b4329e3..4e62eb061fd5 100644 --- a/libcxx/include/__type_traits/is_constructible.h +++ b/libcxx/include/__type_traits/is_constructible.h @@ -18,13 +18,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp, class ..._Args> -struct _LIBCPP_TEMPLATE_VIS is_constructible - : public integral_constant<bool, __is_constructible(_Tp, _Args...)> -{ }; +template <class _Tp, class... _Args> +struct _LIBCPP_TEMPLATE_VIS is_constructible : public integral_constant<bool, __is_constructible(_Tp, _Args...)> {}; -#if _LIBCPP_STD_VER > 14 -template <class _Tp, class ..._Args> +#if _LIBCPP_STD_VER >= 17 +template <class _Tp, class... _Args> inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...); #endif diff --git a/libcxx/include/__type_traits/is_convertible.h b/libcxx/include/__type_traits/is_convertible.h index 5f77fd4d7064..b378a20cedeb 100644 --- a/libcxx/include/__type_traits/is_convertible.h +++ b/libcxx/include/__type_traits/is_convertible.h @@ -24,81 +24,87 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__is_convertible_to) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK) +#if __has_builtin(__is_convertible) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK) -template <class _T1, class _T2> struct _LIBCPP_TEMPLATE_VIS is_convertible - : public integral_constant<bool, __is_convertible_to(_T1, _T2)> {}; +template <class _T1, class _T2> +struct _LIBCPP_TEMPLATE_VIS is_convertible : public integral_constant<bool, __is_convertible(_T1, _T2)> {}; -#else // __has_builtin(__is_convertible_to) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK) +#elif __has_builtin(__is_convertible_to) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK) -namespace __is_convertible_imp -{ -template <class _Tp> void __test_convert(_Tp); +template <class _T1, class _T2> +struct _LIBCPP_TEMPLATE_VIS is_convertible : public integral_constant<bool, __is_convertible_to(_T1, _T2)> {}; + +// TODO: Remove this fallback when GCC < 13 support is no longer required. +// GCC 13 has the __is_convertible built-in. +#else // __has_builtin(__is_convertible_to) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK) + +namespace __is_convertible_imp { +template <class _Tp> +void __test_convert(_Tp); template <class _From, class _To, class = void> struct __is_convertible_test : public false_type {}; template <class _From, class _To> -struct __is_convertible_test<_From, _To, - decltype(__is_convertible_imp::__test_convert<_To>(std::declval<_From>()))> : public true_type -{}; - -template <class _Tp, bool _IsArray = is_array<_Tp>::value, - bool _IsFunction = is_function<_Tp>::value, - bool _IsVoid = is_void<_Tp>::value> - struct __is_array_function_or_void {enum {value = 0};}; -template <class _Tp> struct __is_array_function_or_void<_Tp, true, false, false> {enum {value = 1};}; -template <class _Tp> struct __is_array_function_or_void<_Tp, false, true, false> {enum {value = 2};}; -template <class _Tp> struct __is_array_function_or_void<_Tp, false, false, true> {enum {value = 3};}; -} +struct __is_convertible_test<_From, _To, decltype(__is_convertible_imp::__test_convert<_To>(std::declval<_From>()))> + : public true_type {}; + +// clang-format off +template <class _Tp, + bool _IsArray = is_array<_Tp>::value, + bool _IsFunction = is_function<_Tp>::value, + bool _IsVoid = is_void<_Tp>::value> + struct __is_array_function_or_void { enum { value = 0 }; }; +template <class _Tp> struct __is_array_function_or_void<_Tp, true, false, false> { enum { value = 1 }; }; +template <class _Tp> struct __is_array_function_or_void<_Tp, false, true, false> { enum { value = 2 }; }; +template <class _Tp> struct __is_array_function_or_void<_Tp, false, false, true> { enum { value = 3 }; }; +// clang-format on +} // namespace __is_convertible_imp template <class _Tp, - unsigned = __is_convertible_imp::__is_array_function_or_void<__libcpp_remove_reference_t<_Tp> >::value> -struct __is_convertible_check -{ - static const size_t __v = 0; + unsigned = __is_convertible_imp::__is_array_function_or_void<__libcpp_remove_reference_t<_Tp> >::value> +struct __is_convertible_check { + static const size_t __v = 0; }; template <class _Tp> -struct __is_convertible_check<_Tp, 0> -{ - static const size_t __v = sizeof(_Tp); +struct __is_convertible_check<_Tp, 0> { + static const size_t __v = sizeof(_Tp); }; -template <class _T1, class _T2, - unsigned _T1_is_array_function_or_void = __is_convertible_imp::__is_array_function_or_void<_T1>::value, - unsigned _T2_is_array_function_or_void = __is_convertible_imp::__is_array_function_or_void<_T2>::value> +template <class _T1, + class _T2, + unsigned _T1_is_array_function_or_void = __is_convertible_imp::__is_array_function_or_void<_T1>::value, + unsigned _T2_is_array_function_or_void = __is_convertible_imp::__is_array_function_or_void<_T2>::value> struct __is_convertible - : public integral_constant<bool, - __is_convertible_imp::__is_convertible_test<_T1, _T2>::value - > -{}; - -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 0, 1> : public false_type {}; -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 1> : public false_type {}; -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 1> : public false_type {}; -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 3, 1> : public false_type {}; - -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 0, 2> : public false_type {}; -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 2> : public false_type {}; -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 2> : public false_type {}; -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 3, 2> : public false_type {}; - -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 0, 3> : public false_type {}; -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 3> : public false_type {}; -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 3> : public false_type {}; -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 3, 3> : public true_type {}; - -template <class _T1, class _T2> struct _LIBCPP_TEMPLATE_VIS is_convertible - : public __is_convertible<_T1, _T2> -{ - static const size_t __complete_check1 = __is_convertible_check<_T1>::__v; - static const size_t __complete_check2 = __is_convertible_check<_T2>::__v; + : public integral_constant<bool, __is_convertible_imp::__is_convertible_test<_T1, _T2>::value >{}; + +// clang-format off +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 0, 1> : public false_type{}; +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 1> : public false_type{}; +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 1> : public false_type{}; +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 3, 1> : public false_type{}; + +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 0, 2> : public false_type{}; +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 2> : public false_type{}; +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 2> : public false_type{}; +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 3, 2> : public false_type{}; + +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 0, 3> : public false_type{}; +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 3> : public false_type{}; +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 3> : public false_type{}; +template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 3, 3> : public true_type{}; +// clang-format on + +template <class _T1, class _T2> +struct _LIBCPP_TEMPLATE_VIS is_convertible : public __is_convertible<_T1, _T2> { + static const size_t __complete_check1 = __is_convertible_check<_T1>::__v; + static const size_t __complete_check2 = __is_convertible_check<_T2>::__v; }; #endif // __has_builtin(__is_convertible_to) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _From, class _To> inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value; #endif diff --git a/libcxx/include/__type_traits/is_copy_assignable.h b/libcxx/include/__type_traits/is_copy_assignable.h index b3a965ff3726..e607ace54043 100644 --- a/libcxx/include/__type_traits/is_copy_assignable.h +++ b/libcxx/include/__type_traits/is_copy_assignable.h @@ -24,10 +24,9 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_copy_assignable : public integral_constant< bool, - __is_assignable(__add_lvalue_reference_t<_Tp>, - __add_lvalue_reference_t<typename add_const<_Tp>::type>)> {}; + __is_assignable(__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<typename add_const<_Tp>::type>)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_copy_constructible.h b/libcxx/include/__type_traits/is_copy_constructible.h index 053e15911b91..402f2b89875b 100644 --- a/libcxx/include/__type_traits/is_copy_constructible.h +++ b/libcxx/include/__type_traits/is_copy_constructible.h @@ -22,11 +22,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_copy_constructible - : public integral_constant< - bool, - __is_constructible(_Tp, __add_lvalue_reference_t<typename add_const<_Tp>::type>)> {}; + : public integral_constant<bool, __is_constructible(_Tp, __add_lvalue_reference_t<typename add_const<_Tp>::type>)> { +}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_copy_constructible_v = is_copy_constructible<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_core_convertible.h b/libcxx/include/__type_traits/is_core_convertible.h index 1ce407913052..0de177c7771f 100644 --- a/libcxx/include/__type_traits/is_core_convertible.h +++ b/libcxx/include/__type_traits/is_core_convertible.h @@ -27,9 +27,8 @@ template <class _Tp, class _Up, class = void> struct __is_core_convertible : public false_type {}; template <class _Tp, class _Up> -struct __is_core_convertible<_Tp, _Up, decltype( - static_cast<void(*)(_Up)>(0) ( static_cast<_Tp(*)()>(0)() ) -)> : public true_type {}; +struct __is_core_convertible<_Tp, _Up, decltype(static_cast<void (*)(_Up)>(0)(static_cast<_Tp (*)()>(0)()))> + : public true_type {}; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_default_constructible.h b/libcxx/include/__type_traits/is_default_constructible.h index d2180c6a8557..e73e9b98f5dc 100644 --- a/libcxx/include/__type_traits/is_default_constructible.h +++ b/libcxx/include/__type_traits/is_default_constructible.h @@ -19,11 +19,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_default_constructible - : public integral_constant<bool, __is_constructible(_Tp)> - {}; +struct _LIBCPP_TEMPLATE_VIS is_default_constructible : public integral_constant<bool, __is_constructible(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_default_constructible_v = __is_constructible(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_destructible.h b/libcxx/include/__type_traits/is_destructible.h index 376d74de86e9..3248b07d36ee 100644 --- a/libcxx/include/__type_traits/is_destructible.h +++ b/libcxx/include/__type_traits/is_destructible.h @@ -24,13 +24,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_destructible) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_destructible : _BoolConstant<__is_destructible(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_destructible : _BoolConstant<__is_destructible(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_destructible_v = __is_destructible(_Tp); -#endif +# endif #else // __has_builtin(__is_destructible) @@ -42,19 +42,19 @@ inline constexpr bool is_destructible_v = __is_destructible(_Tp); // where _Up is remove_all_extents<_Tp>::type template <class> -struct __is_destructible_apply { typedef int type; }; +struct __is_destructible_apply { + typedef int type; +}; template <typename _Tp> struct __is_destructor_wellformed { - template <typename _Tp1> - static true_type __test ( - typename __is_destructible_apply<decltype(std::declval<_Tp1&>().~_Tp1())>::type - ); + template <typename _Tp1> + static true_type __test(typename __is_destructible_apply<decltype(std::declval<_Tp1&>().~_Tp1())>::type); - template <typename _Tp1> - static false_type __test (...); + template <typename _Tp1> + static false_type __test(...); - static const bool value = decltype(__test<_Tp>(12))::value; + static const bool value = decltype(__test<_Tp>(12))::value; }; template <class _Tp, bool> @@ -62,12 +62,10 @@ struct __destructible_imp; template <class _Tp> struct __destructible_imp<_Tp, false> - : public integral_constant<bool, - __is_destructor_wellformed<__remove_all_extents_t<_Tp> >::value> {}; + : public integral_constant<bool, __is_destructor_wellformed<__remove_all_extents_t<_Tp> >::value> {}; template <class _Tp> -struct __destructible_imp<_Tp, true> - : public true_type {}; +struct __destructible_imp<_Tp, true> : public true_type {}; template <class _Tp, bool> struct __destructible_false; @@ -79,21 +77,18 @@ template <class _Tp> struct __destructible_false<_Tp, true> : public false_type {}; template <class _Tp> -struct is_destructible - : public __destructible_false<_Tp, is_function<_Tp>::value> {}; +struct is_destructible : public __destructible_false<_Tp, is_function<_Tp>::value> {}; template <class _Tp> -struct is_destructible<_Tp[]> - : public false_type {}; +struct is_destructible<_Tp[]> : public false_type {}; template <> -struct is_destructible<void> - : public false_type {}; +struct is_destructible<void> : public false_type {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_destructible_v = is_destructible<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_destructible) diff --git a/libcxx/include/__type_traits/is_empty.h b/libcxx/include/__type_traits/is_empty.h index 042b4e68074c..951d93b5a2f1 100644 --- a/libcxx/include/__type_traits/is_empty.h +++ b/libcxx/include/__type_traits/is_empty.h @@ -19,10 +19,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_empty - : public integral_constant<bool, __is_empty(_Tp)> {}; +struct _LIBCPP_TEMPLATE_VIS is_empty : public integral_constant<bool, __is_empty(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_empty_v = __is_empty(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_enum.h b/libcxx/include/__type_traits/is_enum.h index 4c1db415d5a6..77ca3ea10874 100644 --- a/libcxx/include/__type_traits/is_enum.h +++ b/libcxx/include/__type_traits/is_enum.h @@ -18,10 +18,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_enum - : public integral_constant<bool, __is_enum(_Tp)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_enum : public integral_constant<bool, __is_enum(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_enum_v = __is_enum(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_equality_comparable.h b/libcxx/include/__type_traits/is_equality_comparable.h new file mode 100644 index 000000000000..e8d3ce87961f --- /dev/null +++ b/libcxx/include/__type_traits/is_equality_comparable.h @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_IS_EQUALITY_COMPARABLE_H +#define _LIBCPP___TYPE_TRAITS_IS_EQUALITY_COMPARABLE_H + +#include <__config> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_void.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp, class _Up, class = void> +struct __is_equality_comparable : false_type {}; + +template <class _Tp, class _Up> +struct __is_equality_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>() == std::declval<_Up>())> > : true_type { +}; + +// A type is_trivially_equality_comparable if the expression `a == b` is equivalent to `std::memcmp(&a, &b, sizeof(T))` +// (with `a` and `b` being of type `T`). For the case where we compare two object of the same type, we can use +// __is_trivially_equality_comparable. We have special-casing for pointers which point to the same type ignoring +// cv-qualifications and comparing to void-pointers. +// +// The following types are not trivially equality comparable: +// floating-point types: different bit-patterns can compare equal. (e.g 0.0 and -0.0) +// enums: The user is allowed to specialize operator== for enums +// pointers that don't have the same type (ignoring cv-qualifiers): pointers to virtual bases are equality comparable, +// but don't have the same bit-pattern. An exception to this is comparing to a void-pointer. There the bit-pattern is +// always compared. + +template <class _Tp, class _Up> +struct __libcpp_is_trivially_equality_comparable_impl : false_type {}; + +template <class _Tp> +struct __libcpp_is_trivially_equality_comparable_impl<_Tp, _Tp> +#if __has_builtin(__is_trivially_equality_comparable) + : integral_constant<bool, __is_trivially_equality_comparable(_Tp) && __is_equality_comparable<_Tp, _Tp>::value> { +}; +#else + : is_integral<_Tp> { +}; +#endif // __has_builtin(__is_trivially_equality_comparable) + +template <class _Tp> +struct __libcpp_is_trivially_equality_comparable_impl<_Tp*, _Tp*> : true_type {}; + +// TODO: Use is_pointer_inverconvertible_base_of +template <class _Tp, class _Up> +struct __libcpp_is_trivially_equality_comparable_impl<_Tp*, _Up*> + : integral_constant< + bool, + __is_equality_comparable<_Tp*, _Up*>::value && + (is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >::value || is_void<_Tp>::value || is_void<_Up>::value)> { +}; + +template <class _Tp, class _Up> +using __libcpp_is_trivially_equality_comparable = + __libcpp_is_trivially_equality_comparable_impl<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_IS_EQUALITY_COMPARABLE_H diff --git a/libcxx/include/__type_traits/is_execution_policy.h b/libcxx/include/__type_traits/is_execution_policy.h new file mode 100644 index 000000000000..6884f17ba16c --- /dev/null +++ b/libcxx/include/__type_traits/is_execution_policy.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_IS_EXECUTION_POLICY_H +#define _LIBCPP___TYPE_TRAITS_IS_EXECUTION_POLICY_H + +#include <__config> +#include <__type_traits/remove_cvref.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class> +inline constexpr bool is_execution_policy_v = false; + +template <class> +inline constexpr bool __is_unsequenced_execution_policy_impl = false; + +template <class _Tp> +inline constexpr bool __is_unsequenced_execution_policy_v = + __is_unsequenced_execution_policy_impl<__remove_cvref_t<_Tp>>; + +template <class> +inline constexpr bool __is_parallel_execution_policy_impl = false; + +template <class _Tp> +inline constexpr bool __is_parallel_execution_policy_v = __is_parallel_execution_policy_impl<__remove_cvref_t<_Tp>>; + +namespace execution { +struct __disable_user_instantiations_tag { + explicit __disable_user_instantiations_tag() = default; +}; +} // namespace execution + +// TODO: Remove default argument once algorithms are using the new backend dispatching +template <class _ExecutionPolicy> +_LIBCPP_HIDE_FROM_ABI auto +__remove_parallel_policy(const _ExecutionPolicy& = _ExecutionPolicy{execution::__disable_user_instantiations_tag{}}); + +// Removes the "parallel" part of an execution policy. +// For example, turns par_unseq into unseq, and par into seq. +template <class _ExecutionPolicy> +using __remove_parallel_policy_t = decltype(std::__remove_parallel_policy<_ExecutionPolicy>()); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___TYPE_TRAITS_IS_EXECUTION_POLICY_H diff --git a/libcxx/include/__type_traits/is_final.h b/libcxx/include/__type_traits/is_final.h index 74ced23a14e0..499c5e3a1edc 100644 --- a/libcxx/include/__type_traits/is_final.h +++ b/libcxx/include/__type_traits/is_final.h @@ -18,15 +18,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS -__libcpp_is_final : public integral_constant<bool, __is_final(_Tp)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS __libcpp_is_final : public integral_constant<bool, __is_final(_Tp)> {}; -#if _LIBCPP_STD_VER > 11 -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS -is_final : public integral_constant<bool, __is_final(_Tp)> {}; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_final : public integral_constant<bool, __is_final(_Tp)> {}; #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_final_v = __is_final(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_floating_point.h b/libcxx/include/__type_traits/is_floating_point.h index 392844814b62..add34782dfa0 100644 --- a/libcxx/include/__type_traits/is_floating_point.h +++ b/libcxx/include/__type_traits/is_floating_point.h @@ -19,15 +19,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// clang-format off template <class _Tp> struct __libcpp_is_floating_point : public false_type {}; template <> struct __libcpp_is_floating_point<float> : public true_type {}; template <> struct __libcpp_is_floating_point<double> : public true_type {}; template <> struct __libcpp_is_floating_point<long double> : public true_type {}; +// clang-format on -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_floating_point - : public __libcpp_is_floating_point<__remove_cv_t<_Tp> > {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_floating_point : public __libcpp_is_floating_point<__remove_cv_t<_Tp> > {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_function.h b/libcxx/include/__type_traits/is_function.h index 53f34b39eb9a..f09f19adf4aa 100644 --- a/libcxx/include/__type_traits/is_function.h +++ b/libcxx/include/__type_traits/is_function.h @@ -33,7 +33,7 @@ struct _LIBCPP_TEMPLATE_VIS is_function #endif // __has_builtin(__is_function) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_function_v = is_function<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_fundamental.h b/libcxx/include/__type_traits/is_fundamental.h index 46f81a103583..57206e0d9deb 100644 --- a/libcxx/include/__type_traits/is_fundamental.h +++ b/libcxx/include/__type_traits/is_fundamental.h @@ -22,25 +22,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_fundamental) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_fundamental : _BoolConstant<__is_fundamental(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_fundamental : _BoolConstant<__is_fundamental(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_fundamental_v = __is_fundamental(_Tp); -#endif +# endif #else // __has_builtin(__is_fundamental) -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_fundamental - : public integral_constant<bool, is_void<_Tp>::value || - __is_nullptr_t<_Tp>::value || - is_arithmetic<_Tp>::value> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_fundamental + : public integral_constant<bool, is_void<_Tp>::value || __is_nullptr_t<_Tp>::value || is_arithmetic<_Tp>::value> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_fundamental) diff --git a/libcxx/include/__type_traits/is_implicitly_default_constructible.h b/libcxx/include/__type_traits/is_implicitly_default_constructible.h index b77f94845fde..576166e52698 100644 --- a/libcxx/include/__type_traits/is_implicitly_default_constructible.h +++ b/libcxx/include/__type_traits/is_implicitly_default_constructible.h @@ -28,19 +28,17 @@ template <class _Tp> void __test_implicit_default_constructible(_Tp); template <class _Tp, class = void, class = typename is_default_constructible<_Tp>::type> -struct __is_implicitly_default_constructible - : false_type -{ }; +struct __is_implicitly_default_constructible : false_type {}; template <class _Tp> -struct __is_implicitly_default_constructible<_Tp, decltype(std::__test_implicit_default_constructible<_Tp const&>({})), true_type> - : true_type -{ }; +struct __is_implicitly_default_constructible<_Tp, + decltype(std::__test_implicit_default_constructible<_Tp const&>({})), + true_type> : true_type {}; template <class _Tp> -struct __is_implicitly_default_constructible<_Tp, decltype(std::__test_implicit_default_constructible<_Tp const&>({})), false_type> - : false_type -{ }; +struct __is_implicitly_default_constructible<_Tp, + decltype(std::__test_implicit_default_constructible<_Tp const&>({})), + false_type> : false_type {}; #endif // !C++03 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_integral.h b/libcxx/include/__type_traits/is_integral.h index 4dcc1918e337..26969885af8d 100644 --- a/libcxx/include/__type_traits/is_integral.h +++ b/libcxx/include/__type_traits/is_integral.h @@ -19,6 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// clang-format off template <class _Tp> struct __libcpp_is_integral { enum { value = 0 }; }; template <> struct __libcpp_is_integral<bool> { enum { value = 1 }; }; template <> struct __libcpp_is_integral<char> { enum { value = 1 }; }; @@ -44,26 +45,27 @@ template <> struct __libcpp_is_integral<unsigned long long> { enum { va template <> struct __libcpp_is_integral<__int128_t> { enum { value = 1 }; }; template <> struct __libcpp_is_integral<__uint128_t> { enum { value = 1 }; }; #endif +// clang-format on #if __has_builtin(__is_integral) template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_integral : _BoolConstant<__is_integral(_Tp)> { }; +struct _LIBCPP_TEMPLATE_VIS is_integral : _BoolConstant<__is_integral(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_integral_v = __is_integral(_Tp); -#endif +# endif #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_integral - : public _BoolConstant<__libcpp_is_integral<__remove_cv_t<_Tp> >::value> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_integral : public _BoolConstant<__libcpp_is_integral<__remove_cv_t<_Tp> >::value> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_integral_v = is_integral<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_integral) diff --git a/libcxx/include/__type_traits/is_literal_type.h b/libcxx/include/__type_traits/is_literal_type.h index be0174550593..81da34572c75 100644 --- a/libcxx/include/__type_traits/is_literal_type.h +++ b/libcxx/include/__type_traits/is_literal_type.h @@ -19,15 +19,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS) -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 is_literal_type - : public integral_constant<bool, __is_literal_type(_Tp)> - {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 is_literal_type + : public integral_constant<bool, __is_literal_type(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> _LIBCPP_DEPRECATED_IN_CXX17 inline constexpr bool is_literal_type_v = __is_literal_type(_Tp); -#endif // _LIBCPP_STD_VER > 14 -#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS) +# endif // _LIBCPP_STD_VER >= 17 +#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_member_function_pointer.h b/libcxx/include/__type_traits/is_member_function_pointer.h index c28f359d72e3..11c8a00c9975 100644 --- a/libcxx/include/__type_traits/is_member_function_pointer.h +++ b/libcxx/include/__type_traits/is_member_function_pointer.h @@ -21,41 +21,39 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct __libcpp_is_member_pointer { - enum { - __is_member = false, - __is_func = false, - __is_obj = false - }; +template <class _Tp> +struct __libcpp_is_member_pointer { + enum { __is_member = false, __is_func = false, __is_obj = false }; }; -template <class _Tp, class _Up> struct __libcpp_is_member_pointer<_Tp _Up::*> { +template <class _Tp, class _Up> +struct __libcpp_is_member_pointer<_Tp _Up::*> { enum { __is_member = true, - __is_func = is_function<_Tp>::value, - __is_obj = !__is_func, + __is_func = is_function<_Tp>::value, + __is_obj = !__is_func, }; }; #if __has_builtin(__is_member_function_pointer) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_member_function_pointer - : _BoolConstant<__is_member_function_pointer(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_member_function_pointer : _BoolConstant<__is_member_function_pointer(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_member_function_pointer_v = __is_member_function_pointer(_Tp); -#endif +# endif #else // __has_builtin(__is_member_function_pointer) -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_member_function_pointer - : public _BoolConstant< __libcpp_is_member_pointer<__remove_cv_t<_Tp> >::__is_func > {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_member_function_pointer + : public _BoolConstant<__libcpp_is_member_pointer<__remove_cv_t<_Tp> >::__is_func> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_member_function_pointer_v = is_member_function_pointer<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_member_function_pointer) diff --git a/libcxx/include/__type_traits/is_member_object_pointer.h b/libcxx/include/__type_traits/is_member_object_pointer.h index 5bab14b4bf56..9141f9da530f 100644 --- a/libcxx/include/__type_traits/is_member_object_pointer.h +++ b/libcxx/include/__type_traits/is_member_object_pointer.h @@ -20,24 +20,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_member_object_pointer) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_member_object_pointer - : _BoolConstant<__is_member_object_pointer(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_member_object_pointer : _BoolConstant<__is_member_object_pointer(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_member_object_pointer_v = __is_member_object_pointer(_Tp); -#endif +# endif #else // __has_builtin(__is_member_object_pointer) -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_member_object_pointer - : public _BoolConstant< __libcpp_is_member_pointer<__remove_cv_t<_Tp> >::__is_obj > {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_member_object_pointer + : public _BoolConstant<__libcpp_is_member_pointer<__remove_cv_t<_Tp> >::__is_obj> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_member_object_pointer_v = is_member_object_pointer<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_member_object_pointer) diff --git a/libcxx/include/__type_traits/is_member_pointer.h b/libcxx/include/__type_traits/is_member_pointer.h index 904d845f3327..4ca01d1c2fc8 100644 --- a/libcxx/include/__type_traits/is_member_pointer.h +++ b/libcxx/include/__type_traits/is_member_pointer.h @@ -21,23 +21,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_member_pointer) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_member_pointer : _BoolConstant<__is_member_pointer(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_member_pointer : _BoolConstant<__is_member_pointer(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_member_pointer_v = __is_member_pointer(_Tp); -#endif +# endif #else // __has_builtin(__is_member_pointer) -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_member_pointer - : public _BoolConstant< __libcpp_is_member_pointer<__remove_cv_t<_Tp> >::__is_member > {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_member_pointer + : public _BoolConstant<__libcpp_is_member_pointer<__remove_cv_t<_Tp> >::__is_member> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_member_pointer) diff --git a/libcxx/include/__type_traits/is_move_assignable.h b/libcxx/include/__type_traits/is_move_assignable.h index 3c7158b2ae06..867bc00d824a 100644 --- a/libcxx/include/__type_traits/is_move_assignable.h +++ b/libcxx/include/__type_traits/is_move_assignable.h @@ -22,11 +22,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_move_assignable - : public integral_constant< - bool, - __is_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> {}; + : public integral_constant<bool, __is_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_move_constructible.h b/libcxx/include/__type_traits/is_move_constructible.h index 667d10494fff..40ec4a070816 100644 --- a/libcxx/include/__type_traits/is_move_constructible.h +++ b/libcxx/include/__type_traits/is_move_constructible.h @@ -21,10 +21,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_move_constructible - : public integral_constant<bool, __is_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> - {}; + : public integral_constant<bool, __is_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_move_constructible_v = is_move_constructible<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_nothrow_assignable.h b/libcxx/include/__type_traits/is_nothrow_assignable.h index 0cd9d5d73414..cc5749331385 100644 --- a/libcxx/include/__type_traits/is_nothrow_assignable.h +++ b/libcxx/include/__type_traits/is_nothrow_assignable.h @@ -19,10 +19,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp, class _Arg> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_assignable - : public integral_constant<bool, __is_nothrow_assignable(_Tp, _Arg)> {}; +struct _LIBCPP_TEMPLATE_VIS is_nothrow_assignable : public integral_constant<bool, __is_nothrow_assignable(_Tp, _Arg)> { +}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp, class _Arg> inline constexpr bool is_nothrow_assignable_v = __is_nothrow_assignable(_Tp, _Arg); #endif diff --git a/libcxx/include/__type_traits/is_nothrow_constructible.h b/libcxx/include/__type_traits/is_nothrow_constructible.h index 8919b7933c2b..d4686d89fd96 100644 --- a/libcxx/include/__type_traits/is_nothrow_constructible.h +++ b/libcxx/include/__type_traits/is_nothrow_constructible.h @@ -24,52 +24,44 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_nothrow_constructible) -template < - class _Tp, class... _Args> +template < class _Tp, class... _Args> struct _LIBCPP_TEMPLATE_VIS is_nothrow_constructible : public integral_constant<bool, __is_nothrow_constructible(_Tp, _Args...)> {}; #else -template <bool, bool, class _Tp, class... _Args> struct __libcpp_is_nothrow_constructible; +template <bool, bool, class _Tp, class... _Args> +struct __libcpp_is_nothrow_constructible; template <class _Tp, class... _Args> -struct __libcpp_is_nothrow_constructible</*is constructible*/true, /*is reference*/false, _Tp, _Args...> - : public integral_constant<bool, noexcept(_Tp(std::declval<_Args>()...))> -{ -}; +struct __libcpp_is_nothrow_constructible</*is constructible*/ true, /*is reference*/ false, _Tp, _Args...> + : public integral_constant<bool, noexcept(_Tp(std::declval<_Args>()...))> {}; template <class _Tp> -void __implicit_conversion_to(_Tp) noexcept { } +void __implicit_conversion_to(_Tp) noexcept {} template <class _Tp, class _Arg> -struct __libcpp_is_nothrow_constructible</*is constructible*/true, /*is reference*/true, _Tp, _Arg> - : public integral_constant<bool, noexcept(_VSTD::__implicit_conversion_to<_Tp>(std::declval<_Arg>()))> -{ -}; +struct __libcpp_is_nothrow_constructible</*is constructible*/ true, /*is reference*/ true, _Tp, _Arg> + : public integral_constant<bool, noexcept(_VSTD::__implicit_conversion_to<_Tp>(std::declval<_Arg>()))> {}; template <class _Tp, bool _IsReference, class... _Args> -struct __libcpp_is_nothrow_constructible</*is constructible*/false, _IsReference, _Tp, _Args...> - : public false_type -{ +struct __libcpp_is_nothrow_constructible</*is constructible*/ false, _IsReference, _Tp, _Args...> : public false_type { }; template <class _Tp, class... _Args> struct _LIBCPP_TEMPLATE_VIS is_nothrow_constructible - : __libcpp_is_nothrow_constructible<is_constructible<_Tp, _Args...>::value, is_reference<_Tp>::value, _Tp, _Args...> -{ -}; + : __libcpp_is_nothrow_constructible<is_constructible<_Tp, _Args...>::value, + is_reference<_Tp>::value, + _Tp, + _Args...> {}; template <class _Tp, size_t _Ns> struct _LIBCPP_TEMPLATE_VIS is_nothrow_constructible<_Tp[_Ns]> - : __libcpp_is_nothrow_constructible<is_constructible<_Tp>::value, is_reference<_Tp>::value, _Tp> -{ -}; + : __libcpp_is_nothrow_constructible<is_constructible<_Tp>::value, is_reference<_Tp>::value, _Tp> {}; #endif // __has_builtin(__is_nothrow_constructible) - -#if _LIBCPP_STD_VER > 14 -template <class _Tp, class ..._Args> +#if _LIBCPP_STD_VER >= 17 +template <class _Tp, class... _Args> inline constexpr bool is_nothrow_constructible_v = is_nothrow_constructible<_Tp, _Args...>::value; #endif diff --git a/libcxx/include/__type_traits/is_nothrow_convertible.h b/libcxx/include/__type_traits/is_nothrow_convertible.h index a8ca1c4c413c..a8f8b4d063a1 100644 --- a/libcxx/include/__type_traits/is_nothrow_convertible.h +++ b/libcxx/include/__type_traits/is_nothrow_convertible.h @@ -24,29 +24,26 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <typename _Tp> -static void __test_noexcept(_Tp) noexcept; +void __test_noexcept(_Tp) noexcept; -template<typename _Fm, typename _To> -static bool_constant<noexcept(_VSTD::__test_noexcept<_To>(std::declval<_Fm>()))> -__is_nothrow_convertible_test(); +template <typename _Fm, typename _To> +bool_constant<noexcept(_VSTD::__test_noexcept<_To>(std::declval<_Fm>()))> __is_nothrow_convertible_test(); template <typename _Fm, typename _To> -struct __is_nothrow_convertible_helper: decltype(__is_nothrow_convertible_test<_Fm, _To>()) -{ }; +struct __is_nothrow_convertible_helper : decltype(__is_nothrow_convertible_test<_Fm, _To>()) {}; template <typename _Fm, typename _To> -struct is_nothrow_convertible : _Or< - _And<is_void<_To>, is_void<_Fm>>, - _Lazy<_And, is_convertible<_Fm, _To>, __is_nothrow_convertible_helper<_Fm, _To>> ->::type { }; +struct is_nothrow_convertible + : _Or<_And<is_void<_To>, is_void<_Fm>>, + _Lazy<_And, is_convertible<_Fm, _To>, __is_nothrow_convertible_helper<_Fm, _To> > >::type {}; template <typename _Fm, typename _To> inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<_Fm, _To>::value; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_nothrow_copy_assignable.h b/libcxx/include/__type_traits/is_nothrow_copy_assignable.h index 58f7d97a5578..a97e962b308c 100644 --- a/libcxx/include/__type_traits/is_nothrow_copy_assignable.h +++ b/libcxx/include/__type_traits/is_nothrow_copy_assignable.h @@ -22,13 +22,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_assignable - : public integral_constant< - bool, - __is_nothrow_assignable( - __add_lvalue_reference_t<_Tp>, - __add_lvalue_reference_t<typename add_const<_Tp>::type>)> {}; + : public integral_constant<bool, + __is_nothrow_assignable(__add_lvalue_reference_t<_Tp>, + __add_lvalue_reference_t<typename add_const<_Tp>::type>)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_nothrow_copy_assignable_v = is_nothrow_copy_assignable<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_nothrow_copy_constructible.h b/libcxx/include/__type_traits/is_nothrow_copy_constructible.h index ce17334b3f81..dd7f1d5ef627 100644 --- a/libcxx/include/__type_traits/is_nothrow_copy_constructible.h +++ b/libcxx/include/__type_traits/is_nothrow_copy_constructible.h @@ -24,9 +24,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD // TODO: remove this implementation once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106611 is fixed #ifdef _LIBCPP_COMPILER_GCC -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_constructible - : public is_nothrow_constructible<_Tp, - __add_lvalue_reference_t<typename add_const<_Tp>::type> > {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_constructible + : public is_nothrow_constructible<_Tp, __add_lvalue_reference_t<typename add_const<_Tp>::type> > {}; #else // _LIBCPP_COMPILER_GCC @@ -38,7 +38,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_constructible #endif // _LIBCPP_COMPILER_GCC -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_nothrow_default_constructible.h b/libcxx/include/__type_traits/is_nothrow_default_constructible.h index 91bffa5e466e..58f31f21b026 100644 --- a/libcxx/include/__type_traits/is_nothrow_default_constructible.h +++ b/libcxx/include/__type_traits/is_nothrow_default_constructible.h @@ -18,11 +18,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_nothrow_default_constructible - : public integral_constant<bool, __is_nothrow_constructible(_Tp)> - {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_default_constructible + : public integral_constant<bool, __is_nothrow_constructible(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_nothrow_default_constructible_v = __is_nothrow_constructible(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_nothrow_destructible.h b/libcxx/include/__type_traits/is_nothrow_destructible.h index 03ebf440492d..370ba27ecd1f 100644 --- a/libcxx/include/__type_traits/is_nothrow_destructible.h +++ b/libcxx/include/__type_traits/is_nothrow_destructible.h @@ -26,60 +26,45 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if !defined(_LIBCPP_CXX03_LANG) -template <bool, class _Tp> struct __libcpp_is_nothrow_destructible; +template <bool, class _Tp> +struct __libcpp_is_nothrow_destructible; template <class _Tp> -struct __libcpp_is_nothrow_destructible<false, _Tp> - : public false_type -{ -}; +struct __libcpp_is_nothrow_destructible<false, _Tp> : public false_type {}; template <class _Tp> struct __libcpp_is_nothrow_destructible<true, _Tp> - : public integral_constant<bool, noexcept(std::declval<_Tp>().~_Tp()) > -{ -}; + : public integral_constant<bool, noexcept(std::declval<_Tp>().~_Tp()) > {}; template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible - : public __libcpp_is_nothrow_destructible<is_destructible<_Tp>::value, _Tp> -{ -}; + : public __libcpp_is_nothrow_destructible<is_destructible<_Tp>::value, _Tp> {}; template <class _Tp, size_t _Ns> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible<_Tp[_Ns]> - : public is_nothrow_destructible<_Tp> -{ -}; +struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible<_Tp[_Ns]> : public is_nothrow_destructible<_Tp> {}; template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible<_Tp&> - : public true_type -{ -}; +struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible<_Tp&> : public true_type {}; template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible<_Tp&&> - : public true_type -{ -}; +struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible<_Tp&&> : public true_type {}; #else -template <class _Tp> struct __libcpp_nothrow_destructor - : public integral_constant<bool, is_scalar<_Tp>::value || - is_reference<_Tp>::value> {}; +template <class _Tp> +struct __libcpp_nothrow_destructor : public integral_constant<bool, is_scalar<_Tp>::value || is_reference<_Tp>::value> { +}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible - : public __libcpp_nothrow_destructor<__remove_all_extents_t<_Tp> > {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible : public __libcpp_nothrow_destructor<__remove_all_extents_t<_Tp> > { +}; template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible<_Tp[]> - : public false_type {}; +struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible<_Tp[]> : public false_type {}; #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_nothrow_move_assignable.h b/libcxx/include/__type_traits/is_nothrow_move_assignable.h index 18dcc9b232c6..aa87e369cd5d 100644 --- a/libcxx/include/__type_traits/is_nothrow_move_assignable.h +++ b/libcxx/include/__type_traits/is_nothrow_move_assignable.h @@ -22,12 +22,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_assignable - : public integral_constant< - bool, - __is_nothrow_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> { + : public integral_constant<bool, + __is_nothrow_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> { }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_nothrow_move_constructible.h b/libcxx/include/__type_traits/is_nothrow_move_constructible.h index ad8222a0e4c0..dab5a019b33b 100644 --- a/libcxx/include/__type_traits/is_nothrow_move_constructible.h +++ b/libcxx/include/__type_traits/is_nothrow_move_constructible.h @@ -23,19 +23,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD // TODO: remove this implementation once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106611 is fixed #ifndef _LIBCPP_COMPILER_GCC -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_constructible - : public integral_constant<bool, __is_nothrow_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> - {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_constructible + : public integral_constant<bool, __is_nothrow_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> {}; #else // _LIBCPP_COMPILER_GCC -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_constructible - : public is_nothrow_constructible<_Tp, __add_rvalue_reference_t<_Tp> > - {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_constructible + : public is_nothrow_constructible<_Tp, __add_rvalue_reference_t<_Tp> > {}; #endif // _LIBCPP_COMPILER_GCC -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_nothrow_move_constructible_v = is_nothrow_move_constructible<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_null_pointer.h b/libcxx/include/__type_traits/is_null_pointer.h index 4864cee11a10..c666f5f24759 100644 --- a/libcxx/include/__type_traits/is_null_pointer.h +++ b/libcxx/include/__type_traits/is_null_pointer.h @@ -20,21 +20,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct __is_nullptr_t_impl : public false_type {}; -template <> struct __is_nullptr_t_impl<nullptr_t> : public true_type {}; +template <class _Tp> +struct __is_nullptr_t_impl : public false_type {}; +template <> +struct __is_nullptr_t_impl<nullptr_t> : public true_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS __is_nullptr_t - : public __is_nullptr_t_impl<__remove_cv_t<_Tp> > {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS __is_nullptr_t : public __is_nullptr_t_impl<__remove_cv_t<_Tp> > {}; -#if _LIBCPP_STD_VER > 11 -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_null_pointer - : public __is_nullptr_t_impl<__remove_cv_t<_Tp> > {}; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_null_pointer : public __is_nullptr_t_impl<__remove_cv_t<_Tp> > {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value; -#endif -#endif // _LIBCPP_STD_VER > 11 +# endif +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_object.h b/libcxx/include/__type_traits/is_object.h index 943f1a736cd5..5ac1d854a695 100644 --- a/libcxx/include/__type_traits/is_object.h +++ b/libcxx/include/__type_traits/is_object.h @@ -24,26 +24,26 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_object) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_object : _BoolConstant<__is_object(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_object : _BoolConstant<__is_object(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_object_v = __is_object(_Tp); -#endif +# endif #else // __has_builtin(__is_object) -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_object - : public integral_constant<bool, is_scalar<_Tp>::value || - is_array<_Tp>::value || - is_union<_Tp>::value || - is_class<_Tp>::value > {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_object + : public integral_constant<bool, + is_scalar<_Tp>::value || is_array<_Tp>::value || is_union<_Tp>::value || + is_class<_Tp>::value > {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_object_v = is_object<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_object) diff --git a/libcxx/include/__type_traits/is_pod.h b/libcxx/include/__type_traits/is_pod.h index c1d00b269f00..5888fbf457d8 100644 --- a/libcxx/include/__type_traits/is_pod.h +++ b/libcxx/include/__type_traits/is_pod.h @@ -18,10 +18,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_pod - : public integral_constant<bool, __is_pod(_Tp)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_pod : public integral_constant<bool, __is_pod(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_pod_v = __is_pod(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_pointer.h b/libcxx/include/__type_traits/is_pointer.h index 3c0ad04892a2..38eb7996c686 100644 --- a/libcxx/include/__type_traits/is_pointer.h +++ b/libcxx/include/__type_traits/is_pointer.h @@ -21,34 +21,42 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_pointer) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_pointer : _BoolConstant<__is_pointer(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_pointer : _BoolConstant<__is_pointer(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_pointer_v = __is_pointer(_Tp); -#endif +# endif #else // __has_builtin(__is_pointer) -template <class _Tp> struct __libcpp_is_pointer : public false_type {}; -template <class _Tp> struct __libcpp_is_pointer<_Tp*> : public true_type {}; +template <class _Tp> +struct __libcpp_is_pointer : public false_type {}; +template <class _Tp> +struct __libcpp_is_pointer<_Tp*> : public true_type {}; -template <class _Tp> struct __libcpp_remove_objc_qualifiers { typedef _Tp type; }; -#if defined(_LIBCPP_HAS_OBJC_ARC) +template <class _Tp> +struct __libcpp_remove_objc_qualifiers { + typedef _Tp type; +}; +# if defined(_LIBCPP_HAS_OBJC_ARC) +// clang-format off template <class _Tp> struct __libcpp_remove_objc_qualifiers<_Tp __strong> { typedef _Tp type; }; template <class _Tp> struct __libcpp_remove_objc_qualifiers<_Tp __weak> { typedef _Tp type; }; template <class _Tp> struct __libcpp_remove_objc_qualifiers<_Tp __autoreleasing> { typedef _Tp type; }; template <class _Tp> struct __libcpp_remove_objc_qualifiers<_Tp __unsafe_unretained> { typedef _Tp type; }; -#endif +// clang-format on +# endif -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_pointer +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_pointer : public __libcpp_is_pointer<typename __libcpp_remove_objc_qualifiers<__remove_cv_t<_Tp> >::type> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_pointer_v = is_pointer<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_pointer) diff --git a/libcxx/include/__type_traits/is_polymorphic.h b/libcxx/include/__type_traits/is_polymorphic.h index 96da48abeeec..d122e1c87775 100644 --- a/libcxx/include/__type_traits/is_polymorphic.h +++ b/libcxx/include/__type_traits/is_polymorphic.h @@ -19,10 +19,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_polymorphic - : public integral_constant<bool, __is_polymorphic(_Tp)> {}; +struct _LIBCPP_TEMPLATE_VIS is_polymorphic : public integral_constant<bool, __is_polymorphic(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_polymorphic_v = __is_polymorphic(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_primary_template.h b/libcxx/include/__type_traits/is_primary_template.h index a9bebcf7e64c..f308dfadc8ec 100644 --- a/libcxx/include/__type_traits/is_primary_template.h +++ b/libcxx/include/__type_traits/is_primary_template.h @@ -21,13 +21,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> -using __test_for_primary_template = __enable_if_t< - _IsSame<_Tp, typename _Tp::__primary_template>::value - >; +using __test_for_primary_template = __enable_if_t<_IsSame<_Tp, typename _Tp::__primary_template>::value>; + template <class _Tp> -using __is_primary_template = _IsValidExpansion< - __test_for_primary_template, _Tp - >; +using __is_primary_template = _IsValidExpansion<__test_for_primary_template, _Tp>; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_reference.h b/libcxx/include/__type_traits/is_reference.h index 27ca2ddb5a72..42853d479039 100644 --- a/libcxx/include/__type_traits/is_reference.h +++ b/libcxx/include/__type_traits/is_reference.h @@ -18,41 +18,46 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__is_lvalue_reference) && \ - __has_builtin(__is_rvalue_reference) && \ - __has_builtin(__is_reference) +#if __has_builtin(__is_lvalue_reference) && __has_builtin(__is_rvalue_reference) && __has_builtin(__is_reference) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference : _BoolConstant<__is_lvalue_reference(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference : _BoolConstant<__is_lvalue_reference(_Tp)> {}; -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_rvalue_reference : _BoolConstant<__is_rvalue_reference(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_rvalue_reference : _BoolConstant<__is_rvalue_reference(_Tp)> {}; -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_reference : _BoolConstant<__is_reference(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_reference : _BoolConstant<__is_reference(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_reference_v = __is_reference(_Tp); template <class _Tp> inline constexpr bool is_lvalue_reference_v = __is_lvalue_reference(_Tp); template <class _Tp> inline constexpr bool is_rvalue_reference_v = __is_rvalue_reference(_Tp); -#endif +# endif #else // __has_builtin(__is_lvalue_reference) && etc... -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference : public false_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference<_Tp&> : public true_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference : public false_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference<_Tp&> : public true_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_rvalue_reference : public false_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_rvalue_reference<_Tp&&> : public true_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_rvalue_reference : public false_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_rvalue_reference<_Tp&&> : public true_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_reference : public false_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_reference<_Tp&> : public true_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_reference<_Tp&&> : public true_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_reference : public false_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_reference<_Tp&> : public true_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_reference<_Tp&&> : public true_type {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_reference_v = is_reference<_Tp>::value; @@ -61,7 +66,7 @@ inline constexpr bool is_lvalue_reference_v = is_lvalue_reference<_Tp>::value; template <class _Tp> inline constexpr bool is_rvalue_reference_v = is_rvalue_reference<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_lvalue_reference) && etc... diff --git a/libcxx/include/__type_traits/is_reference_wrapper.h b/libcxx/include/__type_traits/is_reference_wrapper.h index d187eec1e132..b638e7046b71 100644 --- a/libcxx/include/__type_traits/is_reference_wrapper.h +++ b/libcxx/include/__type_traits/is_reference_wrapper.h @@ -19,12 +19,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> class _LIBCPP_TEMPLATE_VIS reference_wrapper; - -template <class _Tp> struct __is_reference_wrapper_impl : public false_type {}; -template <class _Tp> struct __is_reference_wrapper_impl<reference_wrapper<_Tp> > : public true_type {}; -template <class _Tp> struct __is_reference_wrapper - : public __is_reference_wrapper_impl<__remove_cv_t<_Tp> > {}; +template <class _Tp> +class _LIBCPP_TEMPLATE_VIS reference_wrapper; + +template <class _Tp> +struct __is_reference_wrapper_impl : public false_type {}; +template <class _Tp> +struct __is_reference_wrapper_impl<reference_wrapper<_Tp> > : public true_type {}; +template <class _Tp> +struct __is_reference_wrapper : public __is_reference_wrapper_impl<__remove_cv_t<_Tp> > {}; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_same.h b/libcxx/include/__type_traits/is_same.h index 6fa0afbc18ca..9561b7b5d6da 100644 --- a/libcxx/include/__type_traits/is_same.h +++ b/libcxx/include/__type_traits/is_same.h @@ -19,9 +19,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp, class _Up> -struct _LIBCPP_TEMPLATE_VIS is_same : _BoolConstant<__is_same(_Tp, _Up)> { }; +struct _LIBCPP_TEMPLATE_VIS is_same : _BoolConstant<__is_same(_Tp, _Up)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp, class _Up> inline constexpr bool is_same_v = __is_same(_Tp, _Up); #endif diff --git a/libcxx/include/__type_traits/is_scalar.h b/libcxx/include/__type_traits/is_scalar.h index b4dc70b5d835..15f1c71554f2 100644 --- a/libcxx/include/__type_traits/is_scalar.h +++ b/libcxx/include/__type_traits/is_scalar.h @@ -25,35 +25,42 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_scalar) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_scalar : _BoolConstant<__is_scalar(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_scalar : _BoolConstant<__is_scalar(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_scalar_v = __is_scalar(_Tp); -#endif +# endif #else // __has_builtin(__is_scalar) -template <class _Tp> struct __is_block : false_type {}; -#if defined(_LIBCPP_HAS_EXTENSION_BLOCKS) -template <class _Rp, class ..._Args> struct __is_block<_Rp (^)(_Args...)> : true_type {}; -#endif +template <class _Tp> +struct __is_block : false_type {}; +# if defined(_LIBCPP_HAS_EXTENSION_BLOCKS) +template <class _Rp, class... _Args> +struct __is_block<_Rp (^)(_Args...)> : true_type {}; +# endif -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_scalar - : public integral_constant<bool, is_arithmetic<_Tp>::value || - is_member_pointer<_Tp>::value || - is_pointer<_Tp>::value || - __is_nullptr_t<_Tp>::value || - __is_block<_Tp>::value || - is_enum<_Tp>::value > {}; +// clang-format off +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_scalar + : public integral_constant< + bool, is_arithmetic<_Tp>::value || + is_member_pointer<_Tp>::value || + is_pointer<_Tp>::value || + __is_nullptr_t<_Tp>::value || + __is_block<_Tp>::value || + is_enum<_Tp>::value> {}; +// clang-format on -template <> struct _LIBCPP_TEMPLATE_VIS is_scalar<nullptr_t> : public true_type {}; +template <> +struct _LIBCPP_TEMPLATE_VIS is_scalar<nullptr_t> : public true_type {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_scalar_v = is_scalar<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_scalar) diff --git a/libcxx/include/__type_traits/is_scoped_enum.h b/libcxx/include/__type_traits/is_scoped_enum.h index 85a412813304..43b3a6b66b1f 100644 --- a/libcxx/include/__type_traits/is_scoped_enum.h +++ b/libcxx/include/__type_traits/is_scoped_enum.h @@ -21,17 +21,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _Tp, bool = is_enum_v<_Tp> > struct __is_scoped_enum_helper : false_type {}; template <class _Tp> -struct __is_scoped_enum_helper<_Tp, true> - : public bool_constant<!is_convertible_v<_Tp, underlying_type_t<_Tp> > > {}; +struct __is_scoped_enum_helper<_Tp, true> : public bool_constant<!is_convertible_v<_Tp, underlying_type_t<_Tp> > > {}; template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_scoped_enum - : public __is_scoped_enum_helper<_Tp> {}; +struct _LIBCPP_TEMPLATE_VIS is_scoped_enum : public __is_scoped_enum_helper<_Tp> {}; template <class _Tp> inline constexpr bool is_scoped_enum_v = is_scoped_enum<_Tp>::value; diff --git a/libcxx/include/__type_traits/is_signed.h b/libcxx/include/__type_traits/is_signed.h index aa42a4e420da..fd6f93e18236 100644 --- a/libcxx/include/__type_traits/is_signed.h +++ b/libcxx/include/__type_traits/is_signed.h @@ -22,13 +22,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_signed) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_signed : _BoolConstant<__is_signed(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_signed : _BoolConstant<__is_signed(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_signed_v = __is_signed(_Tp); -#endif +# endif #else // __has_builtin(__is_signed) @@ -36,19 +36,21 @@ template <class _Tp, bool = is_integral<_Tp>::value> struct __libcpp_is_signed_impl : public _BoolConstant<(_Tp(-1) < _Tp(0))> {}; template <class _Tp> -struct __libcpp_is_signed_impl<_Tp, false> : public true_type {}; // floating point +struct __libcpp_is_signed_impl<_Tp, false> : public true_type {}; // floating point template <class _Tp, bool = is_arithmetic<_Tp>::value> struct __libcpp_is_signed : public __libcpp_is_signed_impl<_Tp> {}; -template <class _Tp> struct __libcpp_is_signed<_Tp, false> : public false_type {}; +template <class _Tp> +struct __libcpp_is_signed<_Tp, false> : public false_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_signed : public __libcpp_is_signed<_Tp> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_signed : public __libcpp_is_signed<_Tp> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_signed_v = is_signed<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_signed) diff --git a/libcxx/include/__type_traits/is_signed_integer.h b/libcxx/include/__type_traits/is_signed_integer.h index 95aa11bfa1b5..467548d0aaaf 100644 --- a/libcxx/include/__type_traits/is_signed_integer.h +++ b/libcxx/include/__type_traits/is_signed_integer.h @@ -18,15 +18,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct __libcpp_is_signed_integer : public false_type {}; -template <> struct __libcpp_is_signed_integer<signed char> : public true_type {}; -template <> struct __libcpp_is_signed_integer<signed short> : public true_type {}; -template <> struct __libcpp_is_signed_integer<signed int> : public true_type {}; -template <> struct __libcpp_is_signed_integer<signed long> : public true_type {}; -template <> struct __libcpp_is_signed_integer<signed long long> : public true_type {}; +// clang-format off +template <class _Tp> struct __libcpp_is_signed_integer : public false_type {}; +template <> struct __libcpp_is_signed_integer<signed char> : public true_type {}; +template <> struct __libcpp_is_signed_integer<signed short> : public true_type {}; +template <> struct __libcpp_is_signed_integer<signed int> : public true_type {}; +template <> struct __libcpp_is_signed_integer<signed long> : public true_type {}; +template <> struct __libcpp_is_signed_integer<signed long long> : public true_type {}; #ifndef _LIBCPP_HAS_NO_INT128 -template <> struct __libcpp_is_signed_integer<__int128_t> : public true_type {}; +template <> struct __libcpp_is_signed_integer<__int128_t> : public true_type {}; #endif +// clang-format on _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_specialization.h b/libcxx/include/__type_traits/is_specialization.h index 0cc36674257c..9b75636b1a51 100644 --- a/libcxx/include/__type_traits/is_specialization.h +++ b/libcxx/include/__type_traits/is_specialization.h @@ -30,7 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp, template <class...> class _Template> inline constexpr bool __is_specialization_v = false; // true if and only if _Tp is a specialization of _Template @@ -38,7 +38,7 @@ inline constexpr bool __is_specialization_v = false; // true if and only if _Tp template <template <class...> class _Template, class... _Args> inline constexpr bool __is_specialization_v<_Template<_Args...>, _Template> = true; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_standard_layout.h b/libcxx/include/__type_traits/is_standard_layout.h index 12c17127482f..76484f3e2a30 100644 --- a/libcxx/include/__type_traits/is_standard_layout.h +++ b/libcxx/include/__type_traits/is_standard_layout.h @@ -18,11 +18,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_standard_layout - : public integral_constant<bool, __is_standard_layout(_Tp)> - {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_standard_layout : public integral_constant<bool, __is_standard_layout(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_standard_layout_v = __is_standard_layout(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_swappable.h b/libcxx/include/__type_traits/is_swappable.h index 3821de17f66e..07c56619856d 100644 --- a/libcxx/include/__type_traits/is_swappable.h +++ b/libcxx/include/__type_traits/is_swappable.h @@ -30,9 +30,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct __is_swappable; -template <class _Tp> struct __is_nothrow_swappable; - +template <class _Tp> +struct __is_swappable; +template <class _Tp> +struct __is_nothrow_swappable; #ifndef _LIBCPP_CXX03_LANG template <class _Tp> @@ -43,49 +44,40 @@ using __swap_result_t = void; #endif template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 __swap_result_t<_Tp> -swap(_Tp& __x, _Tp& __y) _NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value && - is_nothrow_move_assignable<_Tp>::value); +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __swap_result_t<_Tp> swap(_Tp& __x, _Tp& __y) + _NOEXCEPT_(is_nothrow_move_constructible<_Tp>::value&& is_nothrow_move_assignable<_Tp>::value); -template<class _Tp, size_t _Np> +template <class _Tp, size_t _Np> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 -typename enable_if< - __is_swappable<_Tp>::value ->::type -swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value); + typename enable_if<__is_swappable<_Tp>::value>::type swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) + _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value); -namespace __detail -{ +namespace __detail { // ALL generic swap overloads MUST already have a declaration available at this point. -template <class _Tp, class _Up = _Tp, - bool _NotVoid = !is_void<_Tp>::value && !is_void<_Up>::value> -struct __swappable_with -{ - template <class _LHS, class _RHS> - static decltype(swap(std::declval<_LHS>(), std::declval<_RHS>())) - __test_swap(int); - template <class, class> - static __nat __test_swap(long); - - // Extra parens are needed for the C++03 definition of decltype. - typedef decltype((__test_swap<_Tp, _Up>(0))) __swap1; - typedef decltype((__test_swap<_Up, _Tp>(0))) __swap2; - - static const bool value = _IsNotSame<__swap1, __nat>::value - && _IsNotSame<__swap2, __nat>::value; +template <class _Tp, class _Up = _Tp, bool _NotVoid = !is_void<_Tp>::value && !is_void<_Up>::value> +struct __swappable_with { + template <class _LHS, class _RHS> + static decltype(swap(std::declval<_LHS>(), std::declval<_RHS>())) __test_swap(int); + template <class, class> + static __nat __test_swap(long); + + // Extra parens are needed for the C++03 definition of decltype. + typedef decltype((__test_swap<_Tp, _Up>(0))) __swap1; + typedef decltype((__test_swap<_Up, _Tp>(0))) __swap2; + + static const bool value = _IsNotSame<__swap1, __nat>::value && _IsNotSame<__swap2, __nat>::value; }; template <class _Tp, class _Up> -struct __swappable_with<_Tp, _Up, false> : false_type {}; +struct __swappable_with<_Tp, _Up, false> : false_type {}; template <class _Tp, class _Up = _Tp, bool _Swappable = __swappable_with<_Tp, _Up>::value> struct __nothrow_swappable_with { static const bool value = #ifndef _LIBCPP_HAS_NO_NOEXCEPT - noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())) - && noexcept(swap(std::declval<_Up>(), std::declval<_Tp>())); + noexcept(swap(std::declval<_Tp>(), std::declval<_Up>()))&& noexcept( + swap(std::declval<_Up>(), std::declval<_Tp>())); #else false; #endif @@ -97,54 +89,32 @@ struct __nothrow_swappable_with<_Tp, _Up, false> : false_type {}; } // namespace __detail template <class _Tp> -struct __is_swappable - : public integral_constant<bool, __detail::__swappable_with<_Tp&>::value> -{ -}; +struct __is_swappable : public integral_constant<bool, __detail::__swappable_with<_Tp&>::value> {}; template <class _Tp> -struct __is_nothrow_swappable - : public integral_constant<bool, __detail::__nothrow_swappable_with<_Tp&>::value> -{ -}; +struct __is_nothrow_swappable : public integral_constant<bool, __detail::__nothrow_swappable_with<_Tp&>::value> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp, class _Up> struct _LIBCPP_TEMPLATE_VIS is_swappable_with - : public integral_constant<bool, __detail::__swappable_with<_Tp, _Up>::value> -{ -}; + : public integral_constant<bool, __detail::__swappable_with<_Tp, _Up>::value> {}; template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_swappable - : public __conditional_t< - __libcpp_is_referenceable<_Tp>::value, - is_swappable_with< - __add_lvalue_reference_t<_Tp>, - __add_lvalue_reference_t<_Tp> >, - false_type - > -{ -}; + : public __conditional_t<__libcpp_is_referenceable<_Tp>::value, + is_swappable_with<__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<_Tp> >, + false_type> {}; template <class _Tp, class _Up> struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable_with - : public integral_constant<bool, __detail::__nothrow_swappable_with<_Tp, _Up>::value> -{ -}; + : public integral_constant<bool, __detail::__nothrow_swappable_with<_Tp, _Up>::value> {}; template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable - : public __conditional_t< - __libcpp_is_referenceable<_Tp>::value, - is_nothrow_swappable_with< - __add_lvalue_reference_t<_Tp>, - __add_lvalue_reference_t<_Tp> >, - false_type - > -{ -}; + : public __conditional_t<__libcpp_is_referenceable<_Tp>::value, + is_nothrow_swappable_with<__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<_Tp> >, + false_type> {}; template <class _Tp, class _Up> inline constexpr bool is_swappable_with_v = is_swappable_with<_Tp, _Up>::value; @@ -158,7 +128,7 @@ inline constexpr bool is_nothrow_swappable_with_v = is_nothrow_swappable_with<_T template <class _Tp> inline constexpr bool is_nothrow_swappable_v = is_nothrow_swappable<_Tp>::value; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_trivial.h b/libcxx/include/__type_traits/is_trivial.h index 840770d7b7ef..0007c7446d5e 100644 --- a/libcxx/include/__type_traits/is_trivial.h +++ b/libcxx/include/__type_traits/is_trivial.h @@ -18,11 +18,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_trivial - : public integral_constant<bool, __is_trivial(_Tp)> - {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivial : public integral_constant<bool, __is_trivial(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_trivial_v = __is_trivial(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_trivially_assignable.h b/libcxx/include/__type_traits/is_trivially_assignable.h index 9ef101f04ea7..19169d13d6d2 100644 --- a/libcxx/include/__type_traits/is_trivially_assignable.h +++ b/libcxx/include/__type_traits/is_trivially_assignable.h @@ -19,11 +19,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp, class _Arg> -struct is_trivially_assignable - : integral_constant<bool, __is_trivially_assignable(_Tp, _Arg)> -{ }; +struct is_trivially_assignable : integral_constant<bool, __is_trivially_assignable(_Tp, _Arg)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp, class _Arg> inline constexpr bool is_trivially_assignable_v = __is_trivially_assignable(_Tp, _Arg); #endif diff --git a/libcxx/include/__type_traits/is_trivially_constructible.h b/libcxx/include/__type_traits/is_trivially_constructible.h index 4173e3b4cf6d..4faaf9323cd5 100644 --- a/libcxx/include/__type_traits/is_trivially_constructible.h +++ b/libcxx/include/__type_traits/is_trivially_constructible.h @@ -20,11 +20,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp, class... _Args> struct _LIBCPP_TEMPLATE_VIS is_trivially_constructible - : integral_constant<bool, __is_trivially_constructible(_Tp, _Args...)> -{ -}; + : integral_constant<bool, __is_trivially_constructible(_Tp, _Args...)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp, class... _Args> inline constexpr bool is_trivially_constructible_v = __is_trivially_constructible(_Tp, _Args...); #endif diff --git a/libcxx/include/__type_traits/is_trivially_copy_assignable.h b/libcxx/include/__type_traits/is_trivially_copy_assignable.h index e6a4a35dbfb3..b6b3c119746f 100644 --- a/libcxx/include/__type_traits/is_trivially_copy_assignable.h +++ b/libcxx/include/__type_traits/is_trivially_copy_assignable.h @@ -22,13 +22,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_trivially_copy_assignable - : public integral_constant< - bool, - __is_trivially_assignable( - __add_lvalue_reference_t<_Tp>, - __add_lvalue_reference_t<typename add_const<_Tp>::type>)> {}; + : public integral_constant<bool, + __is_trivially_assignable(__add_lvalue_reference_t<_Tp>, + __add_lvalue_reference_t<typename add_const<_Tp>::type>)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_trivially_copy_constructible.h b/libcxx/include/__type_traits/is_trivially_copy_constructible.h index 4bbb803a55cf..8e71fd1fbf8b 100644 --- a/libcxx/include/__type_traits/is_trivially_copy_constructible.h +++ b/libcxx/include/__type_traits/is_trivially_copy_constructible.h @@ -19,11 +19,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_trivially_copy_constructible - : public integral_constant<bool, __is_trivially_constructible(_Tp, __add_lvalue_reference_t<const _Tp>)> - {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivially_copy_constructible + : public integral_constant<bool, __is_trivially_constructible(_Tp, __add_lvalue_reference_t<const _Tp>)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_trivially_copy_constructible_v = is_trivially_copy_constructible<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_trivially_copyable.h b/libcxx/include/__type_traits/is_trivially_copyable.h index ef118bf9c49a..e92af126ee94 100644 --- a/libcxx/include/__type_traits/is_trivially_copyable.h +++ b/libcxx/include/__type_traits/is_trivially_copyable.h @@ -11,6 +11,7 @@ #include <__config> #include <__type_traits/integral_constant.h> +#include <cstdint> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -18,15 +19,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_trivially_copyable - : public integral_constant<bool, __is_trivially_copyable(_Tp)> - {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivially_copyable : public integral_constant<bool, __is_trivially_copyable(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Tp); #endif +#if _LIBCPP_STD_VER >= 20 +template <class _Tp> +inline constexpr bool __is_cheap_to_copy = is_trivially_copyable_v<_Tp> && sizeof(_Tp) <= sizeof(std::intmax_t); +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_COPYABLE_H diff --git a/libcxx/include/__type_traits/is_trivially_default_constructible.h b/libcxx/include/__type_traits/is_trivially_default_constructible.h index 5c53bd55d904..c3b6152a9fca 100644 --- a/libcxx/include/__type_traits/is_trivially_default_constructible.h +++ b/libcxx/include/__type_traits/is_trivially_default_constructible.h @@ -18,11 +18,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_trivially_default_constructible - : public integral_constant<bool, __is_trivially_constructible(_Tp)> - {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivially_default_constructible + : public integral_constant<bool, __is_trivially_constructible(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_trivially_default_constructible_v = __is_trivially_constructible(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_trivially_destructible.h b/libcxx/include/__type_traits/is_trivially_destructible.h index 0239fca54d7f..5f9652f2a501 100644 --- a/libcxx/include/__type_traits/is_trivially_destructible.h +++ b/libcxx/include/__type_traits/is_trivially_destructible.h @@ -21,21 +21,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_trivially_destructible) -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_trivially_destructible +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivially_destructible : public integral_constant<bool, __is_trivially_destructible(_Tp)> {}; #elif __has_builtin(__has_trivial_destructor) -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_trivially_destructible - : public integral_constant<bool, is_destructible<_Tp>::value && __has_trivial_destructor(_Tp)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivially_destructible + : public integral_constant<bool, is_destructible<_Tp>::value&& __has_trivial_destructor(_Tp)> {}; #else -#error is_trivially_destructible is not implemented +# error is_trivially_destructible is not implemented #endif // __has_builtin(__is_trivially_destructible) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_trivially_destructible_v = is_trivially_destructible<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_trivially_lexicographically_comparable.h b/libcxx/include/__type_traits/is_trivially_lexicographically_comparable.h new file mode 100644 index 000000000000..a310ea1b87e3 --- /dev/null +++ b/libcxx/include/__type_traits/is_trivially_lexicographically_comparable.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_LEXICOGRAPHICALLY_COMPARABLE_H +#define _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_LEXICOGRAPHICALLY_COMPARABLE_H + +#include <__config> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_unsigned.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// A type is_trivially_lexicographically_comparable if the expression `a <=> b` (or their pre-C++20 equivalents) is +// equivalent to `std::memcmp(&a, &b, sizeof(T))` (with `a` and `b` being of type `T`). There is currently no builtin to +// tell us whether that's the case for arbitrary types, so we can only do this for known types. Specifically, these are +// currently unsigned integer types with a sizeof(T) == 1. +// +// bool is trivially lexicographically comparable, because e.g. false <=> true is valid code. Furthermore, the standard +// says that [basic.fundamental] "Type bool is a distinct type that has the same object representation, value +// representation, and alignment requirements as an implementation-defined unsigned integer type. The values of type +// bool are true and false." +// This means that bool has to be unsigned and has exactly two values. This means that having anything other than the +// `true` or `false` value representations in a bool is UB. +// +// The following types are not trivially lexicographically comparable: +// signed integer types: `char(-1) < char(1)`, but memcmp compares `unsigned char`s +// unsigned integer types with sizeof(T) > 1: depending on the endianness, the LSB might be the first byte to be +// compared. This means that when comparing unsigned(129) and unsigned(2) +// using memcmp(), the result would be that 2 > 129. +// TODO: Do we want to enable this on big-endian systems? + +template <class _Tp, class _Up> +struct __libcpp_is_trivially_lexicographically_comparable + : integral_constant<bool, + is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >::value && sizeof(_Tp) == 1 && + is_unsigned<_Tp>::value> {}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_LEXICOGRAPHICALLY_COMPARABLE_H diff --git a/libcxx/include/__type_traits/is_trivially_move_assignable.h b/libcxx/include/__type_traits/is_trivially_move_assignable.h index 8f8876f45aad..daf890b26c74 100644 --- a/libcxx/include/__type_traits/is_trivially_move_assignable.h +++ b/libcxx/include/__type_traits/is_trivially_move_assignable.h @@ -26,7 +26,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivially_move_assignable bool, __is_trivially_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_trivially_move_constructible.h b/libcxx/include/__type_traits/is_trivially_move_constructible.h index 151bb256b95b..71e6f898fb3f 100644 --- a/libcxx/include/__type_traits/is_trivially_move_constructible.h +++ b/libcxx/include/__type_traits/is_trivially_move_constructible.h @@ -23,7 +23,7 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_trivially_move_constructible : public integral_constant<bool, __is_trivially_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_trivially_move_constructible_v = is_trivially_move_constructible<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_unbounded_array.h b/libcxx/include/__type_traits/is_unbounded_array.h index 11a12607e1e0..d58bb09e1042 100644 --- a/libcxx/include/__type_traits/is_unbounded_array.h +++ b/libcxx/include/__type_traits/is_unbounded_array.h @@ -18,17 +18,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class> struct _LIBCPP_TEMPLATE_VIS __libcpp_is_unbounded_array : false_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS __libcpp_is_unbounded_array<_Tp[]> : true_type {}; +template <class> +struct _LIBCPP_TEMPLATE_VIS __libcpp_is_unbounded_array : false_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS __libcpp_is_unbounded_array<_Tp[]> : true_type {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 -template <class> struct _LIBCPP_TEMPLATE_VIS is_unbounded_array : false_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_unbounded_array<_Tp[]> : true_type {}; +template <class> +struct _LIBCPP_TEMPLATE_VIS is_unbounded_array : false_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_unbounded_array<_Tp[]> : true_type {}; template <class _Tp> -inline constexpr -bool is_unbounded_array_v = is_unbounded_array<_Tp>::value; +inline constexpr bool is_unbounded_array_v = is_unbounded_array<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/is_union.h b/libcxx/include/__type_traits/is_union.h index 998aedd1428d..1f009d993545 100644 --- a/libcxx/include/__type_traits/is_union.h +++ b/libcxx/include/__type_traits/is_union.h @@ -18,10 +18,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_union - : public integral_constant<bool, __is_union(_Tp)> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_union : public integral_constant<bool, __is_union(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_union_v = __is_union(_Tp); #endif diff --git a/libcxx/include/__type_traits/is_unsigned.h b/libcxx/include/__type_traits/is_unsigned.h index 3d75409914fe..48c5751ed70d 100644 --- a/libcxx/include/__type_traits/is_unsigned.h +++ b/libcxx/include/__type_traits/is_unsigned.h @@ -22,13 +22,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_unsigned) -template<class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_unsigned : _BoolConstant<__is_unsigned(_Tp)> { }; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_unsigned : _BoolConstant<__is_unsigned(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_unsigned_v = __is_unsigned(_Tp); -#endif +# endif #else // __has_builtin(__is_unsigned) @@ -36,19 +36,21 @@ template <class _Tp, bool = is_integral<_Tp>::value> struct __libcpp_is_unsigned_impl : public _BoolConstant<(_Tp(0) < _Tp(-1))> {}; template <class _Tp> -struct __libcpp_is_unsigned_impl<_Tp, false> : public false_type {}; // floating point +struct __libcpp_is_unsigned_impl<_Tp, false> : public false_type {}; // floating point template <class _Tp, bool = is_arithmetic<_Tp>::value> struct __libcpp_is_unsigned : public __libcpp_is_unsigned_impl<_Tp> {}; -template <class _Tp> struct __libcpp_is_unsigned<_Tp, false> : public false_type {}; +template <class _Tp> +struct __libcpp_is_unsigned<_Tp, false> : public false_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_unsigned : public __libcpp_is_unsigned<_Tp> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_unsigned : public __libcpp_is_unsigned<_Tp> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_unsigned) diff --git a/libcxx/include/__type_traits/is_unsigned_integer.h b/libcxx/include/__type_traits/is_unsigned_integer.h index 54b29acd9ea3..265894b32d4f 100644 --- a/libcxx/include/__type_traits/is_unsigned_integer.h +++ b/libcxx/include/__type_traits/is_unsigned_integer.h @@ -18,15 +18,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> struct __libcpp_is_unsigned_integer : public false_type {}; -template <> struct __libcpp_is_unsigned_integer<unsigned char> : public true_type {}; -template <> struct __libcpp_is_unsigned_integer<unsigned short> : public true_type {}; -template <> struct __libcpp_is_unsigned_integer<unsigned int> : public true_type {}; -template <> struct __libcpp_is_unsigned_integer<unsigned long> : public true_type {}; -template <> struct __libcpp_is_unsigned_integer<unsigned long long> : public true_type {}; +// clang-format off +template <class _Tp> struct __libcpp_is_unsigned_integer : public false_type {}; +template <> struct __libcpp_is_unsigned_integer<unsigned char> : public true_type {}; +template <> struct __libcpp_is_unsigned_integer<unsigned short> : public true_type {}; +template <> struct __libcpp_is_unsigned_integer<unsigned int> : public true_type {}; +template <> struct __libcpp_is_unsigned_integer<unsigned long> : public true_type {}; +template <> struct __libcpp_is_unsigned_integer<unsigned long long> : public true_type {}; #ifndef _LIBCPP_HAS_NO_INT128 -template <> struct __libcpp_is_unsigned_integer<__uint128_t> : public true_type {}; +template <> struct __libcpp_is_unsigned_integer<__uint128_t> : public true_type {}; #endif +// clang-format on _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_valid_expansion.h b/libcxx/include/__type_traits/is_valid_expansion.h index db7d7e5f1d05..346bc98b110f 100644 --- a/libcxx/include/__type_traits/is_valid_expansion.h +++ b/libcxx/include/__type_traits/is_valid_expansion.h @@ -18,12 +18,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <template <class...> class _Templ, class ..._Args, class = _Templ<_Args...> > +template <template <class...> class _Templ, class... _Args, class = _Templ<_Args...> > true_type __sfinae_test_impl(int); -template <template <class...> class, class ...> +template <template <class...> class, class...> false_type __sfinae_test_impl(...); -template <template <class ...> class _Templ, class ..._Args> +template <template <class...> class _Templ, class... _Args> using _IsValidExpansion _LIBCPP_NODEBUG = decltype(std::__sfinae_test_impl<_Templ, _Args...>(0)); _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_void.h b/libcxx/include/__type_traits/is_void.h index d8ffdbd82446..4c27060530c8 100644 --- a/libcxx/include/__type_traits/is_void.h +++ b/libcxx/include/__type_traits/is_void.h @@ -23,22 +23,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_void) template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_void : _BoolConstant<__is_void(_Tp)> { }; +struct _LIBCPP_TEMPLATE_VIS is_void : _BoolConstant<__is_void(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_void_v = __is_void(_Tp); -#endif +# endif #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_void - : public is_same<__remove_cv_t<_Tp>, void> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_void : public is_same<__remove_cv_t<_Tp>, void> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_void_v = is_void<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_void) diff --git a/libcxx/include/__type_traits/is_volatile.h b/libcxx/include/__type_traits/is_volatile.h index fb922679d62b..87960a819c8f 100644 --- a/libcxx/include/__type_traits/is_volatile.h +++ b/libcxx/include/__type_traits/is_volatile.h @@ -21,22 +21,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if __has_builtin(__is_volatile) template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_volatile : _BoolConstant<__is_volatile(_Tp)> { }; +struct _LIBCPP_TEMPLATE_VIS is_volatile : _BoolConstant<__is_volatile(_Tp)> {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_volatile_v = __is_volatile(_Tp); -#endif +# endif #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_volatile : public false_type {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_volatile<_Tp volatile> : public true_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_volatile : public false_type {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_volatile<_Tp volatile> : public true_type {}; -#if _LIBCPP_STD_VER > 14 +# if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr bool is_volatile_v = is_volatile<_Tp>::value; -#endif +# endif #endif // __has_builtin(__is_volatile) diff --git a/libcxx/include/__type_traits/lazy.h b/libcxx/include/__type_traits/lazy.h index 6874b06f3c5a..80826f1d64f6 100644 --- a/libcxx/include/__type_traits/lazy.h +++ b/libcxx/include/__type_traits/lazy.h @@ -17,7 +17,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <template <class...> class _Func, class ..._Args> +template <template <class...> class _Func, class... _Args> struct _Lazy : _Func<_Args...> {}; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/make_32_64_or_128_bit.h b/libcxx/include/__type_traits/make_32_64_or_128_bit.h index 87340eac7fb1..f7f2e81735da 100644 --- a/libcxx/include/__type_traits/make_32_64_or_128_bit.h +++ b/libcxx/include/__type_traits/make_32_64_or_128_bit.h @@ -27,21 +27,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD /// /// The restriction is the same as the integral version of to_char. template <class _Tp> -#if _LIBCPP_STD_VER > 17 - requires (is_signed_v<_Tp> || is_unsigned_v<_Tp> || is_same_v<_Tp, char>) +#if _LIBCPP_STD_VER >= 20 + requires(is_signed_v<_Tp> || is_unsigned_v<_Tp> || is_same_v<_Tp, char>) #endif +// clang-format off using __make_32_64_or_128_bit_t = - __copy_unsigned_t<_Tp, - __conditional_t<sizeof(_Tp) <= sizeof(int32_t), int32_t, - __conditional_t<sizeof(_Tp) <= sizeof(int64_t), int64_t, + __copy_unsigned_t<_Tp, + __conditional_t<sizeof(_Tp) <= sizeof(int32_t), int32_t, + __conditional_t<sizeof(_Tp) <= sizeof(int64_t), int64_t, #ifndef _LIBCPP_HAS_NO_INT128 - __conditional_t<sizeof(_Tp) <= sizeof(__int128_t), __int128_t, - /* else */ void> + __conditional_t<sizeof(_Tp) <= sizeof(__int128_t), __int128_t, + /* else */ void> #else - /* else */ void + /* else */ void #endif - > > - >; + > > >; +// clang-format on _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/make_const_lvalue_ref.h b/libcxx/include/__type_traits/make_const_lvalue_ref.h index deea40d5e61a..469d4cb31ef7 100644 --- a/libcxx/include/__type_traits/make_const_lvalue_ref.h +++ b/libcxx/include/__type_traits/make_const_lvalue_ref.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template<class _Tp> +template <class _Tp> using __make_const_lvalue_ref = const __libcpp_remove_reference_t<_Tp>&; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/make_signed.h b/libcxx/include/__type_traits/make_signed.h index bff8744845fa..1a8a35f3859d 100644 --- a/libcxx/include/__type_traits/make_signed.h +++ b/libcxx/include/__type_traits/make_signed.h @@ -29,30 +29,31 @@ template <class _Tp> using __make_signed_t = __make_signed(_Tp); #else -typedef - __type_list<signed char, - __type_list<signed short, - __type_list<signed int, - __type_list<signed long, - __type_list<signed long long, +// clang-format off +typedef __type_list<signed char, + __type_list<signed short, + __type_list<signed int, + __type_list<signed long, + __type_list<signed long long, # ifndef _LIBCPP_HAS_NO_INT128 - __type_list<__int128_t, + __type_list<__int128_t, # endif - __nat + __nat # ifndef _LIBCPP_HAS_NO_INT128 - > + > # endif - > > > > > __signed_types; + > > > > > __signed_types; +// clang-format on template <class _Tp, bool = is_integral<_Tp>::value || is_enum<_Tp>::value> -struct __make_signed {}; +struct __make_signed{}; template <class _Tp> -struct __make_signed<_Tp, true> -{ - typedef typename __find_first<__signed_types, sizeof(_Tp)>::type type; +struct __make_signed<_Tp, true> { + typedef typename __find_first<__signed_types, sizeof(_Tp)>::type type; }; +// clang-format off template <> struct __make_signed<bool, true> {}; template <> struct __make_signed< signed short, true> {typedef short type;}; template <> struct __make_signed<unsigned short, true> {typedef short type;}; @@ -66,9 +67,10 @@ template <> struct __make_signed<unsigned long long, true> {typedef long long ty template <> struct __make_signed<__int128_t, true> {typedef __int128_t type;}; template <> struct __make_signed<__uint128_t, true> {typedef __int128_t type;}; # endif +// clang-format on template <class _Tp> -using __make_signed_t = typename __apply_cv<_Tp, typename __make_signed<__remove_cv_t<_Tp> >::type>::type; +using __make_signed_t = __apply_cv_t<_Tp, typename __make_signed<__remove_cv_t<_Tp> >::type>; #endif // __has_builtin(__make_signed) @@ -77,8 +79,9 @@ struct make_signed { using type _LIBCPP_NODEBUG = __make_signed_t<_Tp>; }; -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using make_signed_t = __make_signed_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using make_signed_t = __make_signed_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/make_unsigned.h b/libcxx/include/__type_traits/make_unsigned.h index 33c30147a613..98967371e773 100644 --- a/libcxx/include/__type_traits/make_unsigned.h +++ b/libcxx/include/__type_traits/make_unsigned.h @@ -31,30 +31,31 @@ template <class _Tp> using __make_unsigned_t = __make_unsigned(_Tp); #else -typedef - __type_list<unsigned char, - __type_list<unsigned short, - __type_list<unsigned int, - __type_list<unsigned long, - __type_list<unsigned long long, +// clang-format off +typedef __type_list<unsigned char, + __type_list<unsigned short, + __type_list<unsigned int, + __type_list<unsigned long, + __type_list<unsigned long long, # ifndef _LIBCPP_HAS_NO_INT128 - __type_list<__uint128_t, + __type_list<__uint128_t, # endif - __nat + __nat # ifndef _LIBCPP_HAS_NO_INT128 - > + > # endif - > > > > > __unsigned_types; + > > > > > __unsigned_types; +// clang-format on template <class _Tp, bool = is_integral<_Tp>::value || is_enum<_Tp>::value> -struct __make_unsigned {}; +struct __make_unsigned{}; template <class _Tp> -struct __make_unsigned<_Tp, true> -{ - typedef typename __find_first<__unsigned_types, sizeof(_Tp)>::type type; +struct __make_unsigned<_Tp, true> { + typedef typename __find_first<__unsigned_types, sizeof(_Tp)>::type type; }; +// clang-format off template <> struct __make_unsigned<bool, true> {}; template <> struct __make_unsigned< signed short, true> {typedef unsigned short type;}; template <> struct __make_unsigned<unsigned short, true> {typedef unsigned short type;}; @@ -68,9 +69,10 @@ template <> struct __make_unsigned<unsigned long long, true> {typedef unsigned l template <> struct __make_unsigned<__int128_t, true> {typedef __uint128_t type;}; template <> struct __make_unsigned<__uint128_t, true> {typedef __uint128_t type;}; # endif +// clang-format on template <class _Tp> -using __make_unsigned_t = typename __apply_cv<_Tp, typename __make_unsigned<__remove_cv_t<_Tp> >::type>::type; +using __make_unsigned_t = __apply_cv_t<_Tp, typename __make_unsigned<__remove_cv_t<_Tp> >::type>; #endif // __has_builtin(__make_unsigned) @@ -79,15 +81,15 @@ struct make_unsigned { using type _LIBCPP_NODEBUG = __make_unsigned_t<_Tp>; }; -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using make_unsigned_t = __make_unsigned_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using make_unsigned_t = __make_unsigned_t<_Tp>; #endif #ifndef _LIBCPP_CXX03_LANG template <class _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr -__make_unsigned_t<_Tp> __to_unsigned_like(_Tp __x) noexcept { - return static_cast<__make_unsigned_t<_Tp> >(__x); +_LIBCPP_HIDE_FROM_ABI constexpr __make_unsigned_t<_Tp> __to_unsigned_like(_Tp __x) noexcept { + return static_cast<__make_unsigned_t<_Tp> >(__x); } #endif diff --git a/libcxx/include/__type_traits/maybe_const.h b/libcxx/include/__type_traits/maybe_const.h index 8403f6aba746..25fba58fb773 100644 --- a/libcxx/include/__type_traits/maybe_const.h +++ b/libcxx/include/__type_traits/maybe_const.h @@ -18,7 +18,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template<bool _Const, class _Tp> +template <bool _Const, class _Tp> using __maybe_const = __conditional_t<_Const, const _Tp, _Tp>; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/nat.h b/libcxx/include/__type_traits/nat.h index 5216ef520420..9f39b806814e 100644 --- a/libcxx/include/__type_traits/nat.h +++ b/libcxx/include/__type_traits/nat.h @@ -17,13 +17,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD -struct __nat -{ +struct __nat { #ifndef _LIBCPP_CXX03_LANG - __nat() = delete; - __nat(const __nat&) = delete; - __nat& operator=(const __nat&) = delete; - ~__nat() = delete; + __nat() = delete; + __nat(const __nat&) = delete; + __nat& operator=(const __nat&) = delete; + ~__nat() = delete; #endif }; diff --git a/libcxx/include/__type_traits/negation.h b/libcxx/include/__type_traits/negation.h index b72f285a4d5d..a72e62d3f96e 100644 --- a/libcxx/include/__type_traits/negation.h +++ b/libcxx/include/__type_traits/negation.h @@ -21,12 +21,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Pred> struct _Not : _BoolConstant<!_Pred::value> {}; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> struct negation : _Not<_Tp> {}; -template<class _Tp> +template <class _Tp> inline constexpr bool negation_v = !_Tp::value; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/noexcept_move_assign_container.h b/libcxx/include/__type_traits/noexcept_move_assign_container.h index 35b0e51ba402..1d6c07e8cf96 100644 --- a/libcxx/include/__type_traits/noexcept_move_assign_container.h +++ b/libcxx/include/__type_traits/noexcept_move_assign_container.h @@ -20,15 +20,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <typename _Alloc, typename _Traits=allocator_traits<_Alloc> > -struct __noexcept_move_assign_container : public integral_constant<bool, - _Traits::propagate_on_container_move_assignment::value -#if _LIBCPP_STD_VER > 14 - || _Traits::is_always_equal::value +template <typename _Alloc, typename _Traits = allocator_traits<_Alloc> > +struct __noexcept_move_assign_container + : public integral_constant<bool, + _Traits::propagate_on_container_move_assignment::value +#if _LIBCPP_STD_VER >= 17 + || _Traits::is_always_equal::value #else - && is_nothrow_move_assignable<_Alloc>::value + && is_nothrow_move_assignable<_Alloc>::value #endif - > {}; + > { +}; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/operation_traits.h b/libcxx/include/__type_traits/operation_traits.h new file mode 100644 index 000000000000..7dda93e9083a --- /dev/null +++ b/libcxx/include/__type_traits/operation_traits.h @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_OPERATION_TRAITS_H +#define _LIBCPP___TYPE_TRAITS_OPERATION_TRAITS_H + +#include <__config> +#include <__type_traits/integral_constant.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Pred, class _Lhs, class _Rhs> +struct __is_trivial_plus_operation : false_type {}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_OPERATION_TRAITS_H diff --git a/libcxx/include/__type_traits/predicate_traits.h b/libcxx/include/__type_traits/predicate_traits.h new file mode 100644 index 000000000000..872608e6ac3b --- /dev/null +++ b/libcxx/include/__type_traits/predicate_traits.h @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TYPE_TRAITS_PREDICATE_TRAITS +#define _LIBCPP___TYPE_TRAITS_PREDICATE_TRAITS + +#include <__config> +#include <__type_traits/integral_constant.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Pred, class _Lhs, class _Rhs> +struct __is_trivial_equality_predicate : false_type {}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TYPE_TRAITS_PREDICATE_TRAITS diff --git a/libcxx/include/__type_traits/promote.h b/libcxx/include/__type_traits/promote.h index c2af327c64f7..018bd69df260 100644 --- a/libcxx/include/__type_traits/promote.h +++ b/libcxx/include/__type_traits/promote.h @@ -13,7 +13,6 @@ #include <__type_traits/integral_constant.h> #include <__type_traits/is_same.h> #include <__utility/declval.h> -#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,73 +21,69 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> -struct __numeric_type -{ - static void __test(...); - static float __test(float); - static double __test(char); - static double __test(int); - static double __test(unsigned); - static double __test(long); - static double __test(unsigned long); - static double __test(long long); - static double __test(unsigned long long); +struct __numeric_type { + static void __test(...); + static float __test(float); + static double __test(char); + static double __test(int); + static double __test(unsigned); + static double __test(long); + static double __test(unsigned long); + static double __test(long long); + static double __test(unsigned long long); #ifndef _LIBCPP_HAS_NO_INT128 - static double __test(__int128_t); - static double __test(__uint128_t); + static double __test(__int128_t); + static double __test(__uint128_t); #endif - static double __test(double); - static long double __test(long double); + static double __test(double); + static long double __test(long double); - typedef decltype(__test(std::declval<_Tp>())) type; - static const bool value = _IsNotSame<type, void>::value; + typedef decltype(__test(std::declval<_Tp>())) type; + static const bool value = _IsNotSame<type, void>::value; }; template <> -struct __numeric_type<void> -{ - static const bool value = true; +struct __numeric_type<void> { + static const bool value = true; }; -template <class _A1, class _A2 = void, class _A3 = void, - bool = __numeric_type<_A1>::value && - __numeric_type<_A2>::value && - __numeric_type<_A3>::value> -class __promote_imp -{ +template <class _A1, + class _A2 = void, + class _A3 = void, + bool = __numeric_type<_A1>::value&& __numeric_type<_A2>::value&& __numeric_type<_A3>::value> +class __promote_imp { public: - static const bool value = false; + static const bool value = false; }; template <class _A1, class _A2, class _A3> -class __promote_imp<_A1, _A2, _A3, true> -{ +class __promote_imp<_A1, _A2, _A3, true> { private: - typedef typename __promote_imp<_A1>::type __type1; - typedef typename __promote_imp<_A2>::type __type2; - typedef typename __promote_imp<_A3>::type __type3; + typedef typename __promote_imp<_A1>::type __type1; + typedef typename __promote_imp<_A2>::type __type2; + typedef typename __promote_imp<_A3>::type __type3; + public: - typedef decltype(__type1() + __type2() + __type3()) type; - static const bool value = true; + typedef decltype(__type1() + __type2() + __type3()) type; + static const bool value = true; }; template <class _A1, class _A2> -class __promote_imp<_A1, _A2, void, true> -{ +class __promote_imp<_A1, _A2, void, true> { private: - typedef typename __promote_imp<_A1>::type __type1; - typedef typename __promote_imp<_A2>::type __type2; + typedef typename __promote_imp<_A1>::type __type1; + typedef typename __promote_imp<_A2>::type __type2; + public: - typedef decltype(__type1() + __type2()) type; - static const bool value = true; + typedef decltype(__type1() + __type2()) type; + static const bool value = true; }; template <class _A1> -class __promote_imp<_A1, void, void, true> -{ +class __promote_imp<_A1, void, void, true> { public: - typedef typename __numeric_type<_A1>::type type; - static const bool value = true; + typedef typename __numeric_type<_A1>::type type; + static const bool value = true; }; template <class _A1, class _A2 = void, class _A3 = void> diff --git a/libcxx/include/__type_traits/rank.h b/libcxx/include/__type_traits/rank.h index 9950907b2278..7f6fad1c5402 100644 --- a/libcxx/include/__type_traits/rank.h +++ b/libcxx/include/__type_traits/rank.h @@ -27,16 +27,16 @@ struct rank : integral_constant<size_t, __array_rank(_Tp)> {}; #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS rank - : public integral_constant<size_t, 0> {}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS rank<_Tp[]> - : public integral_constant<size_t, rank<_Tp>::value + 1> {}; -template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS rank<_Tp[_Np]> - : public integral_constant<size_t, rank<_Tp>::value + 1> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS rank : public integral_constant<size_t, 0> {}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS rank<_Tp[]> : public integral_constant<size_t, rank<_Tp>::value + 1> {}; +template <class _Tp, size_t _Np> +struct _LIBCPP_TEMPLATE_VIS rank<_Tp[_Np]> : public integral_constant<size_t, rank<_Tp>::value + 1> {}; #endif // __has_builtin(__array_rank) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr size_t rank_v = rank<_Tp>::value; #endif diff --git a/libcxx/include/__type_traits/remove_all_extents.h b/libcxx/include/__type_traits/remove_all_extents.h index 868cf1039f6f..d5373b51f522 100644 --- a/libcxx/include/__type_traits/remove_all_extents.h +++ b/libcxx/include/__type_traits/remove_all_extents.h @@ -27,19 +27,26 @@ struct remove_all_extents { template <class _Tp> using __remove_all_extents_t = __remove_all_extents(_Tp); #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_all_extents - {typedef _Tp type;}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_all_extents<_Tp[]> - {typedef typename remove_all_extents<_Tp>::type type;}; -template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS remove_all_extents<_Tp[_Np]> - {typedef typename remove_all_extents<_Tp>::type type;}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS remove_all_extents { + typedef _Tp type; +}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS remove_all_extents<_Tp[]> { + typedef typename remove_all_extents<_Tp>::type type; +}; +template <class _Tp, size_t _Np> +struct _LIBCPP_TEMPLATE_VIS remove_all_extents<_Tp[_Np]> { + typedef typename remove_all_extents<_Tp>::type type; +}; template <class _Tp> using __remove_all_extents_t = typename remove_all_extents<_Tp>::type; #endif // __has_builtin(__remove_all_extents) -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using remove_all_extents_t = __remove_all_extents_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using remove_all_extents_t = __remove_all_extents_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/remove_const.h b/libcxx/include/__type_traits/remove_const.h index dc565338548e..a3f0648c4785 100644 --- a/libcxx/include/__type_traits/remove_const.h +++ b/libcxx/include/__type_traits/remove_const.h @@ -26,15 +26,22 @@ struct remove_const { template <class _Tp> using __remove_const_t = __remove_const(_Tp); #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_const {typedef _Tp type;}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_const<const _Tp> {typedef _Tp type;}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS remove_const { + typedef _Tp type; +}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS remove_const<const _Tp> { + typedef _Tp type; +}; template <class _Tp> using __remove_const_t = typename remove_const<_Tp>::type; #endif // __has_builtin(__remove_const) -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using remove_const_t = __remove_const_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using remove_const_t = __remove_const_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/remove_cv.h b/libcxx/include/__type_traits/remove_cv.h index ea85e23b8065..8fe8fb0e4959 100644 --- a/libcxx/include/__type_traits/remove_cv.h +++ b/libcxx/include/__type_traits/remove_cv.h @@ -28,15 +28,18 @@ struct remove_cv { template <class _Tp> using __remove_cv_t = __remove_cv(_Tp); #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_cv -{typedef __remove_volatile_t<__remove_const_t<_Tp> > type;}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS remove_cv { + typedef __remove_volatile_t<__remove_const_t<_Tp> > type; +}; template <class _Tp> using __remove_cv_t = __remove_volatile_t<__remove_const_t<_Tp> >; #endif // __has_builtin(__remove_cv) -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using remove_cv_t = __remove_cv_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using remove_cv_t = __remove_cv_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/remove_cvref.h b/libcxx/include/__type_traits/remove_cvref.h index e96cc6523b71..4dc950ac31ad 100644 --- a/libcxx/include/__type_traits/remove_cvref.h +++ b/libcxx/include/__type_traits/remove_cvref.h @@ -31,13 +31,14 @@ using __remove_cvref_t _LIBCPP_NODEBUG = __remove_cv_t<__libcpp_remove_reference template <class _Tp, class _Up> struct __is_same_uncvref : _IsSame<__remove_cvref_t<_Tp>, __remove_cvref_t<_Up> > {}; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp> struct remove_cvref { - using type _LIBCPP_NODEBUG = __remove_cvref_t<_Tp>; + using type _LIBCPP_NODEBUG = __remove_cvref_t<_Tp>; }; -template <class _Tp> using remove_cvref_t = __remove_cvref_t<_Tp>; +template <class _Tp> +using remove_cvref_t = __remove_cvref_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/remove_extent.h b/libcxx/include/__type_traits/remove_extent.h index 79d6e573dddb..fe37b5c7266c 100644 --- a/libcxx/include/__type_traits/remove_extent.h +++ b/libcxx/include/__type_traits/remove_extent.h @@ -27,19 +27,26 @@ struct remove_extent { template <class _Tp> using __remove_extent_t = __remove_extent(_Tp); #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_extent - {typedef _Tp type;}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_extent<_Tp[]> - {typedef _Tp type;}; -template <class _Tp, size_t _Np> struct _LIBCPP_TEMPLATE_VIS remove_extent<_Tp[_Np]> - {typedef _Tp type;}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS remove_extent { + typedef _Tp type; +}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS remove_extent<_Tp[]> { + typedef _Tp type; +}; +template <class _Tp, size_t _Np> +struct _LIBCPP_TEMPLATE_VIS remove_extent<_Tp[_Np]> { + typedef _Tp type; +}; template <class _Tp> using __remove_extent_t = typename remove_extent<_Tp>::type; #endif // __has_builtin(__remove_extent) -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using remove_extent_t = __remove_extent_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using remove_extent_t = __remove_extent_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/remove_pointer.h b/libcxx/include/__type_traits/remove_pointer.h index 33ddb7103f0d..54390a1939f7 100644 --- a/libcxx/include/__type_traits/remove_pointer.h +++ b/libcxx/include/__type_traits/remove_pointer.h @@ -17,7 +17,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if __has_builtin(__remove_pointer) +#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer) template <class _Tp> struct remove_pointer { using type _LIBCPP_NODEBUG = __remove_pointer(_Tp); @@ -26,18 +26,21 @@ struct remove_pointer { template <class _Tp> using __remove_pointer_t = __remove_pointer(_Tp); #else +// clang-format off template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer {typedef _LIBCPP_NODEBUG _Tp type;}; template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp*> {typedef _LIBCPP_NODEBUG _Tp type;}; template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* const> {typedef _LIBCPP_NODEBUG _Tp type;}; template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* volatile> {typedef _LIBCPP_NODEBUG _Tp type;}; template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* const volatile> {typedef _LIBCPP_NODEBUG _Tp type;}; +// clang-format on template <class _Tp> using __remove_pointer_t = typename remove_pointer<_Tp>::type; -#endif // __has_builtin(__remove_pointer) +#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer) -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using remove_pointer_t = __remove_pointer_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using remove_pointer_t = __remove_pointer_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/remove_reference.h b/libcxx/include/__type_traits/remove_reference.h index b9a69749b3b9..fd66417bd84f 100644 --- a/libcxx/include/__type_traits/remove_reference.h +++ b/libcxx/include/__type_traits/remove_reference.h @@ -27,16 +27,19 @@ struct remove_reference { template <class _Tp> using __libcpp_remove_reference_t = __remove_reference_t(_Tp); #else +// clang-format off template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference {typedef _LIBCPP_NODEBUG _Tp type;}; template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&> {typedef _LIBCPP_NODEBUG _Tp type;}; template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&&> {typedef _LIBCPP_NODEBUG _Tp type;}; +// clang-format on template <class _Tp> using __libcpp_remove_reference_t = typename remove_reference<_Tp>::type; #endif // __has_builtin(__remove_reference_t) -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using remove_reference_t = __libcpp_remove_reference_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using remove_reference_t = __libcpp_remove_reference_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/remove_volatile.h b/libcxx/include/__type_traits/remove_volatile.h index ed6d63b41744..7600ae0ec516 100644 --- a/libcxx/include/__type_traits/remove_volatile.h +++ b/libcxx/include/__type_traits/remove_volatile.h @@ -26,15 +26,22 @@ struct remove_volatile { template <class _Tp> using __remove_volatile_t = __remove_volatile(_Tp); #else -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_volatile {typedef _Tp type;}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_volatile<volatile _Tp> {typedef _Tp type;}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS remove_volatile { + typedef _Tp type; +}; +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS remove_volatile<volatile _Tp> { + typedef _Tp type; +}; template <class _Tp> using __remove_volatile_t = typename remove_volatile<_Tp>::type; #endif // __has_builtin(__remove_volatile) -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using remove_volatile_t = __remove_volatile_t<_Tp>; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using remove_volatile_t = __remove_volatile_t<_Tp>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/result_of.h b/libcxx/include/__type_traits/result_of.h index 804173e15e21..f00fa8e9be7f 100644 --- a/libcxx/include/__type_traits/result_of.h +++ b/libcxx/include/__type_traits/result_of.h @@ -21,18 +21,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD // result_of #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS) -template <class _Callable> class _LIBCPP_DEPRECATED_IN_CXX17 result_of; - -template <class _Fp, class ..._Args> -class _LIBCPP_TEMPLATE_VIS result_of<_Fp(_Args...)> - : public __invoke_of<_Fp, _Args...> -{ -}; - -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using result_of_t _LIBCPP_DEPRECATED_IN_CXX17 = typename result_of<_Tp>::type; -#endif // _LIBCPP_STD_VER > 11 -#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS) +template <class _Callable> +class _LIBCPP_DEPRECATED_IN_CXX17 result_of; + +template <class _Fp, class... _Args> +class _LIBCPP_TEMPLATE_VIS result_of<_Fp(_Args...)> : public __invoke_of<_Fp, _Args...> {}; + +# if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using result_of_t _LIBCPP_DEPRECATED_IN_CXX17 = typename result_of<_Tp>::type; +# endif // _LIBCPP_STD_VER >= 14 +#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/strip_signature.h b/libcxx/include/__type_traits/strip_signature.h index 2bb7393c1ee7..3fe79592f55b 100644 --- a/libcxx/include/__type_traits/strip_signature.h +++ b/libcxx/include/__type_traits/strip_signature.h @@ -19,23 +19,24 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template<class _Fp> +template <class _Fp> struct __strip_signature; # if defined(__cpp_static_call_operator) && __cpp_static_call_operator >= 202207L template <class _Rp, class... _Args> -struct __strip_signature<_Rp(*)(_Args...)> { +struct __strip_signature<_Rp (*)(_Args...)> { using type = _Rp(_Args...); }; template <class _Rp, class... _Args> -struct __strip_signature<_Rp(*)(_Args...) noexcept> { +struct __strip_signature<_Rp (*)(_Args...) noexcept> { using type = _Rp(_Args...); }; # endif // defined(__cpp_static_call_operator) && __cpp_static_call_operator >= 202207L +// clang-format off template<class _Rp, class _Gp, class ..._Ap> struct __strip_signature<_Rp (_Gp::*) (_Ap...)> { using type = _Rp(_Ap...); }; template<class _Rp, class _Gp, class ..._Ap> @@ -71,6 +72,7 @@ template<class _Rp, class _Gp, class ..._Ap> struct __strip_signature<_Rp (_Gp::*) (_Ap...) volatile & noexcept> { using type = _Rp(_Ap...); }; template<class _Rp, class _Gp, class ..._Ap> struct __strip_signature<_Rp (_Gp::*) (_Ap...) const volatile & noexcept> { using type = _Rp(_Ap...); }; +// clang-format on _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/type_identity.h b/libcxx/include/__type_traits/type_identity.h index 42e52b16725b..b0b5a1277d59 100644 --- a/libcxx/include/__type_traits/type_identity.h +++ b/libcxx/include/__type_traits/type_identity.h @@ -18,14 +18,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> -struct __type_identity { typedef _Tp type; }; +struct __type_identity { + typedef _Tp type; +}; template <class _Tp> using __type_identity_t _LIBCPP_NODEBUG = typename __type_identity<_Tp>::type; -#if _LIBCPP_STD_VER > 17 -template<class _Tp> struct type_identity { typedef _Tp type; }; -template<class _Tp> using type_identity_t = typename type_identity<_Tp>::type; +#if _LIBCPP_STD_VER >= 20 +template <class _Tp> +struct type_identity { + typedef _Tp type; +}; +template <class _Tp> +using type_identity_t = typename type_identity<_Tp>::type; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/type_list.h b/libcxx/include/__type_traits/type_list.h index 5a9e3319a1d4..02905707ee37 100644 --- a/libcxx/include/__type_traits/type_list.h +++ b/libcxx/include/__type_traits/type_list.h @@ -19,24 +19,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Hp, class _Tp> -struct __type_list -{ - typedef _Hp _Head; - typedef _Tp _Tail; +struct __type_list { + typedef _Hp _Head; + typedef _Tp _Tail; }; -template <class _TypeList, size_t _Size, bool = _Size <= sizeof(typename _TypeList::_Head)> struct __find_first; +template <class _TypeList, size_t _Size, bool = _Size <= sizeof(typename _TypeList::_Head)> +struct __find_first; template <class _Hp, class _Tp, size_t _Size> -struct __find_first<__type_list<_Hp, _Tp>, _Size, true> -{ - typedef _LIBCPP_NODEBUG _Hp type; +struct __find_first<__type_list<_Hp, _Tp>, _Size, true> { + typedef _LIBCPP_NODEBUG _Hp type; }; template <class _Hp, class _Tp, size_t _Size> -struct __find_first<__type_list<_Hp, _Tp>, _Size, false> -{ - typedef _LIBCPP_NODEBUG typename __find_first<_Tp, _Size>::type type; +struct __find_first<__type_list<_Hp, _Tp>, _Size, false> { + typedef _LIBCPP_NODEBUG typename __find_first<_Tp, _Size>::type type; }; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/underlying_type.h b/libcxx/include/__type_traits/underlying_type.h index 1c8db6432371..16e7501dee17 100644 --- a/libcxx/include/__type_traits/underlying_type.h +++ b/libcxx/include/__type_traits/underlying_type.h @@ -18,22 +18,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp, bool = is_enum<_Tp>::value> struct __underlying_type_impl; +template <class _Tp, bool = is_enum<_Tp>::value> +struct __underlying_type_impl; template <class _Tp> struct __underlying_type_impl<_Tp, false> {}; template <class _Tp> -struct __underlying_type_impl<_Tp, true> -{ - typedef __underlying_type(_Tp) type; +struct __underlying_type_impl<_Tp, true> { + typedef __underlying_type(_Tp) type; }; template <class _Tp> struct underlying_type : __underlying_type_impl<_Tp, is_enum<_Tp>::value> {}; -#if _LIBCPP_STD_VER > 11 -template <class _Tp> using underlying_type_t = typename underlying_type<_Tp>::type; +#if _LIBCPP_STD_VER >= 14 +template <class _Tp> +using underlying_type_t = typename underlying_type<_Tp>::type; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/unwrap_ref.h b/libcxx/include/__type_traits/unwrap_ref.h index da000d80b8c9..5fed08f7ddda 100644 --- a/libcxx/include/__functional/unwrap_ref.h +++ b/libcxx/include/__type_traits/unwrap_ref.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___FUNCTIONAL_UNWRAP_REF_H -#define _LIBCPP___FUNCTIONAL_UNWRAP_REF_H +#ifndef _LIBCPP___TYPE_TRAITS_UNWRAP_REF_H +#define _LIBCPP___TYPE_TRAITS_UNWRAP_REF_H #include <__config> #include <__type_traits/decay.h> @@ -19,40 +19,45 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> -struct __unwrap_reference { typedef _LIBCPP_NODEBUG _Tp type; }; +struct __unwrap_reference { + typedef _LIBCPP_NODEBUG _Tp type; +}; template <class _Tp> class reference_wrapper; template <class _Tp> -struct __unwrap_reference<reference_wrapper<_Tp> > { typedef _LIBCPP_NODEBUG _Tp& type; }; +struct __unwrap_reference<reference_wrapper<_Tp> > { + typedef _LIBCPP_NODEBUG _Tp& type; +}; template <class _Tp> struct decay; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp> -struct unwrap_reference : __unwrap_reference<_Tp> { }; +struct unwrap_reference : __unwrap_reference<_Tp> {}; template <class _Tp> using unwrap_reference_t = typename unwrap_reference<_Tp>::type; template <class _Tp> -struct unwrap_ref_decay : unwrap_reference<typename decay<_Tp>::type> { }; +struct unwrap_ref_decay : unwrap_reference<__decay_t<_Tp> > {}; template <class _Tp> using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; -#endif // > C++17 +#endif // _LIBCPP_STD_VER >= 20 template <class _Tp> struct __unwrap_ref_decay -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 : unwrap_ref_decay<_Tp> #else - : __unwrap_reference<typename decay<_Tp>::type> + : __unwrap_reference<__decay_t<_Tp> > #endif -{ }; +{ +}; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP___FUNCTIONAL_UNWRAP_REF_H +#endif // _LIBCPP___TYPE_TRAITS_UNWRAP_REF_H diff --git a/libcxx/include/__type_traits/void_t.h b/libcxx/include/__type_traits/void_t.h index 1ed4e4354878..985bba02e72f 100644 --- a/libcxx/include/__type_traits/void_t.h +++ b/libcxx/include/__type_traits/void_t.h @@ -17,8 +17,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 -template <class...> using void_t = void; +#if _LIBCPP_STD_VER >= 17 +template <class...> +using void_t = void; #endif template <class...> diff --git a/libcxx/include/__undef_macros b/libcxx/include/__undef_macros index 3bacbbacb502..29ab327e1c37 100644 --- a/libcxx/include/__undef_macros +++ b/libcxx/include/__undef_macros @@ -14,3 +14,15 @@ #ifdef max # undef max #endif + +#ifdef refresh +# undef refresh +#endif + +#ifdef move +# undef move +#endif + +#ifdef erase +# undef erase +#endif diff --git a/libcxx/include/__utility/as_const.h b/libcxx/include/__utility/as_const.h index d4a72f43d4fa..b5c6091ecfed 100644 --- a/libcxx/include/__utility/as_const.h +++ b/libcxx/include/__utility/as_const.h @@ -20,7 +20,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr add_const_t<_Tp>& as_const(_Tp& __t) noexcept { return __t; } diff --git a/libcxx/include/__utility/auto_cast.h b/libcxx/include/__utility/auto_cast.h index 381ed0c205b2..06715b3438f9 100644 --- a/libcxx/include/__utility/auto_cast.h +++ b/libcxx/include/__utility/auto_cast.h @@ -17,6 +17,6 @@ # pragma GCC system_header #endif -#define _LIBCPP_AUTO_CAST(expr) static_cast<typename decay<decltype((expr))>::type>(expr) +#define _LIBCPP_AUTO_CAST(expr) static_cast<::std::__decay_t<decltype((expr))> >(expr) #endif // _LIBCPP___UTILITY_AUTO_CAST_H diff --git a/libcxx/include/__utility/cmp.h b/libcxx/include/__utility/cmp.h index d448a1d084be..7b7b90136e15 100644 --- a/libcxx/include/__utility/cmp.h +++ b/libcxx/include/__utility/cmp.h @@ -28,7 +28,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class _Tp, class... _Up> struct _IsSameAsAny : _Or<_IsSame<_Tp, _Up>...> {}; @@ -102,7 +102,7 @@ bool in_range(_Up __u) noexcept return _VSTD::cmp_less_equal(__u, numeric_limits<_Tp>::max()) && _VSTD::cmp_greater_equal(__u, numeric_limits<_Tp>::min()); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__utility/exception_guard.h b/libcxx/include/__utility/exception_guard.h index 737d1a69c971..389fca6c7101 100644 --- a/libcxx/include/__utility/exception_guard.h +++ b/libcxx/include/__utility/exception_guard.h @@ -19,6 +19,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // __exception_guard is a helper class for writing code with the strong exception guarantee. @@ -41,7 +44,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // less common, especially one that tries to catch an exception through -fno-exceptions code. // // __exception_guard can help greatly simplify code that would normally be cluttered by -// `#if _LIBCPP_NO_EXCEPTIONS`. For example: +// `#if _LIBCPP_HAS_NO_EXCEPTIONS`. For example: // // template <class Iterator, class Size, class OutputIterator> // Iterator uninitialized_copy_n(Iterator iter, Size n, OutputIterator out) { @@ -58,27 +61,27 @@ _LIBCPP_BEGIN_NAMESPACE_STD // } // -#ifndef _LIBCPP_NO_EXCEPTIONS template <class _Rollback> -struct __exception_guard { - __exception_guard() = delete; +struct __exception_guard_exceptions { + __exception_guard_exceptions() = delete; - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __exception_guard(_Rollback __rollback) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __exception_guard_exceptions(_Rollback __rollback) : __rollback_(std::move(__rollback)), __completed_(false) {} - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __exception_guard(__exception_guard&& __other) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + __exception_guard_exceptions(__exception_guard_exceptions&& __other) _NOEXCEPT_(is_nothrow_move_constructible<_Rollback>::value) : __rollback_(std::move(__other.__rollback_)), __completed_(__other.__completed_) { __other.__completed_ = true; } - __exception_guard(__exception_guard const&) = delete; - __exception_guard& operator=(__exception_guard const&) = delete; - __exception_guard& operator=(__exception_guard&&) = delete; + __exception_guard_exceptions(__exception_guard_exceptions const&) = delete; + __exception_guard_exceptions& operator=(__exception_guard_exceptions const&) = delete; + __exception_guard_exceptions& operator=(__exception_guard_exceptions&&) = delete; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __complete() _NOEXCEPT { __completed_ = true; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__exception_guard() { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__exception_guard_exceptions() { if (!__completed_) __rollback_(); } @@ -87,36 +90,47 @@ private: _Rollback __rollback_; bool __completed_; }; -#else // _LIBCPP_NO_EXCEPTIONS + +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__exception_guard_exceptions); + template <class _Rollback> -struct __exception_guard { - __exception_guard() = delete; - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG explicit __exception_guard(_Rollback) {} +struct __exception_guard_noexceptions { + __exception_guard_noexceptions() = delete; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + _LIBCPP_NODEBUG explicit __exception_guard_noexceptions(_Rollback) {} - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG __exception_guard(__exception_guard&& __other) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG + __exception_guard_noexceptions(__exception_guard_noexceptions&& __other) _NOEXCEPT_(is_nothrow_move_constructible<_Rollback>::value) : __completed_(__other.__completed_) { __other.__completed_ = true; } - __exception_guard(__exception_guard const&) = delete; - __exception_guard& operator=(__exception_guard const&) = delete; - __exception_guard& operator=(__exception_guard&&) = delete; + __exception_guard_noexceptions(__exception_guard_noexceptions const&) = delete; + __exception_guard_noexceptions& operator=(__exception_guard_noexceptions const&) = delete; + __exception_guard_noexceptions& operator=(__exception_guard_noexceptions&&) = delete; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG void __complete() _NOEXCEPT { __completed_ = true; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG ~__exception_guard() { - _LIBCPP_ASSERT(__completed_, "__exception_guard not completed with exceptions disabled"); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG ~__exception_guard_noexceptions() { + _LIBCPP_ASSERT_UNCATEGORIZED(__completed_, "__exception_guard not completed with exceptions disabled"); } private: bool __completed_ = false; }; -#endif // _LIBCPP_NO_EXCEPTIONS -_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__exception_guard); +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__exception_guard_noexceptions); + +#ifdef _LIBCPP_HAS_NO_EXCEPTIONS +template <class _Rollback> +using __exception_guard = __exception_guard_noexceptions<_Rollback>; +#else +template <class _Rollback> +using __exception_guard = __exception_guard_exceptions<_Rollback>; +#endif template <class _Rollback> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __exception_guard<_Rollback> __make_exception_guard(_Rollback __rollback) { @@ -125,4 +139,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __exception_guard<_Rollback> __make_exce _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___UTILITY_TRANSACTION_H diff --git a/libcxx/include/__utility/exchange.h b/libcxx/include/__utility/exchange.h index 8df71a17b1c0..4cbc921b739d 100644 --- a/libcxx/include/__utility/exchange.h +++ b/libcxx/include/__utility/exchange.h @@ -19,9 +19,12 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template<class _T1, class _T2 = _T1> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _T1 exchange(_T1& __obj, _T2&& __new_value) @@ -31,8 +34,10 @@ _T1 exchange(_T1& __obj, _T2&& __new_value) __obj = _VSTD::forward<_T2>(__new_value); return __old_value; } -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___UTILITY_EXCHANGE_H diff --git a/libcxx/include/__utility/forward_like.h b/libcxx/include/__utility/forward_like.h index 7bb0d7d2033c..ce11b640fc42 100644 --- a/libcxx/include/__utility/forward_like.h +++ b/libcxx/include/__utility/forward_like.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _Ap, class _Bp> using _CopyConst = _If<is_const_v<_Ap>, const _Bp, _Bp>; @@ -39,7 +39,7 @@ template <class _Tp, class _Up> return static_cast<_ForwardLike<_Tp, _Up>>(__ux); } -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__utility/in_place.h b/libcxx/include/__utility/in_place.h index a3518455e257..5b878529fb21 100644 --- a/libcxx/include/__utility/in_place.h +++ b/libcxx/include/__utility/in_place.h @@ -19,23 +19,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 -struct _LIBCPP_TYPE_VIS in_place_t { - explicit in_place_t() = default; +struct _LIBCPP_EXPORTED_FROM_ABI in_place_t { + explicit in_place_t() = default; }; inline constexpr in_place_t in_place{}; template <class _Tp> struct _LIBCPP_TEMPLATE_VIS in_place_type_t { - explicit in_place_type_t() = default; + _LIBCPP_HIDE_FROM_ABI explicit in_place_type_t() = default; }; template <class _Tp> inline constexpr in_place_type_t<_Tp> in_place_type{}; template <size_t _Idx> struct _LIBCPP_TEMPLATE_VIS in_place_index_t { - explicit in_place_index_t() = default; + _LIBCPP_HIDE_FROM_ABI explicit in_place_index_t() = default; }; template <size_t _Idx> inline constexpr in_place_index_t<_Idx> in_place_index{}; @@ -52,7 +52,7 @@ template <size_t _Idx> struct __is_inplace_index_imp<in_place_index_t<_Idx>> : t template <class _Tp> using __is_inplace_index = __is_inplace_index_imp<__remove_cvref_t<_Tp>>; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__utility/integer_sequence.h b/libcxx/include/__utility/integer_sequence.h index 257b4301c086..633b387d02ed 100644 --- a/libcxx/include/__utility/integer_sequence.h +++ b/libcxx/include/__utility/integer_sequence.h @@ -85,7 +85,7 @@ using __make_indices_imp = #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template<class _Tp, _Tp... _Ip> struct _LIBCPP_TEMPLATE_VIS integer_sequence @@ -138,15 +138,15 @@ template<size_t _Np> template<class... _Tp> using index_sequence_for = make_index_sequence<sizeof...(_Tp)>; -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 // Executes __func for every element in an index_sequence. template <size_t... _Index, class _Function> _LIBCPP_HIDE_FROM_ABI constexpr void __for_each_index_sequence(index_sequence<_Index...>, _Function __func) { (__func.template operator()<_Index>(), ...); } -# endif // _LIBCPP_STD_VER > 17 +# endif // _LIBCPP_STD_VER >= 20 -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__utility/is_pointer_in_range.h b/libcxx/include/__utility/is_pointer_in_range.h new file mode 100644 index 000000000000..e859562e7457 --- /dev/null +++ b/libcxx/include/__utility/is_pointer_in_range.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H +#define _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H + +#include <__algorithm/comp.h> +#include <__assert> +#include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/integral_constant.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp, class _Up, class = void> +struct __is_less_than_comparable : false_type {}; + +template <class _Tp, class _Up> +struct __is_less_than_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>() < std::declval<_Up>())> > : true_type { +}; + +template <class _Tp, class _Up, __enable_if_t<__is_less_than_comparable<const _Tp*, const _Up*>::value, int> = 0> +_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") bool __is_pointer_in_range( + const _Tp* __begin, const _Tp* __end, const _Up* __ptr) { + if (__libcpp_is_constant_evaluated()) { + _LIBCPP_ASSERT_UNCATEGORIZED(__builtin_constant_p(__begin <= __end), "__begin and __end do not form a range"); + + // If this is not a constant during constant evaluation we know that __ptr is not part of the allocation where + // [__begin, __end) is. + if (!__builtin_constant_p(__begin <= __ptr && __ptr < __end)) + return false; + } + + // Checking this for unrelated pointers is technically UB, but no compiler optimizes based on it (currently). + return !__less<>()(__ptr, __begin) && __less<>()(__ptr, __end); +} + +template <class _Tp, class _Up, __enable_if_t<!__is_less_than_comparable<const _Tp*, const _Up*>::value, int> = 0> +_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") bool __is_pointer_in_range( + const _Tp* __begin, const _Tp* __end, const _Up* __ptr) { + if (__libcpp_is_constant_evaluated()) + return false; + + return reinterpret_cast<const char*>(__begin) <= reinterpret_cast<const char*>(__ptr) && + reinterpret_cast<const char*>(__ptr) < reinterpret_cast<const char*>(__end); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H diff --git a/libcxx/include/__utility/move.h b/libcxx/include/__utility/move.h index 4859c39e8bd5..86d7fc88473b 100644 --- a/libcxx/include/__utility/move.h +++ b/libcxx/include/__utility/move.h @@ -20,6 +20,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> @@ -41,4 +44,6 @@ move_if_noexcept(_LIBCPP_LIFETIMEBOUND _Tp& __x) _NOEXCEPT { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___UTILITY_MOVE_H diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h index 8151674bcc55..43c9dbec737b 100644 --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -11,17 +11,23 @@ #include <__compare/common_comparison_category.h> #include <__compare/synth_three_way.h> +#include <__concepts/different_from.h> #include <__config> -#include <__functional/unwrap_ref.h> +#include <__fwd/array.h> #include <__fwd/get.h> +#include <__fwd/pair.h> +#include <__fwd/subrange.h> #include <__fwd/tuple.h> -#include <__tuple_dir/sfinae_helpers.h> -#include <__tuple_dir/tuple_element.h> -#include <__tuple_dir/tuple_indices.h> -#include <__tuple_dir/tuple_size.h> +#include <__tuple/pair_like.h> +#include <__tuple/sfinae_helpers.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_indices.h> +#include <__tuple/tuple_size.h> #include <__type_traits/common_reference.h> #include <__type_traits/common_type.h> #include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/integral_constant.h> #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> @@ -38,6 +44,9 @@ #include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> #include <__type_traits/nat.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/unwrap_ref.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/piecewise_construct.h> @@ -47,16 +56,25 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -#if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) template <class, class> struct __non_trivially_copyable_base { - _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __non_trivially_copyable_base() _NOEXCEPT {} - _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI __non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {} }; + +#if _LIBCPP_STD_VER >= 23 +template <class _Tp> +struct __is_specialization_of_subrange : false_type {}; + +template <class _Iter, class _Sent, ranges::subrange_kind _Kind> +struct __is_specialization_of_subrange<ranges::subrange<_Iter, _Sent, _Kind>> : true_type {}; #endif template <class _T1, class _T2> @@ -65,66 +83,80 @@ struct _LIBCPP_TEMPLATE_VIS pair : private __non_trivially_copyable_base<_T1, _T2> #endif { - typedef _T1 first_type; - typedef _T2 second_type; + using first_type = _T1; + using second_type = _T2; _T1 first; _T2 second; - pair(pair const&) = default; - pair(pair&&) = default; + _LIBCPP_HIDE_FROM_ABI pair(pair const&) = default; + _LIBCPP_HIDE_FROM_ABI pair(pair&&) = default; #ifdef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI pair() : first(), second() {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI pair(_T1 const& __t1, _T2 const& __t2) : first(__t1), second(__t2) {} template <class _U1, class _U2> - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI pair& operator=(pair const& __p) { first = __p.first; second = __p.second; return *this; } + + // Extension: This is provided in C++03 because it allows properly handling the + // assignment to a pair containing references, which would be a hard + // error otherwise. + template <class _U1, class _U2, class = __enable_if_t< + is_assignable<first_type&, _U1 const&>::value && + is_assignable<second_type&, _U2 const&>::value + > > + _LIBCPP_HIDE_FROM_ABI + pair& operator=(pair<_U1, _U2> const& __p) { + first = __p.first; + second = __p.second; + return *this; + } #else struct _CheckArgs { template <int&...> - static constexpr bool __enable_explicit_default() { + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_explicit_default() { return is_default_constructible<_T1>::value && is_default_constructible<_T2>::value && !__enable_implicit_default<>(); } template <int&...> - static constexpr bool __enable_implicit_default() { + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit_default() { return __is_implicitly_default_constructible<_T1>::value && __is_implicitly_default_constructible<_T2>::value; } template <class _U1, class _U2> - static constexpr bool __is_pair_constructible() { + static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_pair_constructible() { return is_constructible<first_type, _U1>::value && is_constructible<second_type, _U2>::value; } template <class _U1, class _U2> - static constexpr bool __is_implicit() { + static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_implicit() { return is_convertible<_U1, first_type>::value && is_convertible<_U2, second_type>::value; } template <class _U1, class _U2> - static constexpr bool __enable_explicit() { + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_explicit() { return __is_pair_constructible<_U1, _U2>() && !__is_implicit<_U1, _U2>(); } template <class _U1, class _U2> - static constexpr bool __enable_implicit() { + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit() { return __is_pair_constructible<_U1, _U2>() && __is_implicit<_U1, _U2>(); } }; @@ -133,36 +165,10 @@ struct _LIBCPP_TEMPLATE_VIS pair using _CheckArgsDep _LIBCPP_NODEBUG = typename conditional< _MaybeEnable, _CheckArgs, __check_tuple_constructor_fail>::type; - struct _CheckTupleLikeConstructor { - template <class _Tuple> - static constexpr bool __enable_implicit() { - return __tuple_convertible<_Tuple, pair>::value; - } - - template <class _Tuple> - static constexpr bool __enable_explicit() { - return __tuple_constructible<_Tuple, pair>::value - && !__tuple_convertible<_Tuple, pair>::value; - } - - template <class _Tuple> - static constexpr bool __enable_assign() { - return __tuple_assignable<_Tuple, pair>::value; - } - }; - - template <class _Tuple> - using _CheckTLC _LIBCPP_NODEBUG = __conditional_t< - __tuple_like_with_size<_Tuple, 2>::value - && !is_same<typename decay<_Tuple>::type, pair>::value, - _CheckTupleLikeConstructor, - __check_tuple_constructor_fail - >; - template<bool _Dummy = true, typename enable_if< _CheckArgsDep<_Dummy>::__enable_explicit_default() >::type* = nullptr> - explicit _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair() _NOEXCEPT_(is_nothrow_default_constructible<first_type>::value && is_nothrow_default_constructible<second_type>::value) : first(), second() {} @@ -170,7 +176,7 @@ struct _LIBCPP_TEMPLATE_VIS pair template<bool _Dummy = true, typename enable_if< _CheckArgsDep<_Dummy>::__enable_implicit_default() >::type* = nullptr> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair() _NOEXCEPT_(is_nothrow_default_constructible<first_type>::value && is_nothrow_default_constructible<second_type>::value) : first(), second() {} @@ -178,7 +184,7 @@ struct _LIBCPP_TEMPLATE_VIS pair template <bool _Dummy = true, typename enable_if< _CheckArgsDep<_Dummy>::template __enable_explicit<_T1 const&, _T2 const&>() >::type* = nullptr> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(_T1 const& __t1, _T2 const& __t2) _NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value && is_nothrow_copy_constructible<second_type>::value) @@ -187,41 +193,41 @@ struct _LIBCPP_TEMPLATE_VIS pair template<bool _Dummy = true, typename enable_if< _CheckArgsDep<_Dummy>::template __enable_implicit<_T1 const&, _T2 const&>() >::type* = nullptr> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(_T1 const& __t1, _T2 const& __t2) _NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value && is_nothrow_copy_constructible<second_type>::value) : first(__t1), second(__t2) {} template < -#if _LIBCPP_STD_VER > 20 // http://wg21.link/P1951 +#if _LIBCPP_STD_VER >= 23 // http://wg21.link/P1951 class _U1 = _T1, class _U2 = _T2, #else class _U1, class _U2, #endif typename enable_if<_CheckArgs::template __enable_explicit<_U1, _U2>()>::type* = nullptr > - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(_U1&& __u1, _U2&& __u2) _NOEXCEPT_((is_nothrow_constructible<first_type, _U1>::value && is_nothrow_constructible<second_type, _U2>::value)) - : first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {} + : first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) {} template < -#if _LIBCPP_STD_VER > 20 // http://wg21.link/P1951 +#if _LIBCPP_STD_VER >= 23 // http://wg21.link/P1951 class _U1 = _T1, class _U2 = _T2, #else class _U1, class _U2, #endif typename enable_if<_CheckArgs::template __enable_implicit<_U1, _U2>()>::type* = nullptr > - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(_U1&& __u1, _U2&& __u2) _NOEXCEPT_((is_nothrow_constructible<first_type, _U1>::value && is_nothrow_constructible<second_type, _U2>::value)) - : first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {} + : first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) {} -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template<class _U1, class _U2, __enable_if_t< _CheckArgs::template __is_pair_constructible<_U1&, _U2&>() >* = nullptr> @@ -235,7 +241,7 @@ struct _LIBCPP_TEMPLATE_VIS pair template<class _U1, class _U2, typename enable_if< _CheckArgs::template __enable_explicit<_U1 const&, _U2 const&>() >::type* = nullptr> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(pair<_U1, _U2> const& __p) _NOEXCEPT_((is_nothrow_constructible<first_type, _U1 const&>::value && is_nothrow_constructible<second_type, _U2 const&>::value)) @@ -244,7 +250,7 @@ struct _LIBCPP_TEMPLATE_VIS pair template<class _U1, class _U2, typename enable_if< _CheckArgs::template __enable_implicit<_U1 const&, _U2 const&>() >::type* = nullptr> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(pair<_U1, _U2> const& __p) _NOEXCEPT_((is_nothrow_constructible<first_type, _U1 const&>::value && is_nothrow_constructible<second_type, _U2 const&>::value)) @@ -253,22 +259,22 @@ struct _LIBCPP_TEMPLATE_VIS pair template<class _U1, class _U2, typename enable_if< _CheckArgs::template __enable_explicit<_U1, _U2>() >::type* = nullptr> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(pair<_U1, _U2>&&__p) _NOEXCEPT_((is_nothrow_constructible<first_type, _U1&&>::value && is_nothrow_constructible<second_type, _U2&&>::value)) - : first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {} + : first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) {} template<class _U1, class _U2, typename enable_if< _CheckArgs::template __enable_implicit<_U1, _U2>() >::type* = nullptr> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(pair<_U1, _U2>&& __p) _NOEXCEPT_((is_nothrow_constructible<first_type, _U1&&>::value && is_nothrow_constructible<second_type, _U2&&>::value)) - : first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {} + : first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) {} -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template<class _U1, class _U2, __enable_if_t< _CheckArgs::template __is_pair_constructible<const _U1&&, const _U2&&>() >* = nullptr> @@ -280,24 +286,27 @@ struct _LIBCPP_TEMPLATE_VIS pair : first(std::move(__p.first)), second(std::move(__p.second)) {} #endif - template<class _Tuple, typename enable_if< - _CheckTLC<_Tuple>::template __enable_explicit<_Tuple>() - >::type* = nullptr> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - explicit pair(_Tuple&& __p) - : first(_VSTD::get<0>(_VSTD::forward<_Tuple>(__p))), - second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {} +# if _LIBCPP_STD_VER >= 23 + // This is a workaround for http://llvm.org/PR60710. We should be able to remove it once Clang is fixed. + template <class _PairLike, bool _Enable = tuple_size<remove_cvref_t<_PairLike>>::value == 2> + _LIBCPP_HIDE_FROM_ABI static constexpr bool __pair_like_explicit_wknd() { + if constexpr (tuple_size<remove_cvref_t<_PairLike>>::value == 2) { + return !is_convertible_v<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> || + !is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>; + } + return false; + } - template<class _Tuple, typename enable_if< - _CheckTLC<_Tuple>::template __enable_implicit<_Tuple>() - >::type* = nullptr> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 - pair(_Tuple&& __p) - : first(_VSTD::get<0>(_VSTD::forward<_Tuple>(__p))), - second(_VSTD::get<1>(_VSTD::forward<_Tuple>(__p))) {} + template <__pair_like _PairLike> + requires(is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike&&>()))> && + is_constructible_v<second_type, decltype(std::get<1>(std::declval<_PairLike&&>()))>) + _LIBCPP_HIDE_FROM_ABI constexpr explicit(__pair_like_explicit_wknd<_PairLike>()) + pair(_PairLike&& __p) + : first(std::get<0>(std::forward<_PairLike>(__p))), second(std::get<1>(std::forward<_PairLike>(__p))) {} +# endif template <class... _Args1, class... _Args2> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args, tuple<_Args2...> __second_args) _NOEXCEPT_((is_nothrow_constructible<first_type, _Args1...>::value && @@ -306,7 +315,7 @@ struct _LIBCPP_TEMPLATE_VIS pair typename __make_tuple_indices<sizeof...(_Args1)>::type(), typename __make_tuple_indices<sizeof...(_Args2) >::type()) {} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair& operator=(__conditional_t< is_copy_assignable<first_type>::value && is_copy_assignable<second_type>::value, @@ -319,7 +328,7 @@ struct _LIBCPP_TEMPLATE_VIS pair return *this; } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair& operator=(__conditional_t< is_move_assignable<first_type>::value && is_move_assignable<second_type>::value, @@ -327,12 +336,34 @@ struct _LIBCPP_TEMPLATE_VIS pair _NOEXCEPT_(is_nothrow_move_assignable<first_type>::value && is_nothrow_move_assignable<second_type>::value) { - first = _VSTD::forward<first_type>(__p.first); - second = _VSTD::forward<second_type>(__p.second); + first = std::forward<first_type>(__p.first); + second = std::forward<second_type>(__p.second); return *this; } -#if _LIBCPP_STD_VER > 20 + template <class _U1, class _U2, __enable_if_t< + is_assignable<first_type&, _U1 const&>::value && + is_assignable<second_type&, _U2 const&>::value + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + pair& operator=(pair<_U1, _U2> const& __p) { + first = __p.first; + second = __p.second; + return *this; + } + + template <class _U1, class _U2, __enable_if_t< + is_assignable<first_type&, _U1>::value && + is_assignable<second_type&, _U2>::value + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + pair& operator=(pair<_U1, _U2>&& __p) { + first = std::forward<_U1>(__p.first); + second = std::forward<_U2>(__p.second); + return *this; + } + +# if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr const pair& operator=(pair const& __p) const noexcept(is_nothrow_copy_assignable_v<const first_type> && @@ -374,30 +405,178 @@ struct _LIBCPP_TEMPLATE_VIS pair second = std::forward<_U2>(__p.second); return *this; } -#endif // _LIBCPP_STD_VER > 20 - - template <class _Tuple, typename enable_if< - _CheckTLC<_Tuple>::template __enable_assign<_Tuple>() - >::type* = nullptr> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 - pair& operator=(_Tuple&& __p) { - first = _VSTD::get<0>(_VSTD::forward<_Tuple>(__p)); - second = _VSTD::get<1>(_VSTD::forward<_Tuple>(__p)); + + template <__pair_like _PairLike> + requires(__different_from<_PairLike, pair> && + !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value && + is_assignable_v<first_type&, decltype(std::get<0>(std::declval<_PairLike>()))> && + is_assignable_v<second_type&, decltype(std::get<1>(std::declval<_PairLike>()))>) + _LIBCPP_HIDE_FROM_ABI constexpr pair& operator=(_PairLike&& __p) { + first = std::get<0>(std::forward<_PairLike>(__p)); + second = std::get<1>(std::forward<_PairLike>(__p)); return *this; } -#endif - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + template <__pair_like _PairLike> + requires(__different_from<_PairLike, pair> && + !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value && + is_assignable_v<first_type const&, decltype(std::get<0>(std::declval<_PairLike>()))> && + is_assignable_v<second_type const&, decltype(std::get<1>(std::declval<_PairLike>()))>) + _LIBCPP_HIDE_FROM_ABI constexpr pair const& operator=(_PairLike&& __p) const { + first = std::get<0>(std::forward<_PairLike>(__p)); + second = std::get<1>(std::forward<_PairLike>(__p)); + return *this; + } +# endif // _LIBCPP_STD_VER >= 23 + + // Prior to C++23, we provide an approximation of constructors and assignment operators from + // pair-like types. This was historically provided as an extension. +#if _LIBCPP_STD_VER < 23 + // from std::tuple + template<class _U1, class _U2, __enable_if_t< + is_convertible<_U1 const&, _T1>::value && + is_convertible<_U2 const&, _T2>::value + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + pair(tuple<_U1, _U2> const& __p) + : first(std::get<0>(__p)), + second(std::get<1>(__p)) {} + + template<class _U1, class _U2, __enable_if_t< + is_constructible<_T1, _U1 const&>::value && + is_constructible<_T2, _U2 const&>::value && + !(is_convertible<_U1 const&, _T1>::value && + is_convertible<_U2 const&, _T2>::value) + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + explicit + pair(tuple<_U1, _U2> const& __p) + : first(std::get<0>(__p)), + second(std::get<1>(__p)) {} + + template<class _U1, class _U2, __enable_if_t< + is_convertible<_U1, _T1>::value && + is_convertible<_U2, _T2>::value + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + pair(tuple<_U1, _U2>&& __p) + : first(std::get<0>(std::move(__p))), + second(std::get<1>(std::move(__p))) {} + + template<class _U1, class _U2, __enable_if_t< + is_constructible<_T1, _U1>::value && + is_constructible<_T2, _U2>::value && + !(is_convertible<_U1, _T1>::value && + is_convertible<_U2, _T2>::value) + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + explicit + pair(tuple<_U1, _U2>&& __p) + : first(std::get<0>(std::move(__p))), + second(std::get<1>(std::move(__p))) {} + + + template<class _U1, class _U2, __enable_if_t< + is_assignable<_T1&, _U1 const&>::value && + is_assignable<_T2&, _U2 const&>::value + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + pair& operator=(tuple<_U1, _U2> const& __p) { + first = std::get<0>(__p); + second = std::get<1>(__p); + return *this; + } + + template<class _U1, class _U2, __enable_if_t< + is_assignable<_T1&, _U1&&>::value && + is_assignable<_T2&, _U2&&>::value + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + pair& operator=(tuple<_U1, _U2>&& __p) { + first = std::get<0>(std::move(__p)); + second = std::get<1>(std::move(__p)); + return *this; + } + + // from std::array + template<class _Up, __enable_if_t< + is_convertible<_Up const&, _T1>::value && + is_convertible<_Up const&, _T2>::value + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + pair(array<_Up, 2> const& __p) + : first(__p[0]), + second(__p[1]) {} + + template<class _Up, __enable_if_t< + is_constructible<_T1, _Up const&>::value && + is_constructible<_T2, _Up const&>::value && + !(is_convertible<_Up const&, _T1>::value && + is_convertible<_Up const&, _T2>::value) + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + explicit + pair(array<_Up, 2> const& __p) + : first(__p[0]), + second(__p[1]) {} + + template<class _Up, __enable_if_t< + is_convertible<_Up, _T1>::value && + is_convertible<_Up, _T2>::value + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + pair(array<_Up, 2>&& __p) + : first(std::move(__p)[0]), + second(std::move(__p)[1]) {} + + template<class _Up, __enable_if_t< + is_constructible<_T1, _Up>::value && + is_constructible<_T2, _Up>::value && + !(is_convertible<_Up, _T1>::value && + is_convertible<_Up, _T2>::value) + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + explicit + pair(array<_Up, 2>&& __p) + : first(std::move(__p)[0]), + second(std::move(__p)[1]) {} + + + template<class _Up, __enable_if_t< + is_assignable<_T1&, _Up const&>::value && + is_assignable<_T2&, _Up const&>::value + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + pair& operator=(array<_Up, 2> const& __p) { + first = std::get<0>(__p); + second = std::get<1>(__p); + return *this; + } + + template<class _Up, __enable_if_t< + is_assignable<_T1&, _Up>::value && + is_assignable<_T2&, _Up>::value + >* = nullptr> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 + pair& operator=(array<_Up, 2>&& __p) { + first = std::get<0>(std::move(__p)); + second = std::get<1>(std::move(__p)); + return *this; + } +#endif // _LIBCPP_STD_VER < 23 +#endif // _LIBCPP_CXX03_LANG + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(pair& __p) _NOEXCEPT_(__is_nothrow_swappable<first_type>::value && __is_nothrow_swappable<second_type>::value) { - using _VSTD::swap; + using std::swap; swap(first, __p.first); swap(second, __p.second); } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr void swap(const pair& __p) const noexcept(__is_nothrow_swappable<const first_type>::value && @@ -412,88 +591,88 @@ private: #ifndef _LIBCPP_CXX03_LANG template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2> - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair(piecewise_construct_t, tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args, __tuple_indices<_I1...>, __tuple_indices<_I2...>); #endif }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template<class _T1, class _T2> pair(_T1, _T2) -> pair<_T1, _T2>; #endif // [pairs.spec], specialized algorithms -template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +template <class _T1, class _T2, class _U1, class _U2> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool -operator==(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) +operator==(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y) { return __x.first == __y.first && __x.second == __y.second; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 -template <class _T1, class _T2> +template <class _T1, class _T2, class _U1, class _U2> _LIBCPP_HIDE_FROM_ABI constexpr common_comparison_category_t< - __synth_three_way_result<_T1>, - __synth_three_way_result<_T2> > -operator<=>(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) + __synth_three_way_result<_T1, _U1>, + __synth_three_way_result<_T2, _U2> > +operator<=>(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y) { - if (auto __c = _VSTD::__synth_three_way(__x.first, __y.first); __c != 0) { + if (auto __c = std::__synth_three_way(__x.first, __y.first); __c != 0) { return __c; } - return _VSTD::__synth_three_way(__x.second, __y.second); + return std::__synth_three_way(__x.second, __y.second); } -#else // _LIBCPP_STD_VER > 17 +#else // _LIBCPP_STD_VER >= 20 -template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +template <class _T1, class _T2, class _U1, class _U2> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool -operator!=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) +operator!=(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y) { return !(__x == __y); } -template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +template <class _T1, class _T2, class _U1, class _U2> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool -operator< (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) +operator< (const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y) { return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second); } -template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +template <class _T1, class _T2, class _U1, class _U2> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool -operator> (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) +operator> (const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y) { return __y < __x; } -template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +template <class _T1, class _T2, class _U1, class _U2> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool -operator>=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) +operator>=(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y) { return !(__x < __y); } -template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +template <class _T1, class _T2, class _U1, class _U2> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool -operator<=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y) +operator<=(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y) { return !(__y < __x); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _T1, class _T2, class _U1, class _U2, template<class> class _TQual, template<class> class _UQual> requires requires { typename pair<common_reference_t<_TQual<_T1>, _UQual<_U1>>, common_reference_t<_TQual<_T2>, _UQual<_U2>>>; } @@ -507,10 +686,10 @@ template <class _T1, class _T2, class _U1, class _U2> struct common_type<pair<_T1, _T2>, pair<_U1, _U2>> { using type = pair<common_type_t<_T1, _U1>, common_type_t<_T2, _U2>>; }; -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < __is_swappable<_T1>::value && @@ -524,7 +703,7 @@ swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) __x.swap(__y); } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _T1, class _T2> requires (__is_swappable<const _T1>::value && __is_swappable<const _T2>::value) @@ -537,12 +716,12 @@ void swap(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) #endif template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type> make_pair(_T1&& __t1, _T2&& __t2) { return pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type> - (_VSTD::forward<_T1>(__t1), _VSTD::forward<_T2>(__t2)); + (std::forward<_T1>(__t1), std::forward<_T2>(__t2)); } template <class _T1, class _T2> @@ -558,13 +737,13 @@ struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, pair<_T1, _T2> > template <class _T1, class _T2> struct _LIBCPP_TEMPLATE_VIS tuple_element<0, pair<_T1, _T2> > { - typedef _LIBCPP_NODEBUG _T1 type; + using type _LIBCPP_NODEBUG = _T1; }; template <class _T1, class _T2> struct _LIBCPP_TEMPLATE_VIS tuple_element<1, pair<_T1, _T2> > { - typedef _LIBCPP_NODEBUG _T2 type; + using type _LIBCPP_NODEBUG = _T2; }; template <size_t _Ip> struct __get_pair; @@ -574,27 +753,27 @@ struct __get_pair<0> { template <class _T1, class _T2> static - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _T1& get(pair<_T1, _T2>& __p) _NOEXCEPT {return __p.first;} template <class _T1, class _T2> static - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T1& get(const pair<_T1, _T2>& __p) _NOEXCEPT {return __p.first;} template <class _T1, class _T2> static - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _T1&& - get(pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<_T1>(__p.first);} + get(pair<_T1, _T2>&& __p) _NOEXCEPT {return std::forward<_T1>(__p.first);} template <class _T1, class _T2> static - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T1&& - get(const pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<const _T1>(__p.first);} + get(const pair<_T1, _T2>&& __p) _NOEXCEPT {return std::forward<const _T1>(__p.first);} }; template <> @@ -602,31 +781,31 @@ struct __get_pair<1> { template <class _T1, class _T2> static - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _T2& get(pair<_T1, _T2>& __p) _NOEXCEPT {return __p.second;} template <class _T1, class _T2> static - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T2& get(const pair<_T1, _T2>& __p) _NOEXCEPT {return __p.second;} template <class _T1, class _T2> static - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _T2&& - get(pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<_T2>(__p.second);} + get(pair<_T1, _T2>&& __p) _NOEXCEPT {return std::forward<_T2>(__p.second);} template <class _T1, class _T2> static - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T2&& - get(const pair<_T1, _T2>&& __p) _NOEXCEPT {return _VSTD::forward<const _T2>(__p.second);} + get(const pair<_T1, _T2>&& __p) _NOEXCEPT {return std::forward<const _T2>(__p.second);} }; template <size_t _Ip, class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, pair<_T1, _T2> >::type& get(pair<_T1, _T2>& __p) _NOEXCEPT { @@ -634,7 +813,7 @@ get(pair<_T1, _T2>& __p) _NOEXCEPT } template <size_t _Ip, class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, pair<_T1, _T2> >::type& get(const pair<_T1, _T2>& __p) _NOEXCEPT { @@ -642,80 +821,82 @@ get(const pair<_T1, _T2>& __p) _NOEXCEPT } template <size_t _Ip, class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, pair<_T1, _T2> >::type&& get(pair<_T1, _T2>&& __p) _NOEXCEPT { - return __get_pair<_Ip>::get(_VSTD::move(__p)); + return __get_pair<_Ip>::get(std::move(__p)); } template <size_t _Ip, class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, pair<_T1, _T2> >::type&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT { - return __get_pair<_Ip>::get(_VSTD::move(__p)); + return __get_pair<_Ip>::get(std::move(__p)); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 & get(pair<_T1, _T2>& __p) _NOEXCEPT { return __get_pair<0>::get(__p); } template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const & get(pair<_T1, _T2> const& __p) _NOEXCEPT { return __get_pair<0>::get(__p); } template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 && get(pair<_T1, _T2>&& __p) _NOEXCEPT { - return __get_pair<0>::get(_VSTD::move(__p)); + return __get_pair<0>::get(std::move(__p)); } template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const && get(pair<_T1, _T2> const&& __p) _NOEXCEPT { - return __get_pair<0>::get(_VSTD::move(__p)); + return __get_pair<0>::get(std::move(__p)); } template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 & get(pair<_T2, _T1>& __p) _NOEXCEPT { return __get_pair<1>::get(__p); } template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const & get(pair<_T2, _T1> const& __p) _NOEXCEPT { return __get_pair<1>::get(__p); } template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 && get(pair<_T2, _T1>&& __p) _NOEXCEPT { - return __get_pair<1>::get(_VSTD::move(__p)); + return __get_pair<1>::get(std::move(__p)); } template <class _T1, class _T2> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const && get(pair<_T2, _T1> const&& __p) _NOEXCEPT { - return __get_pair<1>::get(_VSTD::move(__p)); + return __get_pair<1>::get(std::move(__p)); } -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___UTILITY_PAIR_H diff --git a/libcxx/include/__utility/piecewise_construct.h b/libcxx/include/__utility/piecewise_construct.h index 3cc86fef2a0f..ad86badb66c8 100644 --- a/libcxx/include/__utility/piecewise_construct.h +++ b/libcxx/include/__utility/piecewise_construct.h @@ -18,10 +18,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD struct _LIBCPP_TEMPLATE_VIS piecewise_construct_t { explicit piecewise_construct_t() = default; }; -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) -extern _LIBCPP_EXPORTED_FROM_ABI const piecewise_construct_t piecewise_construct;// = piecewise_construct_t(); -#else -/* inline */ constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); + +#if _LIBCPP_STD_VER >= 17 +inline constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); +#elif !defined(_LIBCPP_CXX03_LANG) +constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__utility/swap.h b/libcxx/include/__utility/swap.h index 0843b35a8b58..767f69cc2fff 100644 --- a/libcxx/include/__utility/swap.h +++ b/libcxx/include/__utility/swap.h @@ -23,6 +23,9 @@ # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_CXX03_LANG @@ -51,4 +54,6 @@ swap(_Tp (&__a)[_Np], _Tp (&__b)[_Np]) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::v _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___UTILITY_SWAP_H diff --git a/libcxx/include/__utility/terminate_on_exception.h b/libcxx/include/__utility/terminate_on_exception.h new file mode 100644 index 000000000000..e035ec3409ae --- /dev/null +++ b/libcxx/include/__utility/terminate_on_exception.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___UTILITY_TERMINATE_ON_EXCEPTION_H +#define _LIBCPP___UTILITY_TERMINATE_ON_EXCEPTION_H + +#include <__config> +#include <__exception/terminate.h> +#include <new> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +# ifndef _LIBCPP_HAS_NO_EXCEPTIONS + +template <class _Func> +_LIBCPP_HIDE_FROM_ABI auto __terminate_on_exception(_Func __func) { + try { + return __func(); + } catch (...) { + std::terminate(); + } +} + +# else // _LIBCPP_HAS_NO_EXCEPTIONS + +template <class _Func> +_LIBCPP_HIDE_FROM_ABI auto __terminate_on_exception(_Func __func) { + return __func(); +} + +# endif // _LIBCPP_HAS_NO_EXCEPTIONS + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 17 + +#endif // _LIBCPP___UTILITY_TERMINATE_ON_EXCEPTION_H diff --git a/libcxx/include/__utility/to_underlying.h b/libcxx/include/__utility/to_underlying.h index a194d3ef28c5..b70f70a74be9 100644 --- a/libcxx/include/__utility/to_underlying.h +++ b/libcxx/include/__utility/to_underlying.h @@ -27,7 +27,7 @@ __to_underlying(_Tp __val) noexcept { } #endif // !_LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _Tp> _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY constexpr underlying_type_t<_Tp> to_underlying(_Tp __val) noexcept { diff --git a/libcxx/include/__utility/unreachable.h b/libcxx/include/__utility/unreachable.h index d93e60b10b86..4a21b74b1973 100644 --- a/libcxx/include/__utility/unreachable.h +++ b/libcxx/include/__utility/unreachable.h @@ -19,11 +19,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI inline void __libcpp_unreachable() { - _LIBCPP_ASSERT(false, "std::unreachable() was reached"); + _LIBCPP_ASSERT_UNCATEGORIZED(false, "std::unreachable() was reached"); __builtin_unreachable(); } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 [[noreturn]] _LIBCPP_HIDE_FROM_ABI inline void unreachable() { __libcpp_unreachable(); } diff --git a/libcxx/include/__variant/monostate.h b/libcxx/include/__variant/monostate.h index b3b4597dd985..8fec34008f2d 100644 --- a/libcxx/include/__variant/monostate.h +++ b/libcxx/include/__variant/monostate.h @@ -21,19 +21,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 struct _LIBCPP_TEMPLATE_VIS monostate {}; _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(monostate, monostate) noexcept { return true; } -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; } -# else // _LIBCPP_STD_VER > 17 +# else // _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(monostate, monostate) noexcept { return false; } @@ -45,7 +45,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(monostate, monostate) noexcept { _LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(monostate, monostate) noexcept { return true; } -# endif // _LIBCPP_STD_VER > 17 +# endif // _LIBCPP_STD_VER >= 20 template <> struct _LIBCPP_TEMPLATE_VIS hash<monostate> { @@ -57,7 +57,7 @@ struct _LIBCPP_TEMPLATE_VIS hash<monostate> { } }; -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__verbose_abort b/libcxx/include/__verbose_abort index a16d75d5ac4c..a38284b711f3 100644 --- a/libcxx/include/__verbose_abort +++ b/libcxx/include/__verbose_abort @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // This function should never be called directly from the code -- it should only be called through // the _LIBCPP_VERBOSE_ABORT macro. -_LIBCPP_NORETURN _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) +_LIBCPP_NORETURN _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) void __libcpp_verbose_abort(const char *__format, ...); // _LIBCPP_VERBOSE_ABORT(format, args...) @@ -40,16 +40,19 @@ void __libcpp_verbose_abort(const char *__format, ...); // Support _LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED until LLVM 18, but tell people // to move to customizing _LIBCPP_VERBOSE_ABORT instead. -# if defined(_LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY) && defined(_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED) -# undef _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY +# if defined(_LIBCPP_AVAILABILITY_HAS_NO_VERBOSE_ABORT) && defined(_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED) +# undef _LIBCPP_AVAILABILITY_HAS_NO_VERBOSE_ABORT # warning _LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED is deprecated, please customize _LIBCPP_VERBOSE_ABORT instead # endif -# if defined(_LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY) -# define _LIBCPP_VERBOSE_ABORT(...) __builtin_abort() +# if defined(_LIBCPP_AVAILABILITY_HAS_NO_VERBOSE_ABORT) +// The decltype is there to suppress -Wunused warnings in this configuration. +void __use(const char*, ...); +# define _LIBCPP_VERBOSE_ABORT(...) (decltype(::std::__use(__VA_ARGS__))(), __builtin_abort()) # else # define _LIBCPP_VERBOSE_ABORT(...) ::std::__libcpp_verbose_abort(__VA_ARGS__) # endif + #endif // !defined(_LIBCPP_VERBOSE_ABORT) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index cb2d27cbc80c..76e0d22bf73e 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -22,41 +22,41 @@ namespace ranges { // [algorithms.results], algorithm result types template <class I, class F> - struct in_fun_result; // since C++20 + struct in_fun_result; // since C++20 template <class I1, class I2> - struct in_in_result; // since C++20 + struct in_in_result; // since C++20 template <class I, class O> - struct in_out_result; // since C++20 + struct in_out_result; // since C++20 template <class I1, class I2, class O> - struct in_in_out_result; // since C++20 + struct in_in_out_result; // since C++20 template <class I, class O1, class O2> - struct in_out_out_result; // since C++20 + struct in_out_out_result; // since C++20 template <class I1, class I2> - struct min_max_result; // since C++20 + struct min_max_result; // since C++20 template <class I> - struct in_found_result; // since C++20 + struct in_found_result; // since C++20 template<forward_iterator I, sentinel_for<I> S, class Proj = identity, - indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> // since C++20 + indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> // since C++20 constexpr I min_element(I first, S last, Comp comp = {}, Proj proj = {}); template<forward_range R, class Proj = identity, - indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> // since C++20 + indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> // since C++20 constexpr borrowed_iterator_t<R> min_element(R&& r, Comp comp = {}, Proj proj = {}); template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> - constexpr I ranges::max_element(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20 + constexpr I ranges::max_element(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20 template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> - constexpr borrowed_iterator_t<R> ranges::max_element(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 + constexpr borrowed_iterator_t<R> ranges::max_element(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 template<class I1, class I2> using mismatch_result = in_in_result<I1, I2>; @@ -64,86 +64,86 @@ namespace ranges { template <input_iterator I1, sentinel_for<_I1> S1, input_iterator I2, sentinel_for<_I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> - constexpr mismatch_result<_I1, _I2> - mismatch()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) // since C++20 + constexpr mismatch_result<_I1, _I2> // since C++20 + mismatch()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) template <input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr mismatch_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>> - mismatch(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) // since C++20 + mismatch(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) // since C++20 requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> - constexpr I find(I first, S last, const T& value, Proj proj = {}); // since C++20 + constexpr I find(I first, S last, const T& value, Proj proj = {}); // since C++20 template<input_range R, class T, class Proj = identity> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr borrowed_iterator_t<R> - find(R&& r, const T& value, Proj proj = {}); // since C++20 + find(R&& r, const T& value, Proj proj = {}); // since C++20 template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> - constexpr I find_if(I first, S last, Pred pred, Proj proj = {}); // since C++20 + constexpr I find_if(I first, S last, Pred pred, Proj proj = {}); // since C++20 template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_iterator_t<R> - find_if(R&& r, Pred pred, Proj proj = {}); // since C++20 + find_if(R&& r, Pred pred, Proj proj = {}); // since C++20 template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> - constexpr I find_if_not(I first, S last, Pred pred, Proj proj = {}); // since C++20 + constexpr I find_if_not(I first, S last, Pred pred, Proj proj = {}); // since C++20 template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_iterator_t<R> - find_if_not(R&& r, Pred pred, Proj proj = {}); // since C++20 + find_if_not(R&& r, Pred pred, Proj proj = {}); // since C++20 template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> - constexpr const T& min(const T& a, const T& b, Comp comp = {}, Proj proj = {}); // since C++20 + constexpr const T& min(const T& a, const T& b, Comp comp = {}, Proj proj = {}); // since C++20 template<copyable T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> - constexpr T min(initializer_list<T> r, Comp comp = {}, Proj proj = {}); // since C++20 + constexpr T min(initializer_list<T> r, Comp comp = {}, Proj proj = {}); // since C++20 template<input_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> constexpr range_value_t<R> - min(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 + min(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> - constexpr const T& max(const T& a, const T& b, Comp comp = {}, Proj proj = {}); // since C++20 + constexpr const T& max(const T& a, const T& b, Comp comp = {}, Proj proj = {}); // since C++20 template<copyable T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> - constexpr T max(initializer_list<T> r, Comp comp = {}, Proj proj = {}); // since C++20 + constexpr T max(initializer_list<T> r, Comp comp = {}, Proj proj = {}); // since C++20 template<input_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> constexpr range_value_t<R> - max(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 + max(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 template<class I, class O> - using unary_transform_result = in_out_result<I, O>; // since C++20 + using unary_transform_result = in_out_result<I, O>; // since C++20 template<class I1, class I2, class O> - using binary_transform_result = in_in_out_result<I1, I2, O>; // since C++20 + using binary_transform_result = in_in_out_result<I1, I2, O>; // since C++20 template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, copy_constructible F, class Proj = identity> requires indirectly_writable<O, indirect_result_t<F&, projected<I, Proj>>> constexpr ranges::unary_transform_result<I, O> - transform(I first1, S last1, O result, F op, Proj proj = {}); // since C++20 + transform(I first1, S last1, O result, F op, Proj proj = {}); // since C++20 template<input_range R, weakly_incrementable O, copy_constructible F, class Proj = identity> requires indirectly_writable<O, indirect_result_t<F&, projected<iterator_t<R>, Proj>>> constexpr ranges::unary_transform_result<borrowed_iterator_t<R>, O> - transform(R&& r, O result, F op, Proj proj = {}); // since C++20 + transform(R&& r, O result, F op, Proj proj = {}); // since C++20 template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, weakly_incrementable O, copy_constructible F, class Proj1 = identity, @@ -152,7 +152,7 @@ namespace ranges { projected<I2, Proj2>>> constexpr ranges::binary_transform_result<I1, I2, O> transform(I1 first1, S1 last1, I2 first2, S2 last2, O result, - F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 + F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 template<input_range R1, input_range R2, weakly_incrementable O, copy_constructible F, class Proj1 = identity, class Proj2 = identity> @@ -160,27 +160,27 @@ namespace ranges { projected<iterator_t<R2>, Proj2>>> constexpr ranges::binary_transform_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>, O> transform(R1&& r1, R2&& r2, O result, - F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 + F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 template<input_iterator I, sentinel_for<I> S, class T, class Proj = identity> requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr iter_difference_t<I> - count(I first, S last, const T& value, Proj proj = {}); // since C++20 + count(I first, S last, const T& value, Proj proj = {}); // since C++20 template<input_range R, class T, class Proj = identity> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr range_difference_t<R> - count(R&& r, const T& value, Proj proj = {}); // since C++20 + count(R&& r, const T& value, Proj proj = {}); // since C++20 template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr iter_difference_t<I> - count_if(I first, S last, Pred pred, Proj proj = {}); // since C++20 + count_if(I first, S last, Pred pred, Proj proj = {}); // since C++20 template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr range_difference_t<R> - count_if(R&& r, Pred pred, Proj proj = {}); // since C++20 + count_if(R&& r, Pred pred, Proj proj = {}); // since C++20 template<class T> using minmax_result = min_max_result<T>; @@ -188,18 +188,18 @@ namespace ranges { template<class T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr ranges::minmax_result<const T&> - minmax(const T& a, const T& b, Comp comp = {}, Proj proj = {}); // since C++20 + minmax(const T& a, const T& b, Comp comp = {}, Proj proj = {}); // since C++20 template<copyable T, class Proj = identity, indirect_strict_weak_order<projected<const T*, Proj>> Comp = ranges::less> constexpr ranges::minmax_result<T> - minmax(initializer_list<T> r, Comp comp = {}, Proj proj = {}); // since C++20 + minmax(initializer_list<T> r, Comp comp = {}, Proj proj = {}); // since C++20 template<input_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*> constexpr ranges::minmax_result<range_value_t<R>> - minmax(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 + minmax(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 template<class I> using minmax_element_result = min_max_result<I>; @@ -207,18 +207,18 @@ namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> constexpr ranges::minmax_element_result<I> - minmax_element(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20 + minmax_element(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20 template<forward_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr ranges::minmax_element_result<borrowed_iterator_t<R>> - minmax_element(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 + minmax_element(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 template<class I, class O> - using copy_result = in_out_result<I, O>; // since C++20 + using copy_result = in_out_result<I, O>; // since C++20 template<class I, class O> - using copy_n_result = in_out_result<I, O>; // since C++20 + using copy_n_result = in_out_result<I, O>; // since C++20 template<class I, class O> using copy_if_result = in_out_result<I, O>; // since C++20 @@ -333,20 +333,20 @@ namespace ranges { template<random_access_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> - constexpr bool is_heap(I first, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + constexpr bool is_heap(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20 template<random_access_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> - constexpr bool is_heap(R&& r, Comp comp = {}, Proj proj = {}); // Since C++20 + constexpr bool is_heap(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 template<random_access_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> - constexpr I is_heap_until(I first, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + constexpr I is_heap_until(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20 template<random_access_range R, class Proj = identity, indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> - is_heap_until(R&& r, Comp comp = {}, Proj proj = {}); // Since C++20 + is_heap_until(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 template<bidirectional_iterator I, sentinel_for<I> S> requires permutable<I> @@ -399,15 +399,24 @@ namespace ranges { template<input_or_output_iterator O, sentinel_for<O> S, copy_constructible F> requires invocable<F&> && indirectly_writable<O, invoke_result_t<F&>> - constexpr O generate(O first, S last, F gen); // Since C++20 + constexpr O generate(O first, S last, F gen); // since C++20 + + template<class ExecutionPolicy, class ForwardIterator, class Generator> + void generate(ExecutionPolicy&& exec, + ForwardIterator first, ForwardIterator last, + Generator gen); // since C++17 template<class R, copy_constructible F> requires invocable<F&> && output_range<R, invoke_result_t<F&>> - constexpr borrowed_iterator_t<R> generate(R&& r, F gen); // Since C++20 + constexpr borrowed_iterator_t<R> generate(R&& r, F gen); // since C++20 template<input_or_output_iterator O, copy_constructible F> requires invocable<F&> && indirectly_writable<O, invoke_result_t<F&>> - constexpr O generate_n(O first, iter_difference_t<O> n, F gen); // Since C++20 + constexpr O generate_n(O first, iter_difference_t<O> n, F gen); // since C++20 + + template<class ExecutionPolicy, class ForwardIterator, class Size, class Generator> + ForwardIterator generate_n(ExecutionPolicy&& exec, + ForwardIterator first, Size n, Generator gen); // since C++17 template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> @@ -424,27 +433,39 @@ namespace ranges { template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> - constexpr bool ranges::all_of(I first, S last, Pred pred, Proj proj = {}); // since C++20 + constexpr bool ranges::all_of(I first, S last, Pred pred, Proj proj = {}); // since C++20 template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> - constexpr bool ranges::all_of(R&& r, Pred pred, Proj proj = {}); // since C++20 + constexpr bool ranges::all_of(R&& r, Pred pred, Proj proj = {}); // since C++20 template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> - constexpr bool ranges::any_of(I first, S last, Pred pred, Proj proj = {}); // since C++20 + constexpr bool ranges::any_of(I first, S last, Pred pred, Proj proj = {}); // since C++20 template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> - constexpr bool ranges::any_of(R&& r, Pred pred, Proj proj = {}); // since C++20 + constexpr bool ranges::any_of(R&& r, Pred pred, Proj proj = {}); // since C++20 template<input_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> - constexpr bool ranges::none_of(I first, S last, Pred pred, Proj proj = {}); // since C++20 + constexpr bool ranges::none_of(I first, S last, Pred pred, Proj proj = {}); // since C++20 template<input_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> - constexpr bool ranges::none_of(R&& r, Pred pred, Proj proj = {}); // since C++20 + constexpr bool ranges::none_of(R&& r, Pred pred, Proj proj = {}); // since C++20 + + template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2, + class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> + requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> + constexpr bool ranges::starts_with(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++23 + + template<input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity, + class Proj2 = identity> + requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> + constexpr bool ranges::starts_with(R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++23 template<input_iterator I1, sentinel_for<I1> S1, random_access_iterator I2, sentinel_for<I2> S2, @@ -453,7 +474,7 @@ namespace ranges { indirect_strict_weak_order<Comp, projected<I1, Proj1>, projected<I2, Proj2>> constexpr partial_sort_copy_result<I1, I2> partial_sort_copy(I1 first, S1 last, I2 result_first, S2 result_last, - Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 template<input_range R1, random_access_range R2, class Comp = ranges::less, class Proj1 = identity, class Proj2 = identity> @@ -463,7 +484,7 @@ namespace ranges { projected<iterator_t<R2>, Proj2>> constexpr partial_sort_copy_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>> partial_sort_copy(R1&& r, R2&& result_r, Comp comp = {}, - Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_strict_weak_order<projected<I, Proj>> Comp = ranges::less> @@ -486,64 +507,64 @@ namespace ranges { class Proj = identity> requires sortable<I, Comp, Proj> constexpr I - ranges::nth_element(I first, I nth, S last, Comp comp = {}, Proj proj = {}); // since C++20 + ranges::nth_element(I first, I nth, S last, Comp comp = {}, Proj proj = {}); // since C++20 template<random_access_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr borrowed_iterator_t<R> - ranges::nth_element(R&& r, iterator_t<R> nth, Comp comp = {}, Proj proj = {}); // since C++20 + ranges::nth_element(R&& r, iterator_t<R> nth, Comp comp = {}, Proj proj = {}); // since C++20 template<forward_iterator I, sentinel_for<I> S, class T, class Proj = identity, - indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> - constexpr I upper_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 + indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> // since C++20 + constexpr I upper_bound(I first, S last, const T& value, Comp comp = {}, Proj proj = {}); template<forward_range R, class T, class Proj = identity, indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> - upper_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 + upper_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 template<forward_iterator I, sentinel_for<I> S, class T, class Proj = identity, indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> constexpr I lower_bound(I first, S last, const T& value, Comp comp = {}, - Proj proj = {}); // since C++20 + Proj proj = {}); // since C++20 template<forward_range R, class T, class Proj = identity, indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr borrowed_iterator_t<R> - lower_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 + lower_bound(R&& r, const T& value, Comp comp = {}, Proj proj = {}); // since C++20 template<forward_iterator I, sentinel_for<I> S, class T, class Proj = identity, indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less> constexpr bool binary_search(I first, S last, const T& value, Comp comp = {}, - Proj proj = {}); // since C++20 + Proj proj = {}); // since C++20 template<forward_range R, class T, class Proj = identity, indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less> constexpr bool binary_search(R&& r, const T& value, Comp comp = {}, - Proj proj = {}); // since C++20 + Proj proj = {}); // since C++20 template<permutable I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> constexpr subrange<I> - partition(I first, S last, Pred pred, Proj proj = {}); // Since C++20 + partition(I first, S last, Pred pred, Proj proj = {}); // since C++20 template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> - partition(R&& r, Pred pred, Proj proj = {}); // Since C++20 + partition(R&& r, Pred pred, Proj proj = {}); // since C++20 template<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires permutable<I> - subrange<I> stable_partition(I first, S last, Pred pred, Proj proj = {}); // Since C++20 + subrange<I> stable_partition(I first, S last, Pred pred, Proj proj = {}); // since C++20 template<bidirectional_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires permutable<iterator_t<R>> - borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, Proj proj = {}); // Since C++20 + borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, Proj proj = {}); // since C++20 template<input_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> @@ -563,7 +584,7 @@ namespace ranges { template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_binary_predicate<projected<I, Proj>, projected<I, Proj>> Pred = ranges::equal_to> - constexpr I ranges::adjacent_find(I first, S last, Pred pred = {}, Proj proj = {}); // since C+20 + constexpr I ranges::adjacent_find(I first, S last, Pred pred = {}, Proj proj = {}); // since C++20 template<forward_range R, class Proj = identity, indirect_binary_predicate<projected<iterator_t<R>, Proj>, @@ -604,7 +625,7 @@ namespace ranges { projected<I2, Proj2>> Comp = ranges::less> constexpr bool ranges::lexicographical_compare(I1 first1, S1 last1, I2 first2, S2 last2, - Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 + Comp comp = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 template<input_range R1, input_range R2, class Proj1 = identity, class Proj2 = identity, @@ -612,7 +633,7 @@ namespace ranges { projected<iterator_t<R2>, Proj2>> Comp = ranges::less> constexpr bool ranges::lexicographical_compare(R1&& r1, R2&& r2, Comp comp = {}, - Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 + Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 template<bidirectional_iterator I1, sentinel_for<I1> S1, bidirectional_iterator I2> requires indirectly_movable<I1, I2> @@ -643,7 +664,7 @@ namespace ranges { requires indirectly_copyable<I, O1> && indirectly_copyable<I, O2> constexpr partition_copy_result<I, O1, O2> partition_copy(I first, S last, O1 out_true, O2 out_false, Pred pred, - Proj proj = {}); // Since C++20 + Proj proj = {}); // since C++20 template<input_range R, weakly_incrementable O1, weakly_incrementable O2, class Proj = identity, @@ -651,16 +672,16 @@ namespace ranges { requires indirectly_copyable<iterator_t<R>, O1> && indirectly_copyable<iterator_t<R>, O2> constexpr partition_copy_result<borrowed_iterator_t<R>, O1, O2> - partition_copy(R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {}); // Since C++20 + partition_copy(R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {}); // since C++20 template<forward_iterator I, sentinel_for<I> S, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> - constexpr I partition_point(I first, S last, Pred pred, Proj proj = {}); // Since C++20 + constexpr I partition_point(I first, S last, Pred pred, Proj proj = {}); // since C++20 template<forward_range R, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> constexpr borrowed_iterator_t<R> - partition_point(R&& r, Pred pred, Proj proj = {}); // Since C++20 + partition_point(R&& r, Pred pred, Proj proj = {}); // since C++20 template<class I1, class I2, class O> using merge_result = in_in_out_result<I1, I2, O>; // since C++20 @@ -755,7 +776,7 @@ namespace ranges { template<forward_range R> requires permutable<iterator_t<R>> - constexpr borrowed_subrange_t<R> rotate(R&& r, iterator_t<R> middle); // Since C++20 + constexpr borrowed_subrange_t<R> rotate(R&& r, iterator_t<R> middle); // since C++20 template <class _InIter, class _OutIter> using rotate_copy_result = in_out_result<_InIter, _OutIter>; // since C++20 @@ -774,23 +795,23 @@ namespace ranges { requires (forward_iterator<I> || random_access_iterator<O>) && indirectly_copyable<I, O> && uniform_random_bit_generator<remove_reference_t<Gen>> - O sample(I first, S last, O out, iter_difference_t<I> n, Gen&& g); // Since C++20 + O sample(I first, S last, O out, iter_difference_t<I> n, Gen&& g); // since C++20 template<input_range R, weakly_incrementable O, class Gen> requires (forward_range<R> || random_access_iterator<O>) && indirectly_copyable<iterator_t<R>, O> && uniform_random_bit_generator<remove_reference_t<Gen>> - O sample(R&& r, O out, range_difference_t<R> n, Gen&& g); // Since C++20 + O sample(R&& r, O out, range_difference_t<R> n, Gen&& g); // since C++20 template<random_access_iterator I, sentinel_for<I> S, class Gen> requires permutable<I> && uniform_random_bit_generator<remove_reference_t<Gen>> - I shuffle(I first, S last, Gen&& g); // Since C++20 + I shuffle(I first, S last, Gen&& g); // since C++20 template<random_access_range R, class Gen> requires permutable<iterator_t<R>> && uniform_random_bit_generator<remove_reference_t<Gen>> - borrowed_iterator_t<R> shuffle(R&& r, Gen&& g); // Since C++20 + borrowed_iterator_t<R> shuffle(R&& r, Gen&& g); // since C++20 template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Proj1 = identity, class Proj2 = identity, @@ -798,14 +819,14 @@ namespace ranges { projected<I2, Proj2>> Pred = ranges::equal_to> constexpr bool ranges::is_permutation(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, - Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 template<forward_range R1, forward_range R2, class Proj1 = identity, class Proj2 = identity, indirect_equivalence_relation<projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> Pred = ranges::equal_to> constexpr bool ranges::is_permutation(R1&& r1, R2&& r2, Pred pred = {}, - Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, @@ -904,35 +925,35 @@ namespace ranges { indirect_strict_weak_order<projected<I1, Proj1>, projected<I2, Proj2>> Comp = ranges::less> constexpr bool includes(I1 first1, S1 last1, I2 first2, S2 last2, Comp comp = {}, - Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 template<input_range R1, input_range R2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order<projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>> Comp = ranges::less> constexpr bool includes(R1&& r1, R2&& r2, Comp comp = {}, - Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + Proj1 proj1 = {}, Proj2 proj2 = {}); // since C++20 template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> - I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // since C++20 template<bidirectional_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> borrowed_iterator_t<R> inplace_merge(R&& r, iterator_t<R> middle, Comp comp = {}, - Proj proj = {}); // Since C++20 + Proj proj = {}); // since C++20 template<permutable I, sentinel_for<I> S, class Proj = identity, indirect_equivalence_relation<projected<I, Proj>> C = ranges::equal_to> - constexpr subrange<I> unique(I first, S last, C comp = {}, Proj proj = {}); // Since C++20 + constexpr subrange<I> unique(I first, S last, C comp = {}, Proj proj = {}); // since C++20 template<forward_range R, class Proj = identity, indirect_equivalence_relation<projected<iterator_t<R>, Proj>> C = ranges::equal_to> requires permutable<iterator_t<R>> constexpr borrowed_subrange_t<R> - unique(R&& r, C comp = {}, Proj proj = {}); // Since C++20 + unique(R&& r, C comp = {}, Proj proj = {}); // since C++20 template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity, indirect_equivalence_relation<projected<I, Proj>> C = ranges::equal_to> @@ -941,7 +962,7 @@ namespace ranges { (input_iterator<O> && same_as<iter_value_t<I>, iter_value_t<O>>) || indirectly_copyable_storable<I, O>) constexpr unique_copy_result<I, O> - unique_copy(I first, S last, O result, C comp = {}, Proj proj = {}); // Since C++20 + unique_copy(I first, S last, O result, C comp = {}, Proj proj = {}); // since C++20 template<input_range R, weakly_incrementable O, class Proj = identity, indirect_equivalence_relation<projected<iterator_t<R>, Proj>> C = ranges::equal_to> @@ -950,41 +971,41 @@ namespace ranges { (input_iterator<O> && same_as<range_value_t<R>, iter_value_t<O>>) || indirectly_copyable_storable<iterator_t<R>, O>) constexpr unique_copy_result<borrowed_iterator_t<R>, O> - unique_copy(R&& r, O result, C comp = {}, Proj proj = {}); // Since C++20 + unique_copy(R&& r, O result, C comp = {}, Proj proj = {}); // since C++20 template<class I, class O> - using remove_copy_result = in_out_result<I, O>; // Since C++20 + using remove_copy_result = in_out_result<I, O>; // since C++20 template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class T, class Proj = identity> indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> constexpr remove_copy_result<I, O> - remove_copy(I first, S last, O result, const T& value, Proj proj = {}); // Since C++20 + remove_copy(I first, S last, O result, const T& value, Proj proj = {}); // since C++20 template<input_range R, weakly_incrementable O, class T, class Proj = identity> requires indirectly_copyable<iterator_t<R>, O> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> constexpr remove_copy_result<borrowed_iterator_t<R>, O> - remove_copy(R&& r, O result, const T& value, Proj proj = {}); // Since C++20 + remove_copy(R&& r, O result, const T& value, Proj proj = {}); // since C++20 template<class I, class O> - using remove_copy_if_result = in_out_result<I, O>; // Since C++20 + using remove_copy_if_result = in_out_result<I, O>; // since C++20 template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_copyable<I, O> constexpr remove_copy_if_result<I, O> - remove_copy_if(I first, S last, O result, Pred pred, Proj proj = {}); // Since C++20 + remove_copy_if(I first, S last, O result, Pred pred, Proj proj = {}); // since C++20 template<input_range R, weakly_incrementable O, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O> constexpr remove_copy_if_result<borrowed_iterator_t<R>, O> - remove_copy_if(R&& r, O result, Pred pred, Proj proj = {}); // Since C++20 + remove_copy_if(R&& r, O result, Pred pred, Proj proj = {}); // since C++20 template<class I, class O> - using replace_copy_result = in_out_result<I, O>; // Since C++20 + using replace_copy_result = in_out_result<I, O>; // since C++20 template<input_iterator I, sentinel_for<I> S, class T1, class T2, output_iterator<const T2&> O, class Proj = identity> @@ -992,7 +1013,7 @@ namespace ranges { indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T1*> constexpr replace_copy_result<I, O> replace_copy(I first, S last, O result, const T1& old_value, const T2& new_value, - Proj proj = {}); // Since C++20 + Proj proj = {}); // since C++20 template<input_range R, class T1, class T2, output_iterator<const T2&> O, class Proj = identity> @@ -1001,54 +1022,54 @@ namespace ranges { projected<iterator_t<R>, Proj>, const T1*> constexpr replace_copy_result<borrowed_iterator_t<R>, O> replace_copy(R&& r, O result, const T1& old_value, const T2& new_value, - Proj proj = {}); // Since C++20 + Proj proj = {}); // since C++20 template<class I, class O> - using replace_copy_if_result = in_out_result<I, O>; // Since C++20 + using replace_copy_if_result = in_out_result<I, O>; // since C++20 template<input_iterator I, sentinel_for<I> S, class T, output_iterator<const T&> O, class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred> requires indirectly_copyable<I, O> constexpr replace_copy_if_result<I, O> replace_copy_if(I first, S last, O result, Pred pred, const T& new_value, - Proj proj = {}); // Since C++20 + Proj proj = {}); // since C++20 template<input_range R, class T, output_iterator<const T&> O, class Proj = identity, indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> requires indirectly_copyable<iterator_t<R>, O> constexpr replace_copy_if_result<borrowed_iterator_t<R>, O> replace_copy_if(R&& r, O result, Pred pred, const T& new_value, - Proj proj = {}); // Since C++20 + Proj proj = {}); // since C++20 template<class I> - using prev_permutation_result = in_found_result<I>; // Since C++20 + using prev_permutation_result = in_found_result<I>; // since C++20 template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr ranges::prev_permutation_result<I> - ranges::prev_permutation(I first, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + ranges::prev_permutation(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20 template<bidirectional_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr ranges::prev_permutation_result<borrowed_iterator_t<R>> - ranges::prev_permutation(R&& r, Comp comp = {}, Proj proj = {}); // Since C++20 + ranges::prev_permutation(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 template<class I> - using next_permutation_result = in_found_result<I>; // Since C++20 + using next_permutation_result = in_found_result<I>; // since C++20 template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less, class Proj = identity> requires sortable<I, Comp, Proj> constexpr ranges::next_permutation_result<I> - ranges::next_permutation(I first, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + ranges::next_permutation(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20 template<bidirectional_range R, class Comp = ranges::less, class Proj = identity> requires sortable<iterator_t<R>, Comp, Proj> constexpr ranges::next_permutation_result<borrowed_iterator_t<R>> - ranges::next_permutation(R&& r, Comp comp = {}, Proj proj = {}); // Since C++20 + ranges::next_permutation(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 } @@ -1684,6 +1705,18 @@ template <class InputIterator1, class InputIterator2, class Compare> lexicographical_compare(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp); +template<class InputIterator1, class InputIterator2, class Cmp> + constexpr auto + lexicographical_compare_three_way(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Cmp comp) + -> decltype(comp(*b1, *b2)); // since C++20 + +template<class InputIterator1, class InputIterator2> + constexpr auto + lexicographical_compare_three_way(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2); // since C++20 + template <class BidirectionalIterator> constexpr bool // constexpr in C++20 next_permutation(BidirectionalIterator first, BidirectionalIterator last); @@ -1705,9 +1738,7 @@ template <class BidirectionalIterator, class Compare> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include <__debug> #include <cstddef> -#include <type_traits> #include <version> #include <__algorithm/adjacent_find.h> @@ -1753,6 +1784,7 @@ template <class BidirectionalIterator, class Compare> #include <__algorithm/is_sorted_until.h> #include <__algorithm/iter_swap.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/lower_bound.h> #include <__algorithm/make_heap.h> #include <__algorithm/max.h> @@ -1776,6 +1808,19 @@ template <class BidirectionalIterator, class Compare> #include <__algorithm/partition_point.h> #include <__algorithm/pop_heap.h> #include <__algorithm/prev_permutation.h> +#include <__algorithm/pstl_any_all_none_of.h> +#include <__algorithm/pstl_copy.h> +#include <__algorithm/pstl_count.h> +#include <__algorithm/pstl_fill.h> +#include <__algorithm/pstl_find.h> +#include <__algorithm/pstl_for_each.h> +#include <__algorithm/pstl_generate.h> +#include <__algorithm/pstl_is_partitioned.h> +#include <__algorithm/pstl_merge.h> +#include <__algorithm/pstl_replace.h> +#include <__algorithm/pstl_sort.h> +#include <__algorithm/pstl_stable_sort.h> +#include <__algorithm/pstl_transform.h> #include <__algorithm/push_heap.h> #include <__algorithm/ranges_adjacent_find.h> #include <__algorithm/ranges_all_of.h> @@ -1857,6 +1902,7 @@ template <class BidirectionalIterator, class Compare> #include <__algorithm/ranges_sort_heap.h> #include <__algorithm/ranges_stable_partition.h> #include <__algorithm/ranges_stable_sort.h> +#include <__algorithm/ranges_starts_with.h> #include <__algorithm/ranges_swap_ranges.h> #include <__algorithm/ranges_transform.h> #include <__algorithm/ranges_unique.h> @@ -1905,21 +1951,16 @@ template <class BidirectionalIterator, class Compare> # pragma GCC system_header #endif -#if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17 -# include <__pstl_algorithm> -#endif - -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17 -# include <chrono> -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <atomic> +# include <bit> # include <concepts> +# include <cstdlib> # include <cstring> # include <iterator> # include <memory> # include <stdexcept> +# include <type_traits> # include <utility> #endif diff --git a/libcxx/include/any b/libcxx/include/any index 92cbc9a6c92d..b3ac5871c42f 100644 --- a/libcxx/include/any +++ b/libcxx/include/any @@ -87,13 +87,27 @@ namespace std { #include <__memory/allocator_destructor.h> #include <__memory/allocator_traits.h> #include <__memory/unique_ptr.h> +#include <__type_traits/add_const.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/aligned_storage.h> +#include <__type_traits/alignment_of.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_function.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> #include <__utility/unreachable.h> -#include <cstdlib> +#include <__verbose_abort> #include <initializer_list> -#include <type_traits> #include <typeinfo> #include <version> @@ -101,8 +115,11 @@ namespace std { # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + namespace std { -class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast { public: const char* what() const _NOEXCEPT override; @@ -111,16 +128,16 @@ public: _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST void __throw_bad_any_cast() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_any_cast(); #else - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("bad_any_cast was thrown in -fno-exceptions mode"); #endif } @@ -175,7 +192,7 @@ namespace __any_imp inline _LIBCPP_INLINE_VISIBILITY bool __compare_typeid(type_info const* __id, const void* __fallback_id) { -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) if (__id && *__id == typeid(_Tp)) return true; #endif @@ -294,7 +311,7 @@ public: _LIBCPP_INLINE_VISIBILITY bool has_value() const _NOEXCEPT { return __h_ != nullptr; } -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) _LIBCPP_INLINE_VISIBILITY const type_info & type() const _NOEXCEPT { if (__h_) { @@ -311,7 +328,7 @@ private: const void* __fallback_info); union _Storage { - constexpr _Storage() : __ptr(nullptr) {} + _LIBCPP_HIDE_FROM_ABI constexpr _Storage() : __ptr(nullptr) {} void * __ptr; __any_imp::_Buffer __buf; }; @@ -426,7 +443,7 @@ namespace __any_imp _LIBCPP_INLINE_VISIBILITY static void* __type_info() { -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); #else return nullptr; @@ -514,7 +531,7 @@ namespace __any_imp _LIBCPP_INLINE_VISIBILITY static void* __type_info() { -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) return const_cast<void*>(static_cast<void const *>(&typeid(_Tp))); #else return nullptr; @@ -680,7 +697,7 @@ any_cast(any * __any) _NOEXCEPT typedef add_pointer_t<_ValueType> _ReturnType; if (__any && __any->__h_) { void *__p = __any->__call(_Action::_Get, nullptr, -#if !defined(_LIBCPP_NO_RTTI) +#if !defined(_LIBCPP_HAS_NO_RTTI) &typeid(_ValueType), #else nullptr, @@ -692,10 +709,12 @@ any_cast(any * __any) _NOEXCEPT return nullptr; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17 # include <chrono> #endif @@ -703,9 +722,12 @@ _LIBCPP_END_NAMESPACE_STD #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <atomic> # include <concepts> +# include <cstdlib> # include <iosfwd> # include <iterator> # include <memory> +# include <stdexcept> +# include <type_traits> # include <variant> #endif diff --git a/libcxx/include/array b/libcxx/include/array index 068a6bd4cc42..3fc25d4c3062 100644 --- a/libcxx/include/array +++ b/libcxx/include/array @@ -77,15 +77,18 @@ template <class T, class... U> template <class T, size_t N> bool operator==(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 template <class T, size_t N> - bool operator!=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 + bool operator!=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 template <class T, size_t N> - bool operator<(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 + bool operator<(const array<T,N>& x, const array<T,N>& y); // removed in C++20 template <class T, size_t N> - bool operator>(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 + bool operator>(const array<T,N>& x, const array<T,N>& y); // removed in C++20 template <class T, size_t N> - bool operator<=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 + bool operator<=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 template <class T, size_t N> - bool operator>=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 + bool operator>=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 +template<class T, size_t N> + constexpr synth-three-way-result<T> + operator<=>(const array<T, N>& x, const array<T, N>& y); // since C++20 template <class T, size_t N > void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); // constexpr in C++20 @@ -111,16 +114,27 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce #include <__algorithm/equal.h> #include <__algorithm/fill_n.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/swap_ranges.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__fwd/array.h> #include <__iterator/reverse_iterator.h> -#include <__tuple_dir/sfinae_helpers.h> +#include <__tuple/sfinae_helpers.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/remove_cv.h> #include <__utility/integer_sequence.h> #include <__utility/move.h> #include <__utility/unreachable.h> #include <stdexcept> -#include <type_traits> #include <version> // standard-mandated includes @@ -137,8 +151,8 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce #include <initializer_list> // [tuple.helper] -#include <__tuple_dir/tuple_element.h> -#include <__tuple_dir/tuple_size.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_size.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -215,23 +229,23 @@ struct _LIBCPP_TEMPLATE_VIS array // element access: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator[](size_type __n) _NOEXCEPT { - _LIBCPP_ASSERT(__n < _Size, "out-of-bounds access in std::array<T, N>"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < _Size, "out-of-bounds access in std::array<T, N>"); return __elems_[__n]; } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference operator[](size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n < _Size, "out-of-bounds access in std::array<T, N>"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < _Size, "out-of-bounds access in std::array<T, N>"); return __elems_[__n]; } - _LIBCPP_CONSTEXPR_SINCE_CXX17 reference at(size_type __n) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference at(size_type __n) { if (__n >= _Size) __throw_out_of_range("array::at"); return __elems_[__n]; } - _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference at(size_type __n) const + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference at(size_type __n) const { if (__n >= _Size) __throw_out_of_range("array::at"); @@ -328,13 +342,13 @@ struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0> // element access: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator[](size_type) _NOEXCEPT { - _LIBCPP_ASSERT(false, "cannot call array<T, 0>::operator[] on a zero-sized array"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::operator[] on a zero-sized array"); __libcpp_unreachable(); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference operator[](size_type) const _NOEXCEPT { - _LIBCPP_ASSERT(false, "cannot call array<T, 0>::operator[] on a zero-sized array"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::operator[] on a zero-sized array"); __libcpp_unreachable(); } @@ -352,31 +366,31 @@ struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reference front() _NOEXCEPT { - _LIBCPP_ASSERT(false, "cannot call array<T, 0>::front() on a zero-sized array"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::front() on a zero-sized array"); __libcpp_unreachable(); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference front() const _NOEXCEPT { - _LIBCPP_ASSERT(false, "cannot call array<T, 0>::front() on a zero-sized array"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::front() on a zero-sized array"); __libcpp_unreachable(); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX17 reference back() _NOEXCEPT { - _LIBCPP_ASSERT(false, "cannot call array<T, 0>::back() on a zero-sized array"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::back() on a zero-sized array"); __libcpp_unreachable(); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference back() const _NOEXCEPT { - _LIBCPP_ASSERT(false, "cannot call array<T, 0>::back() on a zero-sized array"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::back() on a zero-sized array"); __libcpp_unreachable(); } }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template<class _Tp, class... _Args, class = enable_if_t<__all<_IsSame<_Tp, _Args>::value...>::value> > @@ -392,47 +406,44 @@ operator==(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) return _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template <class _Tp, size_t _Size> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return !(__x == __y); } template <class _Tp, size_t _Size> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) -{ - return _VSTD::lexicographical_compare(__x.begin(), __x.end(), - __y.begin(), __y.end()); +inline _LIBCPP_HIDE_FROM_ABI bool operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { + return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); } template <class _Tp, size_t _Size> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI bool operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return __y < __x; } template <class _Tp, size_t _Size> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return !(__y < __x); } template <class _Tp, size_t _Size> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return !(__x < __y); } +#else // _LIBCPP_STD_VER <= 17 + +template <class _Tp, size_t _Size> +_LIBCPP_HIDE_FROM_ABI constexpr __synth_three_way_result<_Tp> +operator<=>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>); +} + +#endif // _LIBCPP_STD_VER <= 17 + template <class _Tp, size_t _Size> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<_Size == 0 || __is_swappable<_Tp>::value, void> @@ -489,7 +500,7 @@ get(const array<_Tp, _Size>&& __a) _NOEXCEPT return _VSTD::move(__a.__elems_[_Ip]); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <typename _Tp, size_t _Size, size_t... _Index> _LIBCPP_INLINE_VISIBILITY constexpr array<remove_cv_t<_Tp>, _Size> @@ -528,14 +539,16 @@ to_array(_Tp(&&__arr)[_Size]) noexcept(is_nothrow_move_constructible_v<_Tp>) { make_index_sequence<_Size>()); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <algorithm> # include <concepts> +# include <cstdlib> # include <iterator> +# include <type_traits> # include <utility> #endif diff --git a/libcxx/include/atomic b/libcxx/include/atomic index d0d682da6238..2f122a707bdc 100644 --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -519,2154 +519,39 @@ template <class T> */ #include <__assert> // all public C++ headers provide the assertion handler -#include <__availability> -#include <__chrono/duration.h> +#include <__atomic/aliases.h> +#include <__atomic/atomic.h> +#include <__atomic/atomic_base.h> +#include <__atomic/atomic_flag.h> +#include <__atomic/atomic_init.h> +#include <__atomic/atomic_lock_free.h> +#include <__atomic/atomic_sync.h> +#include <__atomic/check_memory_order.h> +#include <__atomic/contention_t.h> +#include <__atomic/cxx_atomic_impl.h> +#include <__atomic/fence.h> +#include <__atomic/is_always_lock_free.h> +#include <__atomic/kill_dependency.h> +#include <__atomic/memory_order.h> #include <__config> -#include <__thread/poll_with_backoff.h> -#include <__thread/timed_backoff_policy.h> -#include <__type_traits/conditional.h> -#include <__type_traits/decay.h> -#include <__type_traits/is_assignable.h> -#include <__type_traits/is_function.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__type_traits/is_same.h> -#include <__type_traits/is_trivially_copyable.h> -#include <__type_traits/remove_const.h> -#include <__type_traits/remove_pointer.h> -#include <__type_traits/underlying_type.h> -#include <cstddef> -#include <cstdint> -#include <cstring> #include <version> -#ifndef _LIBCPP_HAS_NO_THREADS -# include <__threading_support> -#endif - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif #ifdef _LIBCPP_HAS_NO_ATOMIC_HEADER -# error <atomic> is not implemented -#endif -#ifdef kill_dependency -# error <atomic> is incompatible with <stdatomic.h> before C++23. Please compile with -std=c++23. +# error <atomic> is not implemented #endif -#define _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) \ - _LIBCPP_DIAGNOSE_WARNING(__m == memory_order_consume || \ - __m == memory_order_acquire || \ - __m == memory_order_acq_rel, \ - "memory order argument to atomic operation is invalid") - -#define _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) \ - _LIBCPP_DIAGNOSE_WARNING(__m == memory_order_release || \ - __m == memory_order_acq_rel, \ - "memory order argument to atomic operation is invalid") - -#define _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__m, __f) \ - _LIBCPP_DIAGNOSE_WARNING(__f == memory_order_release || \ - __f == memory_order_acq_rel, \ - "memory order argument to atomic operation is invalid") - -_LIBCPP_BEGIN_NAMESPACE_STD - -// Figure out what the underlying type for `memory_order` would be if it were -// declared as an unscoped enum (accounting for -fshort-enums). Use this result -// to pin the underlying type in C++20. -enum __legacy_memory_order { - __mo_relaxed, - __mo_consume, - __mo_acquire, - __mo_release, - __mo_acq_rel, - __mo_seq_cst -}; - -typedef underlying_type<__legacy_memory_order>::type __memory_order_underlying_t; - -#if _LIBCPP_STD_VER > 17 - -enum class memory_order : __memory_order_underlying_t { - relaxed = __mo_relaxed, - consume = __mo_consume, - acquire = __mo_acquire, - release = __mo_release, - acq_rel = __mo_acq_rel, - seq_cst = __mo_seq_cst -}; - -inline constexpr auto memory_order_relaxed = memory_order::relaxed; -inline constexpr auto memory_order_consume = memory_order::consume; -inline constexpr auto memory_order_acquire = memory_order::acquire; -inline constexpr auto memory_order_release = memory_order::release; -inline constexpr auto memory_order_acq_rel = memory_order::acq_rel; -inline constexpr auto memory_order_seq_cst = memory_order::seq_cst; - -#else - -typedef enum memory_order { - memory_order_relaxed = __mo_relaxed, - memory_order_consume = __mo_consume, - memory_order_acquire = __mo_acquire, - memory_order_release = __mo_release, - memory_order_acq_rel = __mo_acq_rel, - memory_order_seq_cst = __mo_seq_cst, -} memory_order; - -#endif // _LIBCPP_STD_VER > 17 - -template <typename _Tp> _LIBCPP_INLINE_VISIBILITY -bool __cxx_nonatomic_compare_equal(_Tp const& __lhs, _Tp const& __rhs) { - return _VSTD::memcmp(&__lhs, &__rhs, sizeof(_Tp)) == 0; -} - -static_assert((is_same<underlying_type<memory_order>::type, __memory_order_underlying_t>::value), - "unexpected underlying type for std::memory_order"); - -#if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) || \ - defined(_LIBCPP_ATOMIC_ONLY_USE_BUILTINS) - -// [atomics.types.generic]p1 guarantees _Tp is trivially copyable. Because -// the default operator= in an object is not volatile, a byte-by-byte copy -// is required. -template <typename _Tp, typename _Tv> _LIBCPP_INLINE_VISIBILITY -typename enable_if<is_assignable<_Tp&, _Tv>::value>::type -__cxx_atomic_assign_volatile(_Tp& __a_value, _Tv const& __val) { - __a_value = __val; -} -template <typename _Tp, typename _Tv> _LIBCPP_INLINE_VISIBILITY -typename enable_if<is_assignable<_Tp&, _Tv>::value>::type -__cxx_atomic_assign_volatile(_Tp volatile& __a_value, _Tv volatile const& __val) { - volatile char* __to = reinterpret_cast<volatile char*>(&__a_value); - volatile char* __end = __to + sizeof(_Tp); - volatile const char* __from = reinterpret_cast<volatile const char*>(&__val); - while (__to != __end) - *__to++ = *__from++; -} - -#endif - -#if defined(_LIBCPP_HAS_GCC_ATOMIC_IMP) - -template <typename _Tp> -struct __cxx_atomic_base_impl { - - _LIBCPP_INLINE_VISIBILITY -#ifndef _LIBCPP_CXX03_LANG - __cxx_atomic_base_impl() _NOEXCEPT = default; -#else - __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {} -#endif // _LIBCPP_CXX03_LANG - _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp value) _NOEXCEPT - : __a_value(value) {} - _Tp __a_value; -}; - -_LIBCPP_INLINE_VISIBILITY inline _LIBCPP_CONSTEXPR int __to_gcc_order(memory_order __order) { - // Avoid switch statement to make this a constexpr. - return __order == memory_order_relaxed ? __ATOMIC_RELAXED: - (__order == memory_order_acquire ? __ATOMIC_ACQUIRE: - (__order == memory_order_release ? __ATOMIC_RELEASE: - (__order == memory_order_seq_cst ? __ATOMIC_SEQ_CST: - (__order == memory_order_acq_rel ? __ATOMIC_ACQ_REL: - __ATOMIC_CONSUME)))); -} - -_LIBCPP_INLINE_VISIBILITY inline _LIBCPP_CONSTEXPR int __to_gcc_failure_order(memory_order __order) { - // Avoid switch statement to make this a constexpr. - return __order == memory_order_relaxed ? __ATOMIC_RELAXED: - (__order == memory_order_acquire ? __ATOMIC_ACQUIRE: - (__order == memory_order_release ? __ATOMIC_RELAXED: - (__order == memory_order_seq_cst ? __ATOMIC_SEQ_CST: - (__order == memory_order_acq_rel ? __ATOMIC_ACQUIRE: - __ATOMIC_CONSUME)))); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_init(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { - __cxx_atomic_assign_volatile(__a->__a_value, __val); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val) { - __a->__a_value = __val; -} - -_LIBCPP_INLINE_VISIBILITY inline -void __cxx_atomic_thread_fence(memory_order __order) { - __atomic_thread_fence(__to_gcc_order(__order)); -} - -_LIBCPP_INLINE_VISIBILITY inline -void __cxx_atomic_signal_fence(memory_order __order) { - __atomic_signal_fence(__to_gcc_order(__order)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_store(volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp __val, - memory_order __order) { - __atomic_store(&__a->__a_value, &__val, - __to_gcc_order(__order)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp>* __a, _Tp __val, - memory_order __order) { - __atomic_store(&__a->__a_value, &__val, - __to_gcc_order(__order)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_load(const volatile __cxx_atomic_base_impl<_Tp>* __a, - memory_order __order) { - _Tp __ret; - __atomic_load(&__a->__a_value, &__ret, - __to_gcc_order(__order)); - return __ret; -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_load(const __cxx_atomic_base_impl<_Tp>* __a, memory_order __order) { - _Tp __ret; - __atomic_load(&__a->__a_value, &__ret, - __to_gcc_order(__order)); - return __ret; -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_exchange(volatile __cxx_atomic_base_impl<_Tp>* __a, - _Tp __value, memory_order __order) { - _Tp __ret; - __atomic_exchange(&__a->__a_value, &__value, &__ret, - __to_gcc_order(__order)); - return __ret; -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp>* __a, _Tp __value, - memory_order __order) { - _Tp __ret; - __atomic_exchange(&__a->__a_value, &__value, &__ret, - __to_gcc_order(__order)); - return __ret; -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_strong( - volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, - memory_order __success, memory_order __failure) { - return __atomic_compare_exchange(&__a->__a_value, __expected, &__value, - false, - __to_gcc_order(__success), - __to_gcc_failure_order(__failure)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_strong( - __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, - memory_order __failure) { - return __atomic_compare_exchange(&__a->__a_value, __expected, &__value, - false, - __to_gcc_order(__success), - __to_gcc_failure_order(__failure)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_weak( - volatile __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, - memory_order __success, memory_order __failure) { - return __atomic_compare_exchange(&__a->__a_value, __expected, &__value, - true, - __to_gcc_order(__success), - __to_gcc_failure_order(__failure)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_weak( - __cxx_atomic_base_impl<_Tp>* __a, _Tp* __expected, _Tp __value, memory_order __success, - memory_order __failure) { - return __atomic_compare_exchange(&__a->__a_value, __expected, &__value, - true, - __to_gcc_order(__success), - __to_gcc_failure_order(__failure)); -} - -template <typename _Tp> -struct __skip_amt { enum {value = 1}; }; - -template <typename _Tp> -struct __skip_amt<_Tp*> { enum {value = sizeof(_Tp)}; }; - -// FIXME: Haven't figured out what the spec says about using arrays with -// atomic_fetch_add. Force a failure rather than creating bad behavior. -template <typename _Tp> -struct __skip_amt<_Tp[]> { }; -template <typename _Tp, int n> -struct __skip_amt<_Tp[n]> { }; - -template <typename _Tp, typename _Td> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_add(volatile __cxx_atomic_base_impl<_Tp>* __a, - _Td __delta, memory_order __order) { - return __atomic_fetch_add(&__a->__a_value, __delta * __skip_amt<_Tp>::value, - __to_gcc_order(__order)); -} - -template <typename _Tp, typename _Td> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, - memory_order __order) { - return __atomic_fetch_add(&__a->__a_value, __delta * __skip_amt<_Tp>::value, - __to_gcc_order(__order)); -} - -template <typename _Tp, typename _Td> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_sub(volatile __cxx_atomic_base_impl<_Tp>* __a, - _Td __delta, memory_order __order) { - return __atomic_fetch_sub(&__a->__a_value, __delta * __skip_amt<_Tp>::value, - __to_gcc_order(__order)); -} - -template <typename _Tp, typename _Td> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp>* __a, _Td __delta, - memory_order __order) { - return __atomic_fetch_sub(&__a->__a_value, __delta * __skip_amt<_Tp>::value, - __to_gcc_order(__order)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_and(volatile __cxx_atomic_base_impl<_Tp>* __a, - _Tp __pattern, memory_order __order) { - return __atomic_fetch_and(&__a->__a_value, __pattern, - __to_gcc_order(__order)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp>* __a, - _Tp __pattern, memory_order __order) { - return __atomic_fetch_and(&__a->__a_value, __pattern, - __to_gcc_order(__order)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_or(volatile __cxx_atomic_base_impl<_Tp>* __a, - _Tp __pattern, memory_order __order) { - return __atomic_fetch_or(&__a->__a_value, __pattern, - __to_gcc_order(__order)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, - memory_order __order) { - return __atomic_fetch_or(&__a->__a_value, __pattern, - __to_gcc_order(__order)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_xor(volatile __cxx_atomic_base_impl<_Tp>* __a, - _Tp __pattern, memory_order __order) { - return __atomic_fetch_xor(&__a->__a_value, __pattern, - __to_gcc_order(__order)); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp>* __a, _Tp __pattern, - memory_order __order) { - return __atomic_fetch_xor(&__a->__a_value, __pattern, - __to_gcc_order(__order)); -} - -#define __cxx_atomic_is_lock_free(__s) __atomic_is_lock_free(__s, 0) - -#elif defined(_LIBCPP_HAS_C_ATOMIC_IMP) - -template <typename _Tp> -struct __cxx_atomic_base_impl { - - _LIBCPP_INLINE_VISIBILITY -#ifndef _LIBCPP_CXX03_LANG - __cxx_atomic_base_impl() _NOEXCEPT = default; -#else - __cxx_atomic_base_impl() _NOEXCEPT : __a_value() {} -#endif // _LIBCPP_CXX03_LANG - _LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp __value) _NOEXCEPT - : __a_value(__value) {} - _LIBCPP_DISABLE_EXTENSION_WARNING _Atomic(_Tp) __a_value; -}; - -#define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s) - -_LIBCPP_INLINE_VISIBILITY inline -void __cxx_atomic_thread_fence(memory_order __order) _NOEXCEPT { - __c11_atomic_thread_fence(static_cast<__memory_order_underlying_t>(__order)); -} - -_LIBCPP_INLINE_VISIBILITY inline -void __cxx_atomic_signal_fence(memory_order __order) _NOEXCEPT { - __c11_atomic_signal_fence(static_cast<__memory_order_underlying_t>(__order)); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val) _NOEXCEPT { - __c11_atomic_init(&__a->__a_value, __val); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_init(__cxx_atomic_base_impl<_Tp> * __a, _Tp __val) _NOEXCEPT { - __c11_atomic_init(&__a->__a_value, __val); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __val, memory_order __order) _NOEXCEPT { - __c11_atomic_store(&__a->__a_value, __val, static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_store(__cxx_atomic_base_impl<_Tp> * __a, _Tp __val, memory_order __order) _NOEXCEPT { - __c11_atomic_store(&__a->__a_value, __val, static_cast<__memory_order_underlying_t>(__order)); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const volatile* __a, memory_order __order) _NOEXCEPT { - using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; - return __c11_atomic_load(const_cast<__ptr_type>(&__a->__a_value), static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_load(__cxx_atomic_base_impl<_Tp> const* __a, memory_order __order) _NOEXCEPT { - using __ptr_type = __remove_const_t<decltype(__a->__a_value)>*; - return __c11_atomic_load(const_cast<__ptr_type>(&__a->__a_value), static_cast<__memory_order_underlying_t>(__order)); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __value, memory_order __order) _NOEXCEPT { - return __c11_atomic_exchange(&__a->__a_value, __value, static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_exchange(__cxx_atomic_base_impl<_Tp> * __a, _Tp __value, memory_order __order) _NOEXCEPT { - return __c11_atomic_exchange(&__a->__a_value, __value, static_cast<__memory_order_underlying_t>(__order)); -} - -_LIBCPP_INLINE_VISIBILITY inline _LIBCPP_CONSTEXPR memory_order __to_failure_order(memory_order __order) { - // Avoid switch statement to make this a constexpr. - return __order == memory_order_release ? memory_order_relaxed: - (__order == memory_order_acq_rel ? memory_order_acquire: - __order); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { - return __c11_atomic_compare_exchange_strong(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_base_impl<_Tp> * __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { - return __c11_atomic_compare_exchange_strong(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { - return __c11_atomic_compare_exchange_weak(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_base_impl<_Tp> * __a, _Tp* __expected, _Tp __value, memory_order __success, memory_order __failure) _NOEXCEPT { - return __c11_atomic_compare_exchange_weak(&__a->__a_value, __expected, __value, static_cast<__memory_order_underlying_t>(__success), static_cast<__memory_order_underlying_t>(__to_failure_order(__failure))); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp> * __a, _Tp __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp* __cxx_atomic_fetch_add(__cxx_atomic_base_impl<_Tp*> * __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_add(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp> * __a, _Tp __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> volatile* __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp* __cxx_atomic_fetch_sub(__cxx_atomic_base_impl<_Tp*> * __a, ptrdiff_t __delta, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_sub(&__a->__a_value, __delta, static_cast<__memory_order_underlying_t>(__order)); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_and(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_and(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_and(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_or(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_or(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_or(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); -} - -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> volatile* __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_xor(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); -} -template<class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_xor(__cxx_atomic_base_impl<_Tp> * __a, _Tp __pattern, memory_order __order) _NOEXCEPT { - return __c11_atomic_fetch_xor(&__a->__a_value, __pattern, static_cast<__memory_order_underlying_t>(__order)); -} - -#endif // _LIBCPP_HAS_GCC_ATOMIC_IMP, _LIBCPP_HAS_C_ATOMIC_IMP - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp kill_dependency(_Tp __y) _NOEXCEPT -{ - return __y; -} - -#if defined(__CLANG_ATOMIC_BOOL_LOCK_FREE) -# define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE -# define ATOMIC_CHAR_LOCK_FREE __CLANG_ATOMIC_CHAR_LOCK_FREE -#ifndef _LIBCPP_HAS_NO_CHAR8_T -# define ATOMIC_CHAR8_T_LOCK_FREE __CLANG_ATOMIC_CHAR8_T_LOCK_FREE -#endif -# define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE -# define ATOMIC_CHAR32_T_LOCK_FREE __CLANG_ATOMIC_CHAR32_T_LOCK_FREE -# define ATOMIC_WCHAR_T_LOCK_FREE __CLANG_ATOMIC_WCHAR_T_LOCK_FREE -# define ATOMIC_SHORT_LOCK_FREE __CLANG_ATOMIC_SHORT_LOCK_FREE -# define ATOMIC_INT_LOCK_FREE __CLANG_ATOMIC_INT_LOCK_FREE -# define ATOMIC_LONG_LOCK_FREE __CLANG_ATOMIC_LONG_LOCK_FREE -# define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE -# define ATOMIC_POINTER_LOCK_FREE __CLANG_ATOMIC_POINTER_LOCK_FREE -#elif defined(__GCC_ATOMIC_BOOL_LOCK_FREE) -# define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE -# define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE -#ifndef _LIBCPP_HAS_NO_CHAR8_T -# define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE -#endif -# define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE -# define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE -# define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE -# define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE -# define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE -# define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE -# define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE -# define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE -#endif - -template <class _Tp> -struct __libcpp_is_always_lock_free { - // __atomic_always_lock_free is available in all Standard modes - static const bool __value = __atomic_always_lock_free(sizeof(_Tp), 0); -}; - -#ifdef _LIBCPP_ATOMIC_ONLY_USE_BUILTINS - -template<typename _Tp> -struct __cxx_atomic_lock_impl { - - _LIBCPP_INLINE_VISIBILITY - __cxx_atomic_lock_impl() _NOEXCEPT - : __a_value(), __a_lock(0) {} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR explicit - __cxx_atomic_lock_impl(_Tp value) _NOEXCEPT - : __a_value(value), __a_lock(0) {} - - _Tp __a_value; - mutable __cxx_atomic_base_impl<_LIBCPP_ATOMIC_FLAG_TYPE> __a_lock; - - _LIBCPP_INLINE_VISIBILITY void __lock() const volatile { - while(1 == __cxx_atomic_exchange(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(true), memory_order_acquire)) - /*spin*/; - } - _LIBCPP_INLINE_VISIBILITY void __lock() const { - while(1 == __cxx_atomic_exchange(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(true), memory_order_acquire)) - /*spin*/; - } - _LIBCPP_INLINE_VISIBILITY void __unlock() const volatile { - __cxx_atomic_store(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(false), memory_order_release); - } - _LIBCPP_INLINE_VISIBILITY void __unlock() const { - __cxx_atomic_store(&__a_lock, _LIBCPP_ATOMIC_FLAG_TYPE(false), memory_order_release); - } - _LIBCPP_INLINE_VISIBILITY _Tp __read() const volatile { - __lock(); - _Tp __old; - __cxx_atomic_assign_volatile(__old, __a_value); - __unlock(); - return __old; - } - _LIBCPP_INLINE_VISIBILITY _Tp __read() const { - __lock(); - _Tp __old = __a_value; - __unlock(); - return __old; - } -}; - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_init(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __val) { - __cxx_atomic_assign_volatile(__a->__a_value, __val); -} -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_init(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __val) { - __a->__a_value = __val; -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_store(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __val, memory_order) { - __a->__lock(); - __cxx_atomic_assign_volatile(__a->__a_value, __val); - __a->__unlock(); -} -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -void __cxx_atomic_store(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __val, memory_order) { - __a->__lock(); - __a->__a_value = __val; - __a->__unlock(); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_load(const volatile __cxx_atomic_lock_impl<_Tp>* __a, memory_order) { - return __a->__read(); -} -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_load(const __cxx_atomic_lock_impl<_Tp>* __a, memory_order) { - return __a->__read(); -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_exchange(volatile __cxx_atomic_lock_impl<_Tp>* __a, _Tp __value, memory_order) { - __a->__lock(); - _Tp __old; - __cxx_atomic_assign_volatile(__old, __a->__a_value); - __cxx_atomic_assign_volatile(__a->__a_value, __value); - __a->__unlock(); - return __old; -} -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_exchange(__cxx_atomic_lock_impl<_Tp>* __a, _Tp __value, memory_order) { - __a->__lock(); - _Tp __old = __a->__a_value; - __a->__a_value = __value; - __a->__unlock(); - return __old; -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_strong(volatile __cxx_atomic_lock_impl<_Tp>* __a, - _Tp* __expected, _Tp __value, memory_order, memory_order) { - _Tp __temp; - __a->__lock(); - __cxx_atomic_assign_volatile(__temp, __a->__a_value); - bool __ret = (_VSTD::memcmp(&__temp, __expected, sizeof(_Tp)) == 0); - if(__ret) - __cxx_atomic_assign_volatile(__a->__a_value, __value); - else - __cxx_atomic_assign_volatile(*__expected, __a->__a_value); - __a->__unlock(); - return __ret; -} -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_strong(__cxx_atomic_lock_impl<_Tp>* __a, - _Tp* __expected, _Tp __value, memory_order, memory_order) { - __a->__lock(); - bool __ret = (_VSTD::memcmp(&__a->__a_value, __expected, sizeof(_Tp)) == 0); - if(__ret) - _VSTD::memcpy(&__a->__a_value, &__value, sizeof(_Tp)); - else - _VSTD::memcpy(__expected, &__a->__a_value, sizeof(_Tp)); - __a->__unlock(); - return __ret; -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_weak(volatile __cxx_atomic_lock_impl<_Tp>* __a, - _Tp* __expected, _Tp __value, memory_order, memory_order) { - _Tp __temp; - __a->__lock(); - __cxx_atomic_assign_volatile(__temp, __a->__a_value); - bool __ret = (_VSTD::memcmp(&__temp, __expected, sizeof(_Tp)) == 0); - if(__ret) - __cxx_atomic_assign_volatile(__a->__a_value, __value); - else - __cxx_atomic_assign_volatile(*__expected, __a->__a_value); - __a->__unlock(); - return __ret; -} -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -bool __cxx_atomic_compare_exchange_weak(__cxx_atomic_lock_impl<_Tp>* __a, - _Tp* __expected, _Tp __value, memory_order, memory_order) { - __a->__lock(); - bool __ret = (_VSTD::memcmp(&__a->__a_value, __expected, sizeof(_Tp)) == 0); - if(__ret) - _VSTD::memcpy(&__a->__a_value, &__value, sizeof(_Tp)); - else - _VSTD::memcpy(__expected, &__a->__a_value, sizeof(_Tp)); - __a->__unlock(); - return __ret; -} - -template <typename _Tp, typename _Td> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_add(volatile __cxx_atomic_lock_impl<_Tp>* __a, - _Td __delta, memory_order) { - __a->__lock(); - _Tp __old; - __cxx_atomic_assign_volatile(__old, __a->__a_value); - __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old + __delta)); - __a->__unlock(); - return __old; -} -template <typename _Tp, typename _Td> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_add(__cxx_atomic_lock_impl<_Tp>* __a, - _Td __delta, memory_order) { - __a->__lock(); - _Tp __old = __a->__a_value; - __a->__a_value += __delta; - __a->__unlock(); - return __old; -} - -template <typename _Tp, typename _Td> -_LIBCPP_INLINE_VISIBILITY -_Tp* __cxx_atomic_fetch_add(volatile __cxx_atomic_lock_impl<_Tp*>* __a, - ptrdiff_t __delta, memory_order) { - __a->__lock(); - _Tp* __old; - __cxx_atomic_assign_volatile(__old, __a->__a_value); - __cxx_atomic_assign_volatile(__a->__a_value, __old + __delta); - __a->__unlock(); - return __old; -} -template <typename _Tp, typename _Td> -_LIBCPP_INLINE_VISIBILITY -_Tp* __cxx_atomic_fetch_add(__cxx_atomic_lock_impl<_Tp*>* __a, - ptrdiff_t __delta, memory_order) { - __a->__lock(); - _Tp* __old = __a->__a_value; - __a->__a_value += __delta; - __a->__unlock(); - return __old; -} - -template <typename _Tp, typename _Td> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_sub(volatile __cxx_atomic_lock_impl<_Tp>* __a, - _Td __delta, memory_order) { - __a->__lock(); - _Tp __old; - __cxx_atomic_assign_volatile(__old, __a->__a_value); - __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old - __delta)); - __a->__unlock(); - return __old; -} -template <typename _Tp, typename _Td> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_sub(__cxx_atomic_lock_impl<_Tp>* __a, - _Td __delta, memory_order) { - __a->__lock(); - _Tp __old = __a->__a_value; - __a->__a_value -= __delta; - __a->__unlock(); - return __old; -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_and(volatile __cxx_atomic_lock_impl<_Tp>* __a, - _Tp __pattern, memory_order) { - __a->__lock(); - _Tp __old; - __cxx_atomic_assign_volatile(__old, __a->__a_value); - __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old & __pattern)); - __a->__unlock(); - return __old; -} -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_and(__cxx_atomic_lock_impl<_Tp>* __a, - _Tp __pattern, memory_order) { - __a->__lock(); - _Tp __old = __a->__a_value; - __a->__a_value &= __pattern; - __a->__unlock(); - return __old; -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_or(volatile __cxx_atomic_lock_impl<_Tp>* __a, - _Tp __pattern, memory_order) { - __a->__lock(); - _Tp __old; - __cxx_atomic_assign_volatile(__old, __a->__a_value); - __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old | __pattern)); - __a->__unlock(); - return __old; -} -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_or(__cxx_atomic_lock_impl<_Tp>* __a, - _Tp __pattern, memory_order) { - __a->__lock(); - _Tp __old = __a->__a_value; - __a->__a_value |= __pattern; - __a->__unlock(); - return __old; -} - -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_xor(volatile __cxx_atomic_lock_impl<_Tp>* __a, - _Tp __pattern, memory_order) { - __a->__lock(); - _Tp __old; - __cxx_atomic_assign_volatile(__old, __a->__a_value); - __cxx_atomic_assign_volatile(__a->__a_value, _Tp(__old ^ __pattern)); - __a->__unlock(); - return __old; -} -template <typename _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp __cxx_atomic_fetch_xor(__cxx_atomic_lock_impl<_Tp>* __a, - _Tp __pattern, memory_order) { - __a->__lock(); - _Tp __old = __a->__a_value; - __a->__a_value ^= __pattern; - __a->__unlock(); - return __old; -} - -template <typename _Tp, - typename _Base = typename conditional<__libcpp_is_always_lock_free<_Tp>::__value, - __cxx_atomic_base_impl<_Tp>, - __cxx_atomic_lock_impl<_Tp> >::type> -#else -template <typename _Tp, - typename _Base = __cxx_atomic_base_impl<_Tp> > -#endif //_LIBCPP_ATOMIC_ONLY_USE_BUILTINS -struct __cxx_atomic_impl : public _Base { - static_assert(is_trivially_copyable<_Tp>::value, - "std::atomic<T> requires that 'T' be a trivially copyable type"); - - _LIBCPP_INLINE_VISIBILITY __cxx_atomic_impl() _NOEXCEPT = default; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT - : _Base(__value) {} -}; - -#if defined(__linux__) || (defined(_AIX) && !defined(__64BIT__)) - using __cxx_contention_t = int32_t; -#else - using __cxx_contention_t = int64_t; -#endif // __linux__ || (_AIX && !__64BIT__) - -using __cxx_atomic_contention_t = __cxx_atomic_impl<__cxx_contention_t>; - -#ifndef _LIBCPP_HAS_NO_THREADS - -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*); -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*); -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(void const volatile*); -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(void const volatile*, __cxx_contention_t); - -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*); -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*); -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*); -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t); - -template <class _Atp, class _Fn> -struct __libcpp_atomic_wait_backoff_impl { - _Atp* __a; - _Fn __test_fn; - _LIBCPP_AVAILABILITY_SYNC - _LIBCPP_INLINE_VISIBILITY bool operator()(chrono::nanoseconds __elapsed) const - { - if(__elapsed > chrono::microseconds(64)) - { - auto const __monitor = std::__libcpp_atomic_monitor(__a); - if(__test_fn()) - return true; - std::__libcpp_atomic_wait(__a, __monitor); - } - else if(__elapsed > chrono::microseconds(4)) - __libcpp_thread_yield(); - else - {} // poll - return false; - } -}; - -template <class _Atp, class _Fn> -_LIBCPP_AVAILABILITY_SYNC -_LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp* __a, _Fn && __test_fn) -{ - __libcpp_atomic_wait_backoff_impl<_Atp, typename decay<_Fn>::type> __backoff_fn = {__a, __test_fn}; - return std::__libcpp_thread_poll_with_backoff(__test_fn, __backoff_fn); -} - -#else // _LIBCPP_HAS_NO_THREADS - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY void __cxx_atomic_notify_all(__cxx_atomic_impl<_Tp> const volatile*) { } -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY void __cxx_atomic_notify_one(__cxx_atomic_impl<_Tp> const volatile*) { } -template <class _Atp, class _Fn> -_LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp*, _Fn && __test_fn) -{ - return __libcpp_thread_poll_with_backoff(__test_fn, __spinning_backoff_policy()); -} - -#endif // _LIBCPP_HAS_NO_THREADS - -template <class _Atp, class _Tp> -struct __cxx_atomic_wait_test_fn_impl { - _Atp* __a; - _Tp __val; - memory_order __order; - _LIBCPP_INLINE_VISIBILITY bool operator()() const - { - return !std::__cxx_nonatomic_compare_equal(std::__cxx_atomic_load(__a, __order), __val); - } -}; - -template <class _Atp, class _Tp> -_LIBCPP_AVAILABILITY_SYNC -_LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp* __a, _Tp const __val, memory_order __order) -{ - __cxx_atomic_wait_test_fn_impl<_Atp, _Tp> __test_fn = {__a, __val, __order}; - return std::__cxx_atomic_wait(__a, __test_fn); -} - -// general atomic<T> - -template <class _Tp, bool = is_integral<_Tp>::value && !is_same<_Tp, bool>::value> -struct __atomic_base // false -{ - mutable __cxx_atomic_impl<_Tp> __a_; - -#if defined(__cpp_lib_atomic_is_always_lock_free) - static _LIBCPP_CONSTEXPR bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value; -#endif - - _LIBCPP_INLINE_VISIBILITY - bool is_lock_free() const volatile _NOEXCEPT - {return __cxx_atomic_is_lock_free(sizeof(_Tp));} - _LIBCPP_INLINE_VISIBILITY - bool is_lock_free() const _NOEXCEPT - {return static_cast<__atomic_base const volatile*>(this)->is_lock_free();} - _LIBCPP_INLINE_VISIBILITY - void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) - {std::__cxx_atomic_store(&__a_, __d, __m);} - _LIBCPP_INLINE_VISIBILITY - void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT - _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) - {std::__cxx_atomic_store(&__a_, __d, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) - {return std::__cxx_atomic_load(&__a_, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) - {return std::__cxx_atomic_load(&__a_, __m);} - _LIBCPP_INLINE_VISIBILITY - operator _Tp() const volatile _NOEXCEPT {return load();} - _LIBCPP_INLINE_VISIBILITY - operator _Tp() const _NOEXCEPT {return load();} - _LIBCPP_INLINE_VISIBILITY - _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_exchange(&__a_, __d, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_exchange(&__a_, __d, __m);} - _LIBCPP_INLINE_VISIBILITY - bool compare_exchange_weak(_Tp& __e, _Tp __d, - memory_order __s, memory_order __f) volatile _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) - {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __s, __f);} - _LIBCPP_INLINE_VISIBILITY - bool compare_exchange_weak(_Tp& __e, _Tp __d, - memory_order __s, memory_order __f) _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) - {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __s, __f);} - _LIBCPP_INLINE_VISIBILITY - bool compare_exchange_strong(_Tp& __e, _Tp __d, - memory_order __s, memory_order __f) volatile _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) - {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __s, __f);} - _LIBCPP_INLINE_VISIBILITY - bool compare_exchange_strong(_Tp& __e, _Tp __d, - memory_order __s, memory_order __f) _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) - {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __s, __f);} - _LIBCPP_INLINE_VISIBILITY - bool compare_exchange_weak(_Tp& __e, _Tp __d, - memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __m, __m);} - _LIBCPP_INLINE_VISIBILITY - bool compare_exchange_weak(_Tp& __e, _Tp __d, - memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_compare_exchange_weak(&__a_, &__e, __d, __m, __m);} - _LIBCPP_INLINE_VISIBILITY - bool compare_exchange_strong(_Tp& __e, _Tp __d, - memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} - _LIBCPP_INLINE_VISIBILITY - bool compare_exchange_strong(_Tp& __e, _Tp __d, - memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_compare_exchange_strong(&__a_, &__e, __d, __m, __m);} - - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT - {std::__cxx_atomic_wait(&__a_, __v, __m);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT - {std::__cxx_atomic_wait(&__a_, __v, __m);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_one() volatile _NOEXCEPT - {std::__cxx_atomic_notify_one(&__a_);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_one() _NOEXCEPT - {std::__cxx_atomic_notify_one(&__a_);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_all() volatile _NOEXCEPT - {std::__cxx_atomic_notify_all(&__a_);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void notify_all() _NOEXCEPT - {std::__cxx_atomic_notify_all(&__a_);} - -#if _LIBCPP_STD_VER > 17 - _LIBCPP_INLINE_VISIBILITY constexpr - __atomic_base() noexcept(is_nothrow_default_constructible_v<_Tp>) : __a_(_Tp()) {} -#else - _LIBCPP_INLINE_VISIBILITY - __atomic_base() _NOEXCEPT = default; -#endif - - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {} - - __atomic_base(const __atomic_base&) = delete; -}; - -#if defined(__cpp_lib_atomic_is_always_lock_free) -template <class _Tp, bool __b> -_LIBCPP_CONSTEXPR bool __atomic_base<_Tp, __b>::is_always_lock_free; -#endif - -// atomic<Integral> - -template <class _Tp> -struct __atomic_base<_Tp, true> - : public __atomic_base<_Tp, false> -{ - typedef __atomic_base<_Tp, false> __base; - - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 - __atomic_base() _NOEXCEPT = default; - - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {} - - _LIBCPP_INLINE_VISIBILITY - _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_fetch_add(&this->__a_, __op, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_fetch_add(&this->__a_, __op, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_fetch_sub(&this->__a_, __op, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_fetch_sub(&this->__a_, __op, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_fetch_and(&this->__a_, __op, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_fetch_and(&this->__a_, __op, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_fetch_or(&this->__a_, __op, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_fetch_or(&this->__a_, __op, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return std::__cxx_atomic_fetch_xor(&this->__a_, __op, __m);} - _LIBCPP_INLINE_VISIBILITY - _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return std::__cxx_atomic_fetch_xor(&this->__a_, __op, __m);} - - _LIBCPP_INLINE_VISIBILITY - _Tp operator++(int) volatile _NOEXCEPT {return fetch_add(_Tp(1));} - _LIBCPP_INLINE_VISIBILITY - _Tp operator++(int) _NOEXCEPT {return fetch_add(_Tp(1));} - _LIBCPP_INLINE_VISIBILITY - _Tp operator--(int) volatile _NOEXCEPT {return fetch_sub(_Tp(1));} - _LIBCPP_INLINE_VISIBILITY - _Tp operator--(int) _NOEXCEPT {return fetch_sub(_Tp(1));} - _LIBCPP_INLINE_VISIBILITY - _Tp operator++() volatile _NOEXCEPT {return fetch_add(_Tp(1)) + _Tp(1);} - _LIBCPP_INLINE_VISIBILITY - _Tp operator++() _NOEXCEPT {return fetch_add(_Tp(1)) + _Tp(1);} - _LIBCPP_INLINE_VISIBILITY - _Tp operator--() volatile _NOEXCEPT {return fetch_sub(_Tp(1)) - _Tp(1);} - _LIBCPP_INLINE_VISIBILITY - _Tp operator--() _NOEXCEPT {return fetch_sub(_Tp(1)) - _Tp(1);} - _LIBCPP_INLINE_VISIBILITY - _Tp operator+=(_Tp __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp operator+=(_Tp __op) _NOEXCEPT {return fetch_add(__op) + __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp operator-=(_Tp __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp operator-=(_Tp __op) _NOEXCEPT {return fetch_sub(__op) - __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp operator&=(_Tp __op) volatile _NOEXCEPT {return fetch_and(__op) & __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp operator&=(_Tp __op) _NOEXCEPT {return fetch_and(__op) & __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp operator|=(_Tp __op) volatile _NOEXCEPT {return fetch_or(__op) | __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp operator|=(_Tp __op) _NOEXCEPT {return fetch_or(__op) | __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp operator^=(_Tp __op) volatile _NOEXCEPT {return fetch_xor(__op) ^ __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp operator^=(_Tp __op) _NOEXCEPT {return fetch_xor(__op) ^ __op;} -}; - -// atomic<T> - -template <class _Tp> -struct atomic - : public __atomic_base<_Tp> -{ - typedef __atomic_base<_Tp> __base; - typedef _Tp value_type; - typedef value_type difference_type; - -#if _LIBCPP_STD_VER > 17 - _LIBCPP_INLINE_VISIBILITY - atomic() = default; -#else - _LIBCPP_INLINE_VISIBILITY - atomic() _NOEXCEPT = default; -#endif - - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {} - - _LIBCPP_INLINE_VISIBILITY - _Tp operator=(_Tp __d) volatile _NOEXCEPT - {__base::store(__d); return __d;} - _LIBCPP_INLINE_VISIBILITY - _Tp operator=(_Tp __d) _NOEXCEPT - {__base::store(__d); return __d;} - - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; -}; - -// atomic<T*> - -template <class _Tp> -struct atomic<_Tp*> - : public __atomic_base<_Tp*> -{ - typedef __atomic_base<_Tp*> __base; - typedef _Tp* value_type; - typedef ptrdiff_t difference_type; - - _LIBCPP_INLINE_VISIBILITY - atomic() _NOEXCEPT = default; - - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {} - - _LIBCPP_INLINE_VISIBILITY - _Tp* operator=(_Tp* __d) volatile _NOEXCEPT - {__base::store(__d); return __d;} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator=(_Tp* __d) _NOEXCEPT - {__base::store(__d); return __d;} - - _LIBCPP_INLINE_VISIBILITY - _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { - // __atomic_fetch_add accepts function pointers, guard against them. - static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); - return std::__cxx_atomic_fetch_add(&this->__a_, __op, __m); - } - - _LIBCPP_INLINE_VISIBILITY - _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { - // __atomic_fetch_add accepts function pointers, guard against them. - static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); - return std::__cxx_atomic_fetch_add(&this->__a_, __op, __m); - } - - _LIBCPP_INLINE_VISIBILITY - _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { - // __atomic_fetch_add accepts function pointers, guard against them. - static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); - return std::__cxx_atomic_fetch_sub(&this->__a_, __op, __m); - } - - _LIBCPP_INLINE_VISIBILITY - _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { - // __atomic_fetch_add accepts function pointers, guard against them. - static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed"); - return std::__cxx_atomic_fetch_sub(&this->__a_, __op, __m); - } - - _LIBCPP_INLINE_VISIBILITY - _Tp* operator++(int) volatile _NOEXCEPT {return fetch_add(1);} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator++(int) _NOEXCEPT {return fetch_add(1);} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator--(int) volatile _NOEXCEPT {return fetch_sub(1);} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator--(int) _NOEXCEPT {return fetch_sub(1);} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator++() volatile _NOEXCEPT {return fetch_add(1) + 1;} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator++() _NOEXCEPT {return fetch_add(1) + 1;} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator--() volatile _NOEXCEPT {return fetch_sub(1) - 1;} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator--() _NOEXCEPT {return fetch_sub(1) - 1;} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT {return fetch_add(__op) + __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;} - _LIBCPP_INLINE_VISIBILITY - _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT {return fetch_sub(__op) - __op;} - - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; -}; - -// atomic_is_lock_free - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool -atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT -{ - return __o->is_lock_free(); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool -atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT -{ - return __o->is_lock_free(); -} - -// atomic_init - -template <class _Tp> -_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY -void -atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT -{ - std::__cxx_atomic_init(&__o->__a_, __d); -} - -template <class _Tp> -_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_INLINE_VISIBILITY -void -atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT -{ - std::__cxx_atomic_init(&__o->__a_, __d); -} - -// atomic_store - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -void -atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT -{ - __o->store(__d); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -void -atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT -{ - __o->store(__d); -} - -// atomic_store_explicit - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -void -atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT - _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) -{ - __o->store(__d, __m); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -void -atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT - _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) -{ - __o->store(__d, __m); -} - -// atomic_load - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp -atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT -{ - return __o->load(); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp -atomic_load(const atomic<_Tp>* __o) _NOEXCEPT -{ - return __o->load(); -} - -// atomic_load_explicit - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp -atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) -{ - return __o->load(__m); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp -atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) -{ - return __o->load(__m); -} - -// atomic_exchange - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp -atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT -{ - return __o->exchange(__d); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp -atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT -{ - return __o->exchange(__d); -} - -// atomic_exchange_explicit - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp -atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT -{ - return __o->exchange(__d, __m); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp -atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT -{ - return __o->exchange(__d, __m); -} - -// atomic_compare_exchange_weak - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool -atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT -{ - return __o->compare_exchange_weak(*__e, __d); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool -atomic_compare_exchange_weak(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT -{ - return __o->compare_exchange_weak(*__e, __d); -} - -// atomic_compare_exchange_strong - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool -atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT -{ - return __o->compare_exchange_strong(*__e, __d); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool -atomic_compare_exchange_strong(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT -{ - return __o->compare_exchange_strong(*__e, __d); -} - -// atomic_compare_exchange_weak_explicit - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool -atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, - typename atomic<_Tp>::value_type __d, - memory_order __s, memory_order __f) _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) -{ - return __o->compare_exchange_weak(*__e, __d, __s, __f); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool -atomic_compare_exchange_weak_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, - memory_order __s, memory_order __f) _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) -{ - return __o->compare_exchange_weak(*__e, __d, __s, __f); -} - -// atomic_compare_exchange_strong_explicit - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool -atomic_compare_exchange_strong_explicit(volatile atomic<_Tp>* __o, - typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d, - memory_order __s, memory_order __f) _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) -{ - return __o->compare_exchange_strong(*__e, __d, __s, __f); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -bool -atomic_compare_exchange_strong_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, - typename atomic<_Tp>::value_type __d, - memory_order __s, memory_order __f) _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) -{ - return __o->compare_exchange_strong(*__e, __d, __s, __f); -} - -// atomic_wait - -template <class _Tp> -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY -void atomic_wait(const volatile atomic<_Tp>* __o, - typename atomic<_Tp>::value_type __v) _NOEXCEPT -{ - return __o->wait(__v); -} - -template <class _Tp> -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY -void atomic_wait(const atomic<_Tp>* __o, - typename atomic<_Tp>::value_type __v) _NOEXCEPT -{ - return __o->wait(__v); -} - -// atomic_wait_explicit - -template <class _Tp> -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY -void atomic_wait_explicit(const volatile atomic<_Tp>* __o, - typename atomic<_Tp>::value_type __v, - memory_order __m) _NOEXCEPT - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) -{ - return __o->wait(__v, __m); -} - -template <class _Tp> -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY -void atomic_wait_explicit(const atomic<_Tp>* __o, - typename atomic<_Tp>::value_type __v, - memory_order __m) _NOEXCEPT - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) -{ - return __o->wait(__v, __m); -} - -// atomic_notify_one - -template <class _Tp> -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY -void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT -{ - __o->notify_one(); -} -template <class _Tp> -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY -void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT -{ - __o->notify_one(); -} - -// atomic_notify_all - -template <class _Tp> -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY -void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT -{ - __o->notify_all(); -} -template <class _Tp> -_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY -void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT -{ - __o->notify_all(); -} - -// atomic_fetch_add - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp -atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT -{ - return __o->fetch_add(__op); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp -atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT -{ - return __o->fetch_add(__op); -} - -// atomic_fetch_add_explicit - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp atomic_fetch_add_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT -{ - return __o->fetch_add(__op, __m); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT -{ - return __o->fetch_add(__op, __m); -} - -// atomic_fetch_sub - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT -{ - return __o->fetch_sub(__op); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT -{ - return __o->fetch_sub(__op); -} - -// atomic_fetch_sub_explicit - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp atomic_fetch_sub_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT -{ - return __o->fetch_sub(__op, __m); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -_Tp atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT -{ - return __o->fetch_sub(__op, __m); -} - -// atomic_fetch_and - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT -{ - return __o->fetch_and(__op); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT -{ - return __o->fetch_and(__op); -} - -// atomic_fetch_and_explicit - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_and_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT -{ - return __o->fetch_and(__op, __m); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT -{ - return __o->fetch_and(__op, __m); -} - -// atomic_fetch_or - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT -{ - return __o->fetch_or(__op); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT -{ - return __o->fetch_or(__op); -} - -// atomic_fetch_or_explicit - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT -{ - return __o->fetch_or(__op, __m); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT -{ - return __o->fetch_or(__op, __m); -} - -// atomic_fetch_xor - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT -{ - return __o->fetch_xor(__op); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT -{ - return __o->fetch_xor(__op); -} - -// atomic_fetch_xor_explicit - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_xor_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT -{ - return __o->fetch_xor(__op, __m); -} - -template <class _Tp> -_LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_integral<_Tp>::value && !is_same<_Tp, bool>::value, - _Tp ->::type -atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT -{ - return __o->fetch_xor(__op, __m); -} - -// flag type and operations - -typedef struct atomic_flag -{ - __cxx_atomic_impl<_LIBCPP_ATOMIC_FLAG_TYPE> __a_; - - _LIBCPP_INLINE_VISIBILITY - bool test(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT - {return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m);} - _LIBCPP_INLINE_VISIBILITY - bool test(memory_order __m = memory_order_seq_cst) const _NOEXCEPT - {return _LIBCPP_ATOMIC_FLAG_TYPE(true) == __cxx_atomic_load(&__a_, __m);} - - _LIBCPP_INLINE_VISIBILITY - bool test_and_set(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m);} - _LIBCPP_INLINE_VISIBILITY - bool test_and_set(memory_order __m = memory_order_seq_cst) _NOEXCEPT - {return __cxx_atomic_exchange(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(true), __m);} - _LIBCPP_INLINE_VISIBILITY - void clear(memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - {__cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m);} - _LIBCPP_INLINE_VISIBILITY - void clear(memory_order __m = memory_order_seq_cst) _NOEXCEPT - {__cxx_atomic_store(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(false), __m);} - - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY - void wait(bool __v, memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT - {__cxx_atomic_wait(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY - void wait(bool __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT - {__cxx_atomic_wait(&__a_, _LIBCPP_ATOMIC_FLAG_TYPE(__v), __m);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY - void notify_one() volatile _NOEXCEPT - {__cxx_atomic_notify_one(&__a_);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY - void notify_one() _NOEXCEPT - {__cxx_atomic_notify_one(&__a_);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY - void notify_all() volatile _NOEXCEPT - {__cxx_atomic_notify_all(&__a_);} - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY - void notify_all() _NOEXCEPT - {__cxx_atomic_notify_all(&__a_);} - -#if _LIBCPP_STD_VER > 17 - _LIBCPP_INLINE_VISIBILITY constexpr - atomic_flag() _NOEXCEPT : __a_(false) {} -#else - _LIBCPP_INLINE_VISIBILITY - atomic_flag() _NOEXCEPT = default; -#endif - - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - atomic_flag(bool __b) _NOEXCEPT : __a_(__b) {} // EXTENSION - - atomic_flag(const atomic_flag&) = delete; - atomic_flag& operator=(const atomic_flag&) = delete; - atomic_flag& operator=(const atomic_flag&) volatile = delete; - -} atomic_flag; - - -inline _LIBCPP_INLINE_VISIBILITY -bool -atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT -{ - return __o->test(); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool -atomic_flag_test(const atomic_flag* __o) _NOEXCEPT -{ - return __o->test(); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool -atomic_flag_test_explicit(const volatile atomic_flag* __o, memory_order __m) _NOEXCEPT -{ - return __o->test(__m); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool -atomic_flag_test_explicit(const atomic_flag* __o, memory_order __m) _NOEXCEPT -{ - return __o->test(__m); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool -atomic_flag_test_and_set(volatile atomic_flag* __o) _NOEXCEPT -{ - return __o->test_and_set(); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool -atomic_flag_test_and_set(atomic_flag* __o) _NOEXCEPT -{ - return __o->test_and_set(); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool -atomic_flag_test_and_set_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT -{ - return __o->test_and_set(__m); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool -atomic_flag_test_and_set_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT -{ - return __o->test_and_set(__m); -} - -inline _LIBCPP_INLINE_VISIBILITY -void -atomic_flag_clear(volatile atomic_flag* __o) _NOEXCEPT -{ - __o->clear(); -} - -inline _LIBCPP_INLINE_VISIBILITY -void -atomic_flag_clear(atomic_flag* __o) _NOEXCEPT -{ - __o->clear(); -} - -inline _LIBCPP_INLINE_VISIBILITY -void -atomic_flag_clear_explicit(volatile atomic_flag* __o, memory_order __m) _NOEXCEPT -{ - __o->clear(__m); -} - -inline _LIBCPP_INLINE_VISIBILITY -void -atomic_flag_clear_explicit(atomic_flag* __o, memory_order __m) _NOEXCEPT -{ - __o->clear(__m); -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC -void -atomic_flag_wait(const volatile atomic_flag* __o, bool __v) _NOEXCEPT -{ - __o->wait(__v); -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC -void -atomic_flag_wait(const atomic_flag* __o, bool __v) _NOEXCEPT -{ - __o->wait(__v); -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC -void -atomic_flag_wait_explicit(const volatile atomic_flag* __o, - bool __v, memory_order __m) _NOEXCEPT -{ - __o->wait(__v, __m); -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC -void -atomic_flag_wait_explicit(const atomic_flag* __o, - bool __v, memory_order __m) _NOEXCEPT -{ - __o->wait(__v, __m); -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC -void -atomic_flag_notify_one(volatile atomic_flag* __o) _NOEXCEPT -{ - __o->notify_one(); -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC -void -atomic_flag_notify_one(atomic_flag* __o) _NOEXCEPT -{ - __o->notify_one(); -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC -void -atomic_flag_notify_all(volatile atomic_flag* __o) _NOEXCEPT -{ - __o->notify_all(); -} - -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_SYNC -void -atomic_flag_notify_all(atomic_flag* __o) _NOEXCEPT -{ - __o->notify_all(); -} - -// fences - -inline _LIBCPP_INLINE_VISIBILITY -void -atomic_thread_fence(memory_order __m) _NOEXCEPT -{ - __cxx_atomic_thread_fence(__m); -} - -inline _LIBCPP_INLINE_VISIBILITY -void -atomic_signal_fence(memory_order __m) _NOEXCEPT -{ - __cxx_atomic_signal_fence(__m); -} - -// Atomics for standard typedef types - -typedef atomic<bool> atomic_bool; -typedef atomic<char> atomic_char; -typedef atomic<signed char> atomic_schar; -typedef atomic<unsigned char> atomic_uchar; -typedef atomic<short> atomic_short; -typedef atomic<unsigned short> atomic_ushort; -typedef atomic<int> atomic_int; -typedef atomic<unsigned int> atomic_uint; -typedef atomic<long> atomic_long; -typedef atomic<unsigned long> atomic_ulong; -typedef atomic<long long> atomic_llong; -typedef atomic<unsigned long long> atomic_ullong; -#ifndef _LIBCPP_HAS_NO_CHAR8_T -typedef atomic<char8_t> atomic_char8_t; -#endif -typedef atomic<char16_t> atomic_char16_t; -typedef atomic<char32_t> atomic_char32_t; -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -typedef atomic<wchar_t> atomic_wchar_t; -#endif - -typedef atomic<int_least8_t> atomic_int_least8_t; -typedef atomic<uint_least8_t> atomic_uint_least8_t; -typedef atomic<int_least16_t> atomic_int_least16_t; -typedef atomic<uint_least16_t> atomic_uint_least16_t; -typedef atomic<int_least32_t> atomic_int_least32_t; -typedef atomic<uint_least32_t> atomic_uint_least32_t; -typedef atomic<int_least64_t> atomic_int_least64_t; -typedef atomic<uint_least64_t> atomic_uint_least64_t; - -typedef atomic<int_fast8_t> atomic_int_fast8_t; -typedef atomic<uint_fast8_t> atomic_uint_fast8_t; -typedef atomic<int_fast16_t> atomic_int_fast16_t; -typedef atomic<uint_fast16_t> atomic_uint_fast16_t; -typedef atomic<int_fast32_t> atomic_int_fast32_t; -typedef atomic<uint_fast32_t> atomic_uint_fast32_t; -typedef atomic<int_fast64_t> atomic_int_fast64_t; -typedef atomic<uint_fast64_t> atomic_uint_fast64_t; - -typedef atomic< int8_t> atomic_int8_t; -typedef atomic<uint8_t> atomic_uint8_t; -typedef atomic< int16_t> atomic_int16_t; -typedef atomic<uint16_t> atomic_uint16_t; -typedef atomic< int32_t> atomic_int32_t; -typedef atomic<uint32_t> atomic_uint32_t; -typedef atomic< int64_t> atomic_int64_t; -typedef atomic<uint64_t> atomic_uint64_t; - -typedef atomic<intptr_t> atomic_intptr_t; -typedef atomic<uintptr_t> atomic_uintptr_t; -typedef atomic<size_t> atomic_size_t; -typedef atomic<ptrdiff_t> atomic_ptrdiff_t; -typedef atomic<intmax_t> atomic_intmax_t; -typedef atomic<uintmax_t> atomic_uintmax_t; - -// atomic_*_lock_free : prefer the contention type most highly, then the largest lock-free type - -#ifdef __cpp_lib_atomic_is_always_lock_free -# define _LIBCPP_CONTENTION_LOCK_FREE ::std::__libcpp_is_always_lock_free<__cxx_contention_t>::__value -#else -# define _LIBCPP_CONTENTION_LOCK_FREE false -#endif - -#if ATOMIC_LLONG_LOCK_FREE == 2 -typedef __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, long long> __libcpp_signed_lock_free; -typedef __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned long long> __libcpp_unsigned_lock_free; -#elif ATOMIC_INT_LOCK_FREE == 2 -typedef __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, int> __libcpp_signed_lock_free; -typedef __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned int> __libcpp_unsigned_lock_free; -#elif ATOMIC_SHORT_LOCK_FREE == 2 -typedef __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, short> __libcpp_signed_lock_free; -typedef __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned short> __libcpp_unsigned_lock_free; -#elif ATOMIC_CHAR_LOCK_FREE == 2 -typedef __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, char> __libcpp_signed_lock_free; -typedef __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned char> __libcpp_unsigned_lock_free; -#else - // No signed/unsigned lock-free types -#define _LIBCPP_NO_LOCK_FREE_TYPES -#endif - -#if !defined(_LIBCPP_NO_LOCK_FREE_TYPES) -typedef atomic<__libcpp_signed_lock_free> atomic_signed_lock_free; -typedef atomic<__libcpp_unsigned_lock_free> atomic_unsigned_lock_free; +#ifdef kill_dependency +# error <atomic> is incompatible with <stdatomic.h> before C++23. Please compile with -std=c++23. #endif -#define ATOMIC_FLAG_INIT {false} -#define ATOMIC_VAR_INIT(__v) {__v} - -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) -# if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1400 -# pragma clang deprecated(ATOMIC_VAR_INIT) -# endif -#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) - -_LIBCPP_END_NAMESPACE_STD - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <cmath> # include <compare> +# include <cstring> # include <type_traits> #endif diff --git a/libcxx/include/barrier b/libcxx/include/barrier index 2e8906b71379..e0d63fa59ffd 100644 --- a/libcxx/include/barrier +++ b/libcxx/include/barrier @@ -46,13 +46,18 @@ namespace std */ #include <__assert> // all public C++ headers provide the assertion handler +#include <__atomic/atomic_base.h> +#include <__atomic/memory_order.h> #include <__availability> #include <__config> #include <__memory/unique_ptr.h> +#include <__thread/poll_with_backoff.h> #include <__thread/timed_backoff_policy.h> #include <__utility/move.h> -#include <atomic> +#include <cstddef> +#include <cstdint> #include <limits> +#include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -119,7 +124,7 @@ class __barrier_base { public: using arrival_token = __barrier_phase_t; - static constexpr ptrdiff_t max() noexcept { + static _LIBCPP_HIDE_FROM_ABI constexpr ptrdiff_t max() noexcept { return numeric_limits<ptrdiff_t>::max(); } @@ -130,9 +135,12 @@ public: __expected_adjustment_(0), __completion_(std::move(__completion)), __phase_(0) { } - [[nodiscard]] _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY + [[__nodiscard__]] _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY arrival_token arrive(ptrdiff_t __update) { + _LIBCPP_ASSERT_UNCATEGORIZED( + __update <= __expected_, "update is greater than the expected count for the current barrier phase"); + auto const __old_phase = __phase_.load(memory_order_relaxed); for(; __update; --__update) if(__arrive_barrier_algorithm_base(__base_.get(), __old_phase)) { @@ -200,7 +208,11 @@ public: auto const __old_phase = __phase.load(memory_order_relaxed); auto const __result = __arrived.fetch_sub(update, memory_order_acq_rel) - update; auto const new_expected = __expected.load(memory_order_relaxed); - if(0 == __result) { + + _LIBCPP_ASSERT_UNCATEGORIZED( + update <= new_expected, "update is greater than the expected count for the current barrier phase"); + + if (0 == __result) { __completion(); __arrived.store(new_expected, memory_order_relaxed); __phase.store(!__old_phase, memory_order_release); @@ -256,7 +268,11 @@ public: { auto const __inc = __arrived_unit * update; auto const __old = __phase_arrived_expected.fetch_add(__inc, memory_order_acq_rel); - if((__old ^ (__old + __inc)) & __phase_bit) { + + _LIBCPP_ASSERT_UNCATEGORIZED( + update <= __old, "update is greater than the expected count for the current barrier phase"); + + if ((__old ^ (__old + __inc)) & __phase_bit) { __phase_arrived_expected.fetch_add((__old & __expected_mask) << 32, memory_order_relaxed); __phase_arrived_expected.notify_all(); } @@ -288,21 +304,29 @@ class barrier { public: using arrival_token = typename __barrier_base<_CompletionF>::arrival_token; - static constexpr ptrdiff_t max() noexcept { + static _LIBCPP_HIDE_FROM_ABI constexpr ptrdiff_t max() noexcept { return __barrier_base<_CompletionF>::max(); } _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY - barrier(ptrdiff_t __count, _CompletionF __completion = _CompletionF()) + explicit barrier(ptrdiff_t __count, _CompletionF __completion = _CompletionF()) : __b_(__count, _VSTD::move(__completion)) { + _LIBCPP_ASSERT_UNCATEGORIZED( + __count >= 0, + "barrier::barrier(ptrdiff_t, CompletionFunction): barrier cannot be initialized with a negative value"); + _LIBCPP_ASSERT_UNCATEGORIZED( + __count <= max(), + "barrier::barrier(ptrdiff_t, CompletionFunction): barrier cannot be initialized with " + "a value greater than max()"); } barrier(barrier const&) = delete; barrier& operator=(barrier const&) = delete; - [[nodiscard]] _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY + [[__nodiscard__]] _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY arrival_token arrive(ptrdiff_t __update = 1) { + _LIBCPP_ASSERT_UNCATEGORIZED(__update > 0, "barrier:arrive must be called with a value greater than 0"); return __b_.arrive(__update); } _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY @@ -329,6 +353,7 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <atomic> # include <concepts> # include <iterator> # include <memory> diff --git a/libcxx/include/bit b/libcxx/include/bit index d17a6e45f0db..6b35bb2c7a0b 100644 --- a/libcxx/include/bit +++ b/libcxx/include/bit @@ -83,6 +83,7 @@ namespace std { #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstdlib> # include <iosfwd> # include <limits> # include <type_traits> diff --git a/libcxx/include/bitset b/libcxx/include/bitset index c260f9f592c0..c63ee22b1dfe 100644 --- a/libcxx/include/bitset +++ b/libcxx/include/bitset @@ -79,7 +79,7 @@ public: size_t count() const noexcept; // constexpr since C++23 constexpr size_t size() const noexcept; // constexpr since C++23 bool operator==(const bitset& rhs) const noexcept; // constexpr since C++23 - bool operator!=(const bitset& rhs) const noexcept; // constexpr since C++23 + bool operator!=(const bitset& rhs) const noexcept; // removed in C++20 bool test(size_t pos) const; // constexpr since C++23 bool all() const noexcept; // constexpr since C++23 bool any() const noexcept; // constexpr since C++23 @@ -122,6 +122,7 @@ template <size_t N> struct hash<std::bitset<N>>; #include <climits> #include <cstddef> #include <stdexcept> +#include <string_view> #include <version> // standard-mandated includes @@ -691,18 +692,30 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bitset() _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bitset(unsigned long long __v) _NOEXCEPT : base(__v) {} - template<class _CharT, class = __enable_if_t<_IsCharLikeType<_CharT>::value> > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 - explicit bitset(const _CharT* __str, - typename basic_string<_CharT>::size_type __n = basic_string<_CharT>::npos, - _CharT __zero = _CharT('0'), _CharT __one = _CharT('1')); - template<class _CharT, class _Traits, class _Allocator> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 - explicit bitset(const basic_string<_CharT,_Traits,_Allocator>& __str, - typename basic_string<_CharT,_Traits,_Allocator>::size_type __pos = 0, - typename basic_string<_CharT,_Traits,_Allocator>::size_type __n = - (basic_string<_CharT,_Traits,_Allocator>::npos), - _CharT __zero = _CharT('0'), _CharT __one = _CharT('1')); + template <class _CharT, class = __enable_if_t<_IsCharLikeType<_CharT>::value> > + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit bitset( + const _CharT* __str, + typename basic_string<_CharT>::size_type __n = basic_string<_CharT>::npos, + _CharT __zero = _CharT('0'), + _CharT __one = _CharT('1')) { + + size_t __rlen = std::min(__n, char_traits<_CharT>::length(__str)); + __init_from_string_view(basic_string_view<_CharT>(__str, __rlen), __zero, __one); + } + template <class _CharT, class _Traits, class _Allocator> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit bitset( + const basic_string<_CharT, _Traits, _Allocator>& __str, + typename basic_string<_CharT, _Traits, _Allocator>::size_type __pos = 0, + typename basic_string<_CharT, _Traits, _Allocator>::size_type __n = + basic_string<_CharT, _Traits, _Allocator>::npos, + _CharT __zero = _CharT('0'), + _CharT __one = _CharT('1')) { + if (__pos > __str.size()) + std::__throw_out_of_range("bitset string pos out of range"); + + size_t __rlen = std::min(__n, __str.size() - __pos); + __init_from_string_view(basic_string_view<_CharT, _Traits>(__str.data() + __pos, __rlen), __zero, __one); + } // 23.3.5.2 bitset operations: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 @@ -761,8 +774,10 @@ public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR size_t size() const _NOEXCEPT {return _Size;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const bitset& __rhs) const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 +#if _LIBCPP_STD_VER <= 17 + _LIBCPP_INLINE_VISIBILITY bool operator!=(const bitset& __rhs) const _NOEXCEPT; +#endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool test(size_t __pos) const; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 @@ -776,6 +791,22 @@ public: bitset operator>>(size_t __pos) const _NOEXCEPT; private: + template <class _CharT, class _Traits> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void + __init_from_string_view(basic_string_view<_CharT, _Traits> __str, _CharT __zero, _CharT __one) { + + for (size_t __i = 0; __i < __str.size(); ++__i) + if (!_Traits::eq(__str[__i], __zero) && !_Traits::eq(__str[__i], __one)) + std::__throw_invalid_argument("bitset string ctor has invalid argument"); + + size_t __mp = std::min(__str.size(), _Size); + size_t __i = 0; + for (; __i < __mp; ++__i) { + _CharT __c = __str[__mp - 1 - __i]; + (*this)[__i] = _Traits::eq(__c, __one); + } + std::fill(base::__make_iter(__i), base::__make_iter(_Size), false); + } _LIBCPP_INLINE_VISIBILITY size_t __hash_code() const _NOEXCEPT {return base::__hash_code();} @@ -784,54 +815,6 @@ private: }; template <size_t _Size> -template<class _CharT, class> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 -bitset<_Size>::bitset(const _CharT* __str, - typename basic_string<_CharT>::size_type __n, - _CharT __zero, _CharT __one) -{ - size_t __rlen = _VSTD::min(__n, char_traits<_CharT>::length(__str)); - for (size_t __i = 0; __i < __rlen; ++__i) - if (__str[__i] != __zero && __str[__i] != __one) - __throw_invalid_argument("bitset string ctor has invalid argument"); - - size_t _Mp = _VSTD::min(__rlen, _Size); - size_t __i = 0; - for (; __i < _Mp; ++__i) - { - _CharT __c = __str[_Mp - 1 - __i]; - (*this)[__i] = (__c == __one); - } - _VSTD::fill(base::__make_iter(__i), base::__make_iter(_Size), false); -} - -template <size_t _Size> -template<class _CharT, class _Traits, class _Allocator> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 -bitset<_Size>::bitset(const basic_string<_CharT,_Traits,_Allocator>& __str, - typename basic_string<_CharT,_Traits,_Allocator>::size_type __pos, - typename basic_string<_CharT,_Traits,_Allocator>::size_type __n, - _CharT __zero, _CharT __one) -{ - if (__pos > __str.size()) - __throw_out_of_range("bitset string pos out of range"); - - size_t __rlen = _VSTD::min(__n, __str.size() - __pos); - for (size_t __i = __pos; __i < __pos + __rlen; ++__i) - if (!_Traits::eq(__str[__i], __zero) && !_Traits::eq(__str[__i], __one)) - __throw_invalid_argument("bitset string ctor has invalid argument"); - - size_t _Mp = _VSTD::min(__rlen, _Size); - size_t __i = 0; - for (; __i < _Mp; ++__i) - { - _CharT __c = __str[__pos + _Mp - 1 - __i]; - (*this)[__i] = _Traits::eq(__c, __one); - } - _VSTD::fill(base::__make_iter(__i), base::__make_iter(_Size), false); -} - -template <size_t _Size> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size>& @@ -956,8 +939,8 @@ bitset<_Size>::flip(size_t __pos) if (__pos >= _Size) __throw_out_of_range("bitset flip argument out of range"); - reference r = base::__make_ref(__pos); - r = ~r; + reference __r = base::__make_ref(__pos); + __r = ~__r; return *this; } @@ -1041,15 +1024,19 @@ bitset<_Size>::operator==(const bitset& __rhs) const _NOEXCEPT return _VSTD::equal(base::__make_iter(0), base::__make_iter(_Size), __rhs.__make_iter(0)); } +#if _LIBCPP_STD_VER <= 17 + template <size_t _Size> inline -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 +_LIBCPP_HIDE_FROM_ABI bool bitset<_Size>::operator!=(const bitset& __rhs) const _NOEXCEPT { return !(*this == __rhs); } +#endif + template <size_t _Size> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool @@ -1154,6 +1141,8 @@ _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> +# include <cstdlib> +# include <type_traits> #endif #endif // _LIBCPP_BITSET diff --git a/libcxx/include/charconv b/libcxx/include/charconv index 9c74ce3c697f..5b6c72ea7f10 100644 --- a/libcxx/include/charconv +++ b/libcxx/include/charconv @@ -63,785 +63,41 @@ namespace std { constexpr from_chars_result from_chars(const char* first, const char* last, see below& value, int base = 10); // constexpr since C++23 - from_chars_result from_chars(const char* first, const char* last, - float& value, - chars_format fmt = chars_format::general); - from_chars_result from_chars(const char* first, const char* last, - double& value, - chars_format fmt = chars_format::general); - from_chars_result from_chars(const char* first, const char* last, - long double& value, - chars_format fmt = chars_format::general); - } // namespace std */ -#include <__algorithm/copy_n.h> #include <__assert> // all public C++ headers provide the assertion handler -#include <__availability> -#include <__bit/countl.h> #include <__charconv/chars_format.h> +#include <__charconv/from_chars_integral.h> #include <__charconv/from_chars_result.h> #include <__charconv/tables.h> +#include <__charconv/to_chars.h> #include <__charconv/to_chars_base_10.h> +#include <__charconv/to_chars_floating_point.h> +#include <__charconv/to_chars_integral.h> #include <__charconv/to_chars_result.h> +#include <__charconv/traits.h> #include <__config> -#include <__debug> -#include <__errc> -#include <__memory/addressof.h> -#include <__type_traits/make_32_64_or_128_bit.h> -#include <__utility/unreachable.h> +#include <__system_error/errc.h> #include <cmath> // for log2f #include <cstdint> -#include <cstdlib> -#include <cstring> #include <limits> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 - -to_chars_result to_chars(char*, char*, bool, int = 10) = delete; -from_chars_result from_chars(const char*, const char*, bool, int = 10) = delete; - -namespace __itoa -{ - -template <typename _Tp, typename = void> -struct _LIBCPP_HIDDEN __traits_base; - -template <typename _Tp> -struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) <= sizeof(uint32_t)>> -{ - using type = uint32_t; - - /// The width estimation using a log10 algorithm. - /// - /// The algorithm is based on - /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 - /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that - /// function requires its input to have at least one bit set the value of - /// zero is set to one. This means the first element of the lookup table is - /// zero. - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) - { - auto __t = (32 - std::__libcpp_clz(static_cast<type>(__v | 1))) * 1233 >> 12; - return __t - (__v < __itoa::__pow10_32[__t]) + 1; - } - - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) - { - return __itoa::__base_10_u32(__p, __v); - } - - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_32)& __pow() { return __itoa::__pow10_32; } -}; - -template <typename _Tp> -struct _LIBCPP_HIDDEN - __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(uint64_t)>> { - using type = uint64_t; - - /// The width estimation using a log10 algorithm. - /// - /// The algorithm is based on - /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 - /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that - /// function requires its input to have at least one bit set the value of - /// zero is set to one. This means the first element of the lookup table is - /// zero. - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { - auto __t = (64 - std::__libcpp_clz(static_cast<type>(__v | 1))) * 1233 >> 12; - return __t - (__v < __itoa::__pow10_64[__t]) + 1; - } - - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { return __itoa::__base_10_u64(__p, __v); } - - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_64)& __pow() { return __itoa::__pow10_64; } -}; - - -# ifndef _LIBCPP_HAS_NO_INT128 -template <typename _Tp> -struct _LIBCPP_HIDDEN - __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(__uint128_t)> > { - using type = __uint128_t; - - /// The width estimation using a log10 algorithm. - /// - /// The algorithm is based on - /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 - /// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that - /// function requires its input to have at least one bit set the value of - /// zero is set to one. This means the first element of the lookup table is - /// zero. - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) { - _LIBCPP_ASSERT(__v > numeric_limits<uint64_t>::max(), "The optimizations for this algorithm fail when this isn't true."); - // There's always a bit set in the upper 64-bits. - auto __t = (128 - std::__libcpp_clz(static_cast<uint64_t>(__v >> 64))) * 1233 >> 12; - _LIBCPP_ASSERT(__t >= __itoa::__pow10_128_offset, "Index out of bounds"); - // __t is adjusted since the lookup table misses the lower entries. - return __t - (__v < __itoa::__pow10_128[__t - __itoa::__pow10_128_offset]) + 1; - } - - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __convert(char* __p, _Tp __v) { return __itoa::__base_10_u128(__p, __v); } - - // TODO FMT This pow function should get an index. - // By moving this to its own header it can be reused by the pow function in to_chars_base_10. - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI decltype(__pow10_128)& __pow() { return __itoa::__pow10_128; } -}; -#endif - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool -__mul_overflowed(unsigned char __a, _Tp __b, unsigned char& __r) -{ - auto __c = __a * __b; - __r = __c; - return __c > numeric_limits<unsigned char>::max(); -} - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool -__mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) -{ - auto __c = __a * __b; - __r = __c; - return __c > numeric_limits<unsigned short>::max(); -} - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool -__mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) -{ - static_assert(is_unsigned<_Tp>::value, ""); - return __builtin_mul_overflow(__a, __b, &__r); -} - -template <typename _Tp, typename _Up> -inline _LIBCPP_HIDE_FROM_ABI bool -_LIBCPP_CONSTEXPR_SINCE_CXX23 __mul_overflowed(_Tp __a, _Up __b, _Tp& __r) -{ - return __itoa::__mul_overflowed(__a, static_cast<_Tp>(__b), __r); -} - -template <typename _Tp> -struct _LIBCPP_HIDDEN __traits : __traits_base<_Tp> -{ - static constexpr int digits = numeric_limits<_Tp>::digits10 + 1; - using __traits_base<_Tp>::__pow; - using typename __traits_base<_Tp>::type; - - // precondition: at least one non-zero character available - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char const* - __read(char const* __p, char const* __ep, type& __a, type& __b) - { - type __cprod[digits]; - int __j = digits - 1; - int __i = digits; - do - { - if (*__p < '0' || *__p > '9') - break; - __cprod[--__i] = *__p++ - '0'; - } while (__p != __ep && __i != 0); - - __a = __inner_product(__cprod + __i + 1, __cprod + __j, __pow() + 1, - __cprod[__i]); - if (__itoa::__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b)) - --__p; - return __p; - } - - template <typename _It1, typename _It2, class _Up> - static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Up - __inner_product(_It1 __first1, _It1 __last1, _It2 __first2, _Up __init) - { - for (; __first1 < __last1; ++__first1, ++__first2) - __init = __init + *__first1 * *__first2; - return __init; - } -}; - -} // namespace __itoa - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Tp -__complement(_Tp __x) -{ - static_assert(is_unsigned<_Tp>::value, "cast to unsigned first"); - return _Tp(~__x + 1); -} - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type); - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) -{ - auto __x = std::__to_unsigned_like(__value); - if (__value < 0 && __first != __last) - { - *__first++ = '-'; - __x = std::__complement(__x); - } - - return std::__to_chars_itoa(__first, __last, __x, false_type()); -} - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) -{ - using __tx = __itoa::__traits<_Tp>; - auto __diff = __last - __first; - - if (__tx::digits <= __diff || __tx::__width(__value) <= __diff) - return {__tx::__convert(__first, __value), errc(0)}; - else - return {__last, errc::value_too_large}; -} - -# ifndef _LIBCPP_HAS_NO_INT128 -template <> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) -{ - // When the value fits in 64-bits use the 64-bit code path. This reduces - // the number of expensive calculations on 128-bit values. - // - // NOTE the 128-bit code path requires this optimization. - if(__value <= numeric_limits<uint64_t>::max()) - return __to_chars_itoa(__first, __last, static_cast<uint64_t>(__value), false_type()); - - using __tx = __itoa::__traits<__uint128_t>; - auto __diff = __last - __first; - - if (__tx::digits <= __diff || __tx::__width(__value) <= __diff) - return {__tx::__convert(__first, __value), errc(0)}; - else - return {__last, errc::value_too_large}; -} -#endif - -template <class _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type); - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, - true_type) -{ - auto __x = std::__to_unsigned_like(__value); - if (__value < 0 && __first != __last) - { - *__first++ = '-'; - __x = std::__complement(__x); - } - - return std::__to_chars_integral(__first, __last, __x, __base, false_type()); -} - -namespace __itoa { - -template <unsigned _Base> -struct _LIBCPP_HIDDEN __integral; - -template <> -struct _LIBCPP_HIDDEN __integral<2> { - template <typename _Tp> - _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept { - // If value == 0 still need one digit. If the value != this has no - // effect since the code scans for the most significant bit set. (Note - // that __libcpp_clz doesn't work for 0.) - return numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1); - } - - template <typename _Tp> - _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result __to_chars(char* __first, char* __last, _Tp __value) { - ptrdiff_t __cap = __last - __first; - int __n = __width(__value); - if (__n > __cap) - return {__last, errc::value_too_large}; - - __last = __first + __n; - char* __p = __last; - const unsigned __divisor = 16; - while (__value > __divisor) { - unsigned __c = __value % __divisor; - __value /= __divisor; - __p -= 4; - std::copy_n(&__base_2_lut[4 * __c], 4, __p); - } - do { - unsigned __c = __value % 2; - __value /= 2; - *--__p = "01"[__c]; - } while (__value != 0); - return {__last, errc(0)}; - } -}; - -template <> -struct _LIBCPP_HIDDEN __integral<8> { - template <typename _Tp> - _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept { - // If value == 0 still need one digit. If the value != this has no - // effect since the code scans for the most significat bit set. (Note - // that __libcpp_clz doesn't work for 0.) - return ((numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1)) + 2) / 3; - } - - template <typename _Tp> - _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result __to_chars(char* __first, char* __last, _Tp __value) { - ptrdiff_t __cap = __last - __first; - int __n = __width(__value); - if (__n > __cap) - return {__last, errc::value_too_large}; - - __last = __first + __n; - char* __p = __last; - unsigned __divisor = 64; - while (__value > __divisor) { - unsigned __c = __value % __divisor; - __value /= __divisor; - __p -= 2; - std::copy_n(&__base_8_lut[2 * __c], 2, __p); - } - do { - unsigned __c = __value % 8; - __value /= 8; - *--__p = "01234567"[__c]; - } while (__value != 0); - return {__last, errc(0)}; - } - -}; - -template <> -struct _LIBCPP_HIDDEN __integral<16> { - template <typename _Tp> - _LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept { - // If value == 0 still need one digit. If the value != this has no - // effect since the code scans for the most significat bit set. (Note - // that __libcpp_clz doesn't work for 0.) - return (numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1) + 3) / 4; - } - - template <typename _Tp> - _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result __to_chars(char* __first, char* __last, _Tp __value) { - ptrdiff_t __cap = __last - __first; - int __n = __width(__value); - if (__n > __cap) - return {__last, errc::value_too_large}; - - __last = __first + __n; - char* __p = __last; - unsigned __divisor = 256; - while (__value > __divisor) { - unsigned __c = __value % __divisor; - __value /= __divisor; - __p -= 2; - std::copy_n(&__base_16_lut[2 * __c], 2, __p); - } - if (__first != __last) - do { - unsigned __c = __value % 16; - __value /= 16; - *--__p = "0123456789abcdef"[__c]; - } while (__value != 0); - return {__last, errc(0)}; - } -}; - -} // namespace __itoa - -template <unsigned _Base, typename _Tp, - typename enable_if<(sizeof(_Tp) >= sizeof(unsigned)), int>::type = 0> -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int -__to_chars_integral_width(_Tp __value) { - return __itoa::__integral<_Base>::__width(__value); -} - -template <unsigned _Base, typename _Tp, - typename enable_if<(sizeof(_Tp) < sizeof(unsigned)), int>::type = 0> -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int -__to_chars_integral_width(_Tp __value) { - return std::__to_chars_integral_width<_Base>(static_cast<unsigned>(__value)); -} - -template <unsigned _Base, typename _Tp, - typename enable_if<(sizeof(_Tp) >= sizeof(unsigned)), int>::type = 0> -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_integral(char* __first, char* __last, _Tp __value) { - return __itoa::__integral<_Base>::__to_chars(__first, __last, __value); -} - -template <unsigned _Base, typename _Tp, - typename enable_if<(sizeof(_Tp) < sizeof(unsigned)), int>::type = 0> -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_integral(char* __first, char* __last, _Tp __value) { - return std::__to_chars_integral<_Base>(__first, __last, static_cast<unsigned>(__value)); -} - -template <typename _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int -__to_chars_integral_width(_Tp __value, unsigned __base) { - _LIBCPP_ASSERT(__value >= 0, "The function requires a non-negative value."); - - unsigned __base_2 = __base * __base; - unsigned __base_3 = __base_2 * __base; - unsigned __base_4 = __base_2 * __base_2; - - int __r = 0; - while (true) { - if (__value < __base) - return __r + 1; - if (__value < __base_2) - return __r + 2; - if (__value < __base_3) - return __r + 3; - if (__value < __base_4) - return __r + 4; - - __value /= __base_4; - __r += 4; - } - - __libcpp_unreachable(); -} - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, - false_type) -{ - if (__base == 10) [[likely]] - return std::__to_chars_itoa(__first, __last, __value, false_type()); - - switch (__base) { - case 2: - return std::__to_chars_integral<2>(__first, __last, __value); - case 8: - return std::__to_chars_integral<8>(__first, __last, __value); - case 16: - return std::__to_chars_integral<16>(__first, __last, __value); - } - - ptrdiff_t __cap = __last - __first; - int __n = std::__to_chars_integral_width(__value, __base); - if (__n > __cap) - return {__last, errc::value_too_large}; - - __last = __first + __n; - char* __p = __last; - do { - unsigned __c = __value % __base; - __value /= __base; - *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c]; - } while (__value != 0); - return {__last, errc(0)}; -} - -template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -to_chars(char* __first, char* __last, _Tp __value) -{ - using _Type = __make_32_64_or_128_bit_t<_Tp>; - static_assert(!is_same<_Type, void>::value, "unsupported integral type used in to_chars"); - return std::__to_chars_itoa(__first, __last, static_cast<_Type>(__value), is_signed<_Tp>()); -} - -template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result -to_chars(char* __first, char* __last, _Tp __value, int __base) -{ - _LIBCPP_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]"); - - using _Type = __make_32_64_or_128_bit_t<_Tp>; - return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base, is_signed<_Tp>()); -} - -template <typename _It, typename _Tp, typename _Fn, typename... _Ts> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result -__sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) -{ - using __tl = numeric_limits<_Tp>; - decltype(std::__to_unsigned_like(__value)) __x; - - bool __neg = (__first != __last && *__first == '-'); - auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...); - switch (__r.ec) - { - case errc::invalid_argument: - return {__first, __r.ec}; - case errc::result_out_of_range: - return __r; - default: - break; - } - - if (__neg) - { - if (__x <= std::__complement(std::__to_unsigned_like(__tl::min()))) - { - __x = std::__complement(__x); - std::copy_n(std::addressof(__x), 1, std::addressof(__value)); - return __r; - } - } - else - { - if (__x <= std::__to_unsigned_like(__tl::max())) - { - __value = __x; - return __r; - } - } - - return {__r.ptr, errc::result_out_of_range}; -} - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool -__in_pattern(_Tp __c) -{ - return '0' <= __c && __c <= '9'; -} - -struct _LIBCPP_HIDDEN __in_pattern_result -{ - bool __ok; - int __val; - - explicit _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI operator bool() const { return __ok; } -}; - -template <typename _Tp> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __in_pattern_result -__in_pattern(_Tp __c, int __base) -{ - if (__base <= 10) - return {'0' <= __c && __c < '0' + __base, __c - '0'}; - else if (std::__in_pattern(__c)) - return {true, __c - '0'}; - else if ('a' <= __c && __c < 'a' + __base - 10) - return {true, __c - 'a' + 10}; - else - return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10}; -} - -template <typename _It, typename _Tp, typename _Fn, typename... _Ts> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result -__subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, - _Ts... __args) -{ - auto __find_non_zero = [](_It __firstit, _It __lastit) { - for (; __firstit != __lastit; ++__firstit) - if (*__firstit != '0') - break; - return __firstit; - }; - - auto __p = __find_non_zero(__first, __last); - if (__p == __last || !std::__in_pattern(*__p, __args...)) - { - if (__p == __first) - return {__first, errc::invalid_argument}; - else - { - __value = 0; - return {__p, {}}; - } - } - - auto __r = __f(__p, __last, __value, __args...); - if (__r.ec == errc::result_out_of_range) - { - for (; __r.ptr != __last; ++__r.ptr) - { - if (!std::__in_pattern(*__r.ptr, __args...)) - break; - } - } - - return __r; -} - -template <typename _Tp, typename enable_if<is_unsigned<_Tp>::value, int>::type = 0> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result -__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) -{ - using __tx = __itoa::__traits<_Tp>; - using __output_type = typename __tx::type; - - return std::__subject_seq_combinator( - __first, __last, __value, - [](const char* __f, const char* __l, - _Tp& __val) -> from_chars_result { - __output_type __a, __b; - auto __p = __tx::__read(__f, __l, __a, __b); - if (__p == __l || !std::__in_pattern(*__p)) - { - __output_type __m = numeric_limits<_Tp>::max(); - if (__m >= __a && __m - __a >= __b) - { - __val = __a + __b; - return {__p, {}}; - } - } - return {__p, errc::result_out_of_range}; - }); -} - -template <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result -__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) -{ - using __t = decltype(std::__to_unsigned_like(__value)); - return std::__sign_combinator(__first, __last, __value, __from_chars_atoi<__t>); -} - - -/* -// Code used to generate __from_chars_log2f_lut. -#include <cmath> -#include <iostream> -#include <format> - -int main() { - for (int i = 2; i <= 36; ++i) - std::cout << std::format("{},\n", log2f(i)); -} -*/ -/// log2f table for bases [2, 36]. -inline constexpr float __from_chars_log2f_lut[35] = { - 1, 1.5849625, 2, 2.321928, 2.5849626, 2.807355, 3, 3.169925, 3.321928, - 3.4594316, 3.5849626, 3.7004397, 3.807355, 3.9068906, 4, 4.087463, 4.169925, 4.2479277, - 4.321928, 4.3923173, 4.4594316, 4.523562, 4.5849624, 4.643856, 4.70044, 4.7548876, 4.807355, - 4.857981, 4.9068904, 4.9541965, 5, 5.044394, 5.087463, 5.129283, 5.169925}; - -template <typename _Tp, typename enable_if<is_unsigned<_Tp>::value, int>::type = 0> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result -__from_chars_integral(const char* __first, const char* __last, _Tp& __value, - int __base) -{ - if (__base == 10) - return std::__from_chars_atoi(__first, __last, __value); - - return std::__subject_seq_combinator( - __first, __last, __value, - [](const char* __p, const char* __lastp, _Tp& __val, - int __b) -> from_chars_result { - using __tl = numeric_limits<_Tp>; - // __base is always between 2 and 36 inclusive. - auto __digits = __tl::digits / __from_chars_log2f_lut[__b - 2]; - _Tp __x = __in_pattern(*__p++, __b).__val, __y = 0; - - for (int __i = 1; __p != __lastp; ++__i, ++__p) - { - if (auto __c = __in_pattern(*__p, __b)) - { - if (__i < __digits - 1) - __x = __x * __b + __c.__val; - else - { - if (!__itoa::__mul_overflowed(__x, __b, __x)) - ++__p; - __y = __c.__val; - break; - } - } - else - break; - } - - if (__p == __lastp || !__in_pattern(*__p, __b)) - { - if (__tl::max() - __x >= __y) - { - __val = __x + __y; - return {__p, {}}; - } - } - return {__p, errc::result_out_of_range}; - }, - __base); -} - -template <typename _Tp, typename enable_if<is_signed<_Tp>::value, int>::type = 0> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result -__from_chars_integral(const char* __first, const char* __last, _Tp& __value, - int __base) -{ - using __t = decltype(std::__to_unsigned_like(__value)); - return std::__sign_combinator(__first, __last, __value, - __from_chars_integral<__t>, __base); -} - -template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result -from_chars(const char* __first, const char* __last, _Tp& __value) -{ - return std::__from_chars_atoi(__first, __last, __value); -} - -template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0> -inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result -from_chars(const char* __first, const char* __last, _Tp& __value, int __base) -{ - _LIBCPP_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]"); - return std::__from_chars_integral(__first, __last, __value, __base); -} - -_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS -to_chars_result to_chars(char* __first, char* __last, float __value); - -_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS -to_chars_result to_chars(char* __first, char* __last, double __value); - -_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS -to_chars_result to_chars(char* __first, char* __last, long double __value); - -_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS -to_chars_result to_chars(char* __first, char* __last, float __value, chars_format __fmt); - -_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS -to_chars_result to_chars(char* __first, char* __last, double __value, chars_format __fmt); - -_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS -to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt); - -_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS -to_chars_result to_chars(char* __first, char* __last, float __value, chars_format __fmt, int __precision); - -_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS -to_chars_result to_chars(char* __first, char* __last, double __value, chars_format __fmt, int __precision); - -_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_FUNC_VIS -to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision); - -#endif // _LIBCPP_STD_VER > 14 - _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> +# include <cstdlib> +# include <cstring> # include <iosfwd> +# include <type_traits> #endif #endif // _LIBCPP_CHARCONV diff --git a/libcxx/include/chrono b/libcxx/include/chrono index 44073b557ba1..4fbb9bfd5ca7 100644 --- a/libcxx/include/chrono +++ b/libcxx/include/chrono @@ -182,7 +182,7 @@ template <class Rep1, class Period1, class Rep2, class Period2> bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr - bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); + bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); // removed in C++20 template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); @@ -195,6 +195,10 @@ template <class Rep1, class Period1, class Rep2, class Period2> template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); +template<class Rep1, class Period1, class Rep2, class Period2> + requires three_way_comparable<typename CT::rep> + constexpr auto operator<=>(const duration<Rep1, Period1>& lhs, + const duration<Rep2, Period2>& rhs); // since C++20 // duration_cast template <class ToDuration, class Rep, class Period> @@ -231,7 +235,7 @@ template <class Clock, class Duration1, class Duration2> template <class Clock, class Duration1, class Duration2> bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template <class Clock, class Duration1, class Duration2> - bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); + bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); // removed in C++20 template <class Clock, class Duration1, class Duration2> bool operator< (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template <class Clock, class Duration1, class Duration2> @@ -240,6 +244,10 @@ template <class Clock, class Duration1, class Duration2> bool operator> (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template <class Clock, class Duration1, class Duration2> bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); +template<class Clock, class Duration1, + three_way_comparable_with<Duration1> Duration2> + constexpr auto operator<=>(const time_point<Clock, Duration1>& lhs, + const time_point<Clock, Duration2>& rhs); // since C++20 // time_point_cast (constexpr in C++14) @@ -282,6 +290,10 @@ template <class Duration> using sys_seconds = sys_time<seconds>; // C++20 using sys_days = sys_time<days>; // C++20 +template<class charT, class traits, class Duration> // C++20 + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const sys_time<Duration>& tp); + class file_clock // C++20 { public: @@ -303,6 +315,10 @@ public: template<class Duration> using file_time = time_point<file_clock, Duration>; // C++20 +template<class charT, class traits, class Duration> // C++20 + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const file_time<Duration>& tp); + class steady_clock { public: @@ -324,6 +340,10 @@ template<class Duration> using local_seconds = local_time<seconds>; using local_days = local_time<days>; +template<class charT, class traits, class Duration> // C++20 + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const local_time<Duration>& tp); + // 25.8.2, class last_spec // C++20 struct last_spec; @@ -370,7 +390,6 @@ template<class charT, class traits> class weekday; constexpr bool operator==(const weekday& x, const weekday& y) noexcept; -constexpr bool operator!=(const weekday& x, const weekday& y) noexcept; constexpr weekday operator+(const weekday& x, const days& y) noexcept; constexpr weekday operator+(const days& x, const weekday& y) noexcept; constexpr weekday operator-(const weekday& x, const days& y) noexcept; @@ -383,7 +402,6 @@ template<class charT, class traits> class weekday_indexed; constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; -constexpr bool operator!=(const weekday_indexed& x, const weekday_indexed& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& @@ -393,7 +411,6 @@ template<class charT, class traits> class weekday_last; constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; -constexpr bool operator!=(const weekday_last& x, const weekday_last& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& @@ -423,7 +440,6 @@ template<class charT, class traits> class month_weekday; constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; -constexpr bool operator!=(const month_weekday& x, const month_weekday& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& @@ -433,7 +449,6 @@ template<class charT, class traits> class month_weekday_last; constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; -constexpr bool operator!=(const month_weekday_last& x, const month_weekday_last& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& @@ -503,8 +518,6 @@ class year_month_weekday; constexpr bool operator==(const year_month_weekday& x, const year_month_weekday& y) noexcept; -constexpr bool operator!=(const year_month_weekday& x, - const year_month_weekday& y) noexcept; constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) noexcept; @@ -528,8 +541,6 @@ class year_month_weekday_last; constexpr bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept; -constexpr bool operator!=(const year_month_weekday_last& x, - const year_month_weekday_last& y) noexcept; constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept; constexpr year_month_weekday_last @@ -656,6 +667,10 @@ public: constexpr precision to_duration() const noexcept; }; +template<class charT, class traits, class Duration> + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, const hh_mm_ss<Duration>& hms); // C++20 + // 26.10, 12/24 hour functions constexpr bool is_am(hours const& h) noexcept; constexpr bool is_pm(hours const& h) noexcept; @@ -674,6 +689,12 @@ bool operator>=(const time_zone& x, const time_zone& y) noexcept; } // chrono namespace std { + template<class Duration, class charT> + struct formatter<chrono::sys_time<Duration>, charT>; // C++20 + template<class Duration, class charT> + struct formatter<chrono::filetime<Duration>, charT>; // C++20 + template<class Duration, class charT> + struct formatter<chrono::local_time<Duration>, charT>; // C++20 template<class Rep, class Period, class charT> struct formatter<chrono::duration<Rep, Period>, charT>; // C++20 template<class charT> struct formatter<chrono::day, charT>; // C++20 @@ -691,6 +712,8 @@ namespace std { template<class charT> struct formatter<chrono::year_month_day_last, charT>; // C++20 template<class charT> struct formatter<chrono::year_month_weekday, charT>; // C++20 template<class charT> struct formatter<chrono::year_month_weekday_last, charT>; // C++20 + template<class Rep, class Period, class charT> + struct formatter<chrono::hh_mm_ss<duration<Rep, Period>>, charT>; // C++20 } // namespace std namespace chrono { @@ -769,7 +792,7 @@ constexpr chrono::year operator ""y(unsigned lo // [time.syn] #include <compare> -#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) && _LIBCPP_STD_VER > 17 +#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) && _LIBCPP_STD_VER >= 20 # include <__chrono/formatter.h> # include <__chrono/ostream.h> # include <__chrono/parser_std_format_spec.h> @@ -782,7 +805,13 @@ constexpr chrono::year operator ""y(unsigned lo #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <bit> # include <concepts> +# include <cstring> +#endif + +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER == 20 +# include <charconv> #endif #endif // _LIBCPP_CHRONO diff --git a/libcxx/include/cmath b/libcxx/include/cmath index a27d0ebceb35..e815b3a4ef2e 100644 --- a/libcxx/include/cmath +++ b/libcxx/include/cmath @@ -311,6 +311,7 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept #include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_floating_point.h> #include <__type_traits/is_same.h> +#include <__type_traits/promote.h> #include <__type_traits/remove_cv.h> #include <version> @@ -543,7 +544,7 @@ using ::scalbnl _LIBCPP_USING_IF_EXISTS; using ::tgammal _LIBCPP_USING_IF_EXISTS; using ::truncl _LIBCPP_USING_IF_EXISTS; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 inline _LIBCPP_INLINE_VISIBILITY float hypot( float __x, float __y, float __z ) { return sqrt(__x*__x + __y*__y + __z*__z); } inline _LIBCPP_INLINE_VISIBILITY double hypot( double __x, double __y, double __z ) { return sqrt(__x*__x + __y*__y + __z*__z); } inline _LIBCPP_INLINE_VISIBILITY long double hypot( long double __x, long double __y, long double __z ) { return sqrt(__x*__x + __y*__y + __z*__z); } @@ -782,7 +783,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp _ return __builtin_scalbn(__x, __exp); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <typename _Fp> _LIBCPP_HIDE_FROM_ABI constexpr _Fp __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept { @@ -823,7 +824,7 @@ lerp(_A1 __a, _A2 __b, _A3 __t) noexcept _IsSame<_A3, __result_type>::value)); return std::__lerp((__result_type)__a, (__result_type)__b, (__result_type)__t); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/codecvt b/libcxx/include/codecvt index ce378c8d1c6b..ef22bf053063 100644 --- a/libcxx/include/codecvt +++ b/libcxx/include/codecvt @@ -78,7 +78,7 @@ template <class _Elem> class __codecvt_utf8; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS __codecvt_utf8<wchar_t> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf8<wchar_t> : public codecvt<wchar_t, char, mbstate_t> { unsigned long __maxcode_; @@ -115,7 +115,7 @@ protected: _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -class _LIBCPP_TYPE_VIS __codecvt_utf8<char16_t> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf8<char16_t> : public codecvt<char16_t, char, mbstate_t> { unsigned long __maxcode_; @@ -149,7 +149,7 @@ protected: _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -class _LIBCPP_TYPE_VIS __codecvt_utf8<char32_t> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf8<char32_t> : public codecvt<char32_t, char, mbstate_t> { unsigned long __maxcode_; @@ -203,7 +203,7 @@ template <class _Elem, bool _LittleEndian> class __codecvt_utf16; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS __codecvt_utf16<wchar_t, false> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf16<wchar_t, false> : public codecvt<wchar_t, char, mbstate_t> { unsigned long __maxcode_; @@ -239,7 +239,7 @@ protected: }; template <> -class _LIBCPP_TYPE_VIS __codecvt_utf16<wchar_t, true> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf16<wchar_t, true> : public codecvt<wchar_t, char, mbstate_t> { unsigned long __maxcode_; @@ -276,7 +276,7 @@ protected: _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -class _LIBCPP_TYPE_VIS __codecvt_utf16<char16_t, false> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf16<char16_t, false> : public codecvt<char16_t, char, mbstate_t> { unsigned long __maxcode_; @@ -310,7 +310,7 @@ protected: _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -class _LIBCPP_TYPE_VIS __codecvt_utf16<char16_t, true> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf16<char16_t, true> : public codecvt<char16_t, char, mbstate_t> { unsigned long __maxcode_; @@ -344,7 +344,7 @@ protected: _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -class _LIBCPP_TYPE_VIS __codecvt_utf16<char32_t, false> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf16<char32_t, false> : public codecvt<char32_t, char, mbstate_t> { unsigned long __maxcode_; @@ -378,7 +378,7 @@ protected: _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -class _LIBCPP_TYPE_VIS __codecvt_utf16<char32_t, true> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf16<char32_t, true> : public codecvt<char32_t, char, mbstate_t> { unsigned long __maxcode_; @@ -432,7 +432,7 @@ template <class _Elem> class __codecvt_utf8_utf16; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <> -class _LIBCPP_TYPE_VIS __codecvt_utf8_utf16<wchar_t> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf8_utf16<wchar_t> : public codecvt<wchar_t, char, mbstate_t> { unsigned long __maxcode_; @@ -469,7 +469,7 @@ protected: _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -class _LIBCPP_TYPE_VIS __codecvt_utf8_utf16<char32_t> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf8_utf16<char32_t> : public codecvt<char32_t, char, mbstate_t> { unsigned long __maxcode_; @@ -503,7 +503,7 @@ protected: _LIBCPP_SUPPRESS_DEPRECATED_PUSH template <> -class _LIBCPP_TYPE_VIS __codecvt_utf8_utf16<char16_t> +class _LIBCPP_EXPORTED_FROM_ABI __codecvt_utf8_utf16<char16_t> : public codecvt<char16_t, char, mbstate_t> { unsigned long __maxcode_; diff --git a/libcxx/include/compare b/libcxx/include/compare index 9272dbf62b14..626c7435f5fd 100644 --- a/libcxx/include/compare +++ b/libcxx/include/compare @@ -151,6 +151,7 @@ namespace std { #include <__compare/ordering.h> #include <__compare/partial_order.h> #include <__compare/strong_order.h> +#include <__compare/synth_three_way.h> #include <__compare/three_way_comparable.h> #include <__compare/weak_order.h> #include <__config> diff --git a/libcxx/include/complex b/libcxx/include/complex index 760fbaa81128..d12cfa938dc3 100644 --- a/libcxx/include/complex +++ b/libcxx/include/complex @@ -148,12 +148,12 @@ template<class T> complex<T> operator/(const complex<T>&, const T&); // template<class T> complex<T> operator/(const T&, const complex<T>&); // constexpr in C++20 template<class T> complex<T> operator+(const complex<T>&); // constexpr in C++20 template<class T> complex<T> operator-(const complex<T>&); // constexpr in C++20 -template<class T> bool operator==(const complex<T>&, const complex<T>&); // constexpr in C++14 -template<class T> bool operator==(const complex<T>&, const T&); // constexpr in C++14 -template<class T> bool operator==(const T&, const complex<T>&); // constexpr in C++14 -template<class T> bool operator!=(const complex<T>&, const complex<T>&); // constexpr in C++14 -template<class T> bool operator!=(const complex<T>&, const T&); // constexpr in C++14 -template<class T> bool operator!=(const T&, const complex<T>&); // constexpr in C++14 +template<class T> bool operator==(const complex<T>&, const complex<T>&); // constexpr in C++14 +template<class T> bool operator==(const complex<T>&, const T&); // constexpr in C++14 +template<class T> bool operator==(const T&, const complex<T>&); // constexpr in C++14, removed in C++20 +template<class T> bool operator!=(const complex<T>&, const complex<T>&); // constexpr in C++14, removed in C++20 +template<class T> bool operator!=(const complex<T>&, const T&); // constexpr in C++14, removed in C++20 +template<class T> bool operator!=(const T&, const complex<T>&); // constexpr in C++14, removed in C++20 template<class T, class charT, class traits> basic_istream<charT, traits>& @@ -236,7 +236,6 @@ template<class T> complex<T> tanh (const complex<T>&); #include <cmath> #include <iosfwd> #include <stdexcept> -#include <type_traits> #include <version> #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) @@ -828,6 +827,8 @@ operator==(const complex<_Tp>& __x, const _Tp& __y) return __x.real() == __y && __x.imag() == 0; } +#if _LIBCPP_STD_VER <= 17 + template<class _Tp> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 bool @@ -860,6 +861,8 @@ operator!=(const _Tp& __x, const complex<_Tp>& __y) return !(__x == __y); } +#endif + // 26.3.7 values: template <class _Tp, bool = is_integral<_Tp>::value, @@ -1522,7 +1525,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x) } #endif // !_LIBCPP_HAS_NO_LOCALIZATION -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 // Literal suffix for complex number literals [complex.literals] inline namespace literals { @@ -1565,4 +1568,8 @@ inline namespace literals _LIBCPP_END_NAMESPACE_STD +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> +#endif + #endif // _LIBCPP_COMPLEX diff --git a/libcxx/include/condition_variable b/libcxx/include/condition_variable index f13df1c012fa..ac44eb324816 100644 --- a/libcxx/include/condition_variable +++ b/libcxx/include/condition_variable @@ -107,10 +107,18 @@ public: */ #include <__assert> // all public C++ headers provide the assertion handler +#include <__chrono/duration.h> +#include <__chrono/steady_clock.h> +#include <__chrono/time_point.h> +#include <__condition_variable/condition_variable.h> #include <__config> #include <__memory/shared_ptr.h> #include <__memory/unique_ptr.h> -#include <__mutex_base> +#include <__mutex/lock_guard.h> +#include <__mutex/mutex.h> +#include <__mutex/tag_types.h> +#include <__mutex/unique_lock.h> +#include <__utility/move.h> #include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -121,7 +129,7 @@ public: _LIBCPP_BEGIN_NAMESPACE_STD -class _LIBCPP_TYPE_VIS condition_variable_any +class _LIBCPP_EXPORTED_FROM_ABI condition_variable_any { condition_variable __cv_; shared_ptr<mutex> __mut_; @@ -191,7 +199,7 @@ condition_variable_any::notify_all() _NOEXCEPT struct __lock_external { template <class _Lock> - void operator()(_Lock* __m) {__m->lock();} + _LIBCPP_HIDE_FROM_ABI void operator()(_Lock* __m) {__m->lock();} }; template <class _Lock> @@ -202,7 +210,7 @@ condition_variable_any::wait(_Lock& __lock) unique_lock<mutex> __lk(*__mut); __lock.unlock(); unique_ptr<_Lock, __lock_external> __lxx(&__lock); - lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock); + lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t()); __cv_.wait(__lk); } // __mut_.unlock(), __lock.lock() @@ -224,7 +232,7 @@ condition_variable_any::wait_until(_Lock& __lock, unique_lock<mutex> __lk(*__mut); __lock.unlock(); unique_ptr<_Lock, __lock_external> __lxx(&__lock); - lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock); + lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t()); return __cv_.wait_until(__lk, __t); } // __mut_.unlock(), __lock.lock() @@ -261,16 +269,24 @@ condition_variable_any::wait_for(_Lock& __lock, _VSTD::move(__pred)); } -_LIBCPP_FUNC_VIS -void notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>); +_LIBCPP_EXPORTED_FROM_ABI void notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>); _LIBCPP_END_NAMESPACE_STD #endif // !_LIBCPP_HAS_NO_THREADS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <atomic> # include <concepts> +# include <cstdint> +# include <cstdlib> +# include <cstring> +# include <initializer_list> +# include <new> +# include <stdexcept> +# include <system_error> # include <type_traits> +# include <typeinfo> #endif #endif // _LIBCPP_CONDITION_VARIABLE diff --git a/libcxx/include/cstddef b/libcxx/include/cstddef index e3c066917570..a364e6e55175 100644 --- a/libcxx/include/cstddef +++ b/libcxx/include/cstddef @@ -66,7 +66,7 @@ using ::max_align_t _LIBCPP_USING_IF_EXISTS; _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 namespace std // purposefully not versioned { enum class byte : unsigned char {}; diff --git a/libcxx/include/cstdlib b/libcxx/include/cstdlib index 25c9de5165c2..ab2c159c7259 100644 --- a/libcxx/include/cstdlib +++ b/libcxx/include/cstdlib @@ -144,7 +144,7 @@ using ::wcstombs _LIBCPP_USING_IF_EXISTS; using ::at_quick_exit _LIBCPP_USING_IF_EXISTS; using ::quick_exit _LIBCPP_USING_IF_EXISTS; #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 using ::aligned_alloc _LIBCPP_USING_IF_EXISTS; #endif diff --git a/libcxx/include/cstring b/libcxx/include/cstring index c88d97739f74..a9bdf4ff2dfc 100644 --- a/libcxx/include/cstring +++ b/libcxx/include/cstring @@ -100,53 +100,6 @@ using ::memset _LIBCPP_USING_IF_EXISTS; using ::strerror _LIBCPP_USING_IF_EXISTS; using ::strlen _LIBCPP_USING_IF_EXISTS; -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const char* __str) { - // GCC currently doesn't support __builtin_strlen for heap-allocated memory during constant evaluation. - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816 -#ifdef _LIBCPP_COMPILER_GCC - if (__libcpp_is_constant_evaluated()) { - size_t __i = 0; - for (; __str[__i] != '\0'; ++__i) - ; - return __i; - } -#endif - return __builtin_strlen(__str); -} - -template <class _Tp> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int -__constexpr_memcmp(const _Tp* __lhs, const _Tp* __rhs, size_t __count) { -#ifdef _LIBCPP_COMPILER_GCC - if (__libcpp_is_constant_evaluated()) { - for (; __count; --__count, ++__lhs, ++__rhs) { - if (*__lhs < *__rhs) - return -1; - if (*__rhs < *__lhs) - return 1; - } - return 0; - } -#endif - return __builtin_memcmp(__lhs, __rhs, __count); -} - -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const char* -__constexpr_char_memchr(const char* __str, int __char, size_t __count) { -#if __has_builtin(__builtin_char_memchr) - return __builtin_char_memchr(__str, __char, __count); -#else - if (!__libcpp_is_constant_evaluated()) - return static_cast<const char*>(std::memchr(__str, __char, __count)); - for (; __count; --__count) { - if (*__str == __char) - return __str; - ++__str; - } - return nullptr; -#endif -} - _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_CSTRING diff --git a/libcxx/include/ctime b/libcxx/include/ctime index 2293675b4941..b61e19d6446d 100644 --- a/libcxx/include/ctime +++ b/libcxx/include/ctime @@ -66,7 +66,7 @@ using ::clock_t _LIBCPP_USING_IF_EXISTS; using ::size_t _LIBCPP_USING_IF_EXISTS; using ::time_t _LIBCPP_USING_IF_EXISTS; using ::tm _LIBCPP_USING_IF_EXISTS; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 using ::timespec _LIBCPP_USING_IF_EXISTS; #endif using ::clock _LIBCPP_USING_IF_EXISTS; @@ -78,7 +78,7 @@ using ::ctime _LIBCPP_USING_IF_EXISTS; using ::gmtime _LIBCPP_USING_IF_EXISTS; using ::localtime _LIBCPP_USING_IF_EXISTS; using ::strftime _LIBCPP_USING_IF_EXISTS; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 using ::timespec_get _LIBCPP_USING_IF_EXISTS; #endif diff --git a/libcxx/include/cwchar b/libcxx/include/cwchar index fb7b92b760af..122af242880e 100644 --- a/libcxx/include/cwchar +++ b/libcxx/include/cwchar @@ -104,7 +104,11 @@ size_t wcsrtombs(char* restrict dst, const wchar_t** restrict src, size_t len, #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__type_traits/apply_cv.h> #include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_equality_comparable.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cv.h> #include <cwctype> #include <wchar.h> @@ -222,21 +226,31 @@ __constexpr_wmemcmp(const wchar_t* __lhs, const wchar_t* __rhs, size_t __count) #endif } -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const wchar_t* -__constexpr_wmemchr(const wchar_t* __str, wchar_t __char, size_t __count) { -#if __has_feature(cxx_constexpr_string_builtins) - return __builtin_wmemchr(__str, __char, __count); -#else - if (!__libcpp_is_constant_evaluated()) - return std::wmemchr(__str, __char, __count); +template <class _Tp, class _Up> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __constexpr_wmemchr(_Tp* __str, _Up __value, size_t __count) { + static_assert(sizeof(_Tp) == sizeof(wchar_t)&& _LIBCPP_ALIGNOF(_Tp) >= _LIBCPP_ALIGNOF(wchar_t) && + __libcpp_is_trivially_equality_comparable<_Tp, _Tp>::value, + "Calling wmemchr on non-trivially equality comparable types is unsafe."); + +#if __has_builtin(__builtin_wmemchr) + if (!__libcpp_is_constant_evaluated()) { + wchar_t __value_buffer = 0; + __builtin_memcpy(&__value_buffer, &__value, sizeof(wchar_t)); + return reinterpret_cast<_Tp*>( + __builtin_wmemchr(reinterpret_cast<__apply_cv_t<_Tp, wchar_t>*>(__str), __value_buffer, __count)); + } +# if _LIBCPP_STD_VER >= 17 + else if constexpr (is_same_v<remove_cv_t<_Tp>, wchar_t>) + return __builtin_wmemchr(__str, __value, __count); +# endif +#endif // __has_builtin(__builtin_wmemchr) for (; __count; --__count) { - if (*__str == __char) + if (*__str == __value) return __str; ++__str; } return nullptr; -#endif } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/deque b/libcxx/include/deque index f2b8076c0af1..8ca59438db44 100644 --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -47,6 +47,8 @@ public: deque(InputIterator f, InputIterator l); template <class InputIterator> deque(InputIterator f, InputIterator l, const allocator_type& a); + template<container-compatible-range<T> R> + deque(from_range_t, R&& rg, const Allocator& = Allocator()); // C++23 deque(const deque& c); deque(deque&& c) noexcept(is_nothrow_move_constructible<allocator_type>::value); @@ -64,6 +66,8 @@ public: template <class InputIterator> void assign(InputIterator f, InputIterator l); + template<container-compatible-range<T> R> + void assign_range(R&& rg); // C++23 void assign(size_type n, const value_type& v); void assign(initializer_list<value_type> il); @@ -107,8 +111,12 @@ public: // modifiers: void push_front(const value_type& v); void push_front(value_type&& v); + template<container-compatible-range<T> R> + void prepend_range(R&& rg); // C++23 void push_back(const value_type& v); void push_back(value_type&& v); + template<container-compatible-range<T> R> + void append_range(R&& rg); // C++23 template <class... Args> reference emplace_front(Args&&... args); // reference in C++17 template <class... Args> reference emplace_back(Args&&... args); // reference in C++17 template <class... Args> iterator emplace(const_iterator p, Args&&... args); @@ -117,6 +125,8 @@ public: iterator insert(const_iterator p, size_type n, const value_type& v); template <class InputIterator> iterator insert(const_iterator p, InputIterator f, InputIterator l); + template<container-compatible-range<T> R> + iterator insert_range(const_iterator position, R&& rg); // C++23 iterator insert(const_iterator p, initializer_list<value_type> il); void pop_front(); void pop_back(); @@ -131,18 +141,25 @@ template <class InputIterator, class Allocator = allocator<typename iterator_tra deque(InputIterator, InputIterator, Allocator = Allocator()) -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>; // C++17 +template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> + deque(from_range_t, R&&, Allocator = Allocator()) + -> deque<ranges::range_value_t<R>, Allocator>; // C++23 + template <class T, class Allocator> bool operator==(const deque<T,Allocator>& x, const deque<T,Allocator>& y); template <class T, class Allocator> - bool operator< (const deque<T,Allocator>& x, const deque<T,Allocator>& y); + bool operator< (const deque<T,Allocator>& x, const deque<T,Allocator>& y); // removed in C++20 template <class T, class Allocator> - bool operator!=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); + bool operator!=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); // removed in C++20 template <class T, class Allocator> - bool operator> (const deque<T,Allocator>& x, const deque<T,Allocator>& y); + bool operator> (const deque<T,Allocator>& x, const deque<T,Allocator>& y); // removed in C++20 template <class T, class Allocator> - bool operator>=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); + bool operator>=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); // removed in C++20 template <class T, class Allocator> - bool operator<=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); + bool operator<=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); // removed in C++20 +template<class T, class Allocator> + synth-three-way-result<T> operator<=>(const deque<T, Allocator>& x, + const deque<T, Allocator>& y); // since C++20 // specialized algorithms: template <class T, class Allocator> @@ -162,34 +179,47 @@ template <class T, class Allocator, class Predicate> #include <__algorithm/copy.h> #include <__algorithm/copy_backward.h> +#include <__algorithm/copy_n.h> #include <__algorithm/equal.h> #include <__algorithm/fill_n.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/min.h> #include <__algorithm/remove.h> #include <__algorithm/remove_if.h> #include <__algorithm/unwrap_iter.h> #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> #include <__config> #include <__format/enable_insertable.h> +#include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> #include <__iterator/prev.h> #include <__iterator/reverse_iterator.h> #include <__iterator/segmented_iterator.h> +#include <__memory/addressof.h> #include <__memory/allocator_destructor.h> #include <__memory/pointer_traits.h> #include <__memory/temp_value.h> #include <__memory/unique_ptr.h> #include <__memory_resource/polymorphic_allocator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> +#include <__ranges/size.h> #include <__split_buffer> #include <__type_traits/is_allocator.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/type_identity.h> #include <__utility/forward.h> #include <__utility/move.h> +#include <__utility/pair.h> #include <__utility/swap.h> #include <limits> #include <stdexcept> -#include <type_traits> #include <version> // standard-mandated includes @@ -249,7 +279,7 @@ public: typedef _Reference reference; _LIBCPP_HIDE_FROM_ABI __deque_iterator() _NOEXCEPT -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 : __m_iter_(nullptr), __ptr_(nullptr) #endif {} @@ -451,6 +481,7 @@ public: using __map_alloc_traits = allocator_traits<__pointer_allocator>; using __map_pointer = typename __map_alloc_traits::pointer; using __map_const_pointer = typename allocator_traits<__const_pointer_allocator>::const_pointer; + using __map_const_iterator = typename __map::const_iterator; using reference = value_type&; using const_reference = const value_type&; @@ -550,10 +581,13 @@ public: // construct/copy/destroy: _LIBCPP_HIDE_FROM_ABI deque() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) - : __start_(0), __size_(0, __default_init_tag()) {} + : __start_(0), __size_(0, __default_init_tag()) { + __annotate_new(0); + } _LIBCPP_HIDE_FROM_ABI ~deque() { clear(); + __annotate_delete(); typename __map::iterator __i = __map_.begin(); typename __map::iterator __e = __map_.end(); for (; __i != __e; ++__i) @@ -561,10 +595,12 @@ public: } _LIBCPP_HIDE_FROM_ABI explicit deque(const allocator_type& __a) - : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) {} + : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { + __annotate_new(0); + } explicit _LIBCPP_HIDE_FROM_ABI deque(size_type __n); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 explicit _LIBCPP_HIDE_FROM_ABI deque(size_type __n, const _Allocator& __a); #endif _LIBCPP_HIDE_FROM_ABI deque(size_type __n, const value_type& __v); @@ -573,16 +609,34 @@ public: _LIBCPP_HIDE_FROM_ABI deque(size_type __n, const value_type& __v, const allocator_type& __a) : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { + __annotate_new(0); if (__n > 0) __append(__n, __v); } template <class _InputIter> _LIBCPP_HIDE_FROM_ABI deque(_InputIter __f, _InputIter __l, - typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type* = 0); + typename enable_if<__has_input_iterator_category<_InputIter>::value>::type* = 0); template <class _InputIter> _LIBCPP_HIDE_FROM_ABI deque(_InputIter __f, _InputIter __l, const allocator_type& __a, - typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type* = 0); + typename enable_if<__has_input_iterator_category<_InputIter>::value>::type* = 0); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI deque(from_range_t, _Range&& __range, + const allocator_type& __a = allocator_type()) + : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { + if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + __append_with_size(ranges::begin(__range), ranges::distance(__range)); + + } else { + for (auto&& __e : __range) { + emplace_back(std::forward<decltype(__e)>(__e)); + } + } + } +#endif + _LIBCPP_HIDE_FROM_ABI deque(const deque& __c); _LIBCPP_HIDE_FROM_ABI deque(const deque& __c, const __type_identity_t<allocator_type>& __a); @@ -610,11 +664,30 @@ public: template <class _InputIter> _LIBCPP_HIDE_FROM_ABI void assign(_InputIter __f, _InputIter __l, - typename enable_if<__is_cpp17_input_iterator<_InputIter>::value && - !__is_cpp17_random_access_iterator<_InputIter>::value>::type* = 0); + typename enable_if<__has_input_iterator_category<_InputIter>::value && + !__has_random_access_iterator_category<_InputIter>::value>::type* = 0); template <class _RAIter> _LIBCPP_HIDE_FROM_ABI void assign(_RAIter __f, _RAIter __l, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type* = 0); + typename enable_if<__has_random_access_iterator_category<_RAIter>::value>::type* = 0); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void assign_range(_Range&& __range) { + if constexpr (ranges::random_access_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + __assign_with_size_random_access(ranges::begin(__range), __n); + + } else if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + __assign_with_size(ranges::begin(__range), __n); + + } else { + __assign_with_sentinel(ranges::begin(__range), ranges::end(__range)); + } + } +#endif + _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const value_type& __v); _LIBCPP_HIDE_FROM_ABI @@ -713,7 +786,7 @@ public: _LIBCPP_HIDE_FROM_ABI void push_front(const value_type& __v); _LIBCPP_HIDE_FROM_ABI void push_back(const value_type& __v); #ifndef _LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class... _Args> _LIBCPP_HIDE_FROM_ABI reference emplace_front(_Args&&... __args); template <class... _Args> _LIBCPP_HIDE_FROM_ABI reference emplace_back (_Args&&... __args); #else @@ -724,6 +797,21 @@ public: _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __v); _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __v); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void prepend_range(_Range&& __range) { + insert_range(begin(), std::forward<_Range>(__range)); + } + + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void append_range(_Range&& __range) { + insert_range(end(), std::forward<_Range>(__range)); + } +#endif + _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, value_type&& __v); _LIBCPP_HIDE_FROM_ABI @@ -734,13 +822,31 @@ public: _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, size_type __n, const value_type& __v); template <class _InputIter> _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, _InputIter __f, _InputIter __l, - typename enable_if<__is_exactly_cpp17_input_iterator<_InputIter>::value>::type* = 0); + typename enable_if<__has_exactly_input_iterator_category<_InputIter>::value>::type* = 0); template <class _ForwardIterator> _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, _ForwardIterator __f, _ForwardIterator __l, - typename enable_if<__is_exactly_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0); + typename enable_if<__has_exactly_forward_iterator_category<_ForwardIterator>::value>::type* = 0); template <class _BiIter> _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, _BiIter __f, _BiIter __l, - typename enable_if<__is_cpp17_bidirectional_iterator<_BiIter>::value>::type* = 0); + typename enable_if<__has_bidirectional_iterator_category<_BiIter>::value>::type* = 0); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + iterator insert_range(const_iterator __position, _Range&& __range) { + if constexpr (ranges::bidirectional_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + return __insert_bidirectional(__position, ranges::begin(__range), ranges::end(__range), __n); + + } else if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + return __insert_with_size(__position, ranges::begin(__range), __n); + + } else { + return __insert_with_sentinel(__position, ranges::begin(__range), ranges::end(__range)); + } + } +#endif _LIBCPP_HIDE_FROM_ABI void pop_front(); _LIBCPP_HIDE_FROM_ABI void pop_back(); @@ -764,7 +870,7 @@ public: return false; if (__map_.size() >= size_type(-1) / __block_size) return false; - for (typename __map::const_iterator __i = __map_.begin(), __e = __map_.end(); + for (__map_const_iterator __i = __map_.begin(), __e = __map_.end(); __i != __e; ++__i) if (*__i == nullptr) return false; @@ -851,9 +957,264 @@ public: } private: + enum __asan_annotation_type { + __asan_unposion, + __asan_poison + }; + + enum __asan_annotation_place { + __asan_front_moved, + __asan_back_moved, + }; + +// The following functions are no-ops outside of AddressSanitizer mode. +// We call annotations for every allocator, unless explicitly disabled. +// +// To disable annotations for a particular allocator, change value of +// __asan_annotate_container_with_allocator to false. +// For more details, see the "Using libc++" documentation page or +// the documentation for __sanitizer_annotate_contiguous_container. +#if !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 1600 + // TODO LLVM18: Remove the special-casing + _LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container( + const void* __beg, + const void* __end, + const void* __old_con_beg, + const void* __old_con_end, + const void* __new_con_beg, + const void* __new_con_end) const { + if (__beg != nullptr && __asan_annotate_container_with_allocator<_Allocator>::value) + __sanitizer_annotate_double_ended_contiguous_container( + __beg, __end, __old_con_beg, __old_con_end, __new_con_beg, __new_con_end); + } +#else + _LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container( + const void*, const void*, const void*, const void*, const void*, const void*) const _NOEXCEPT {} +#endif // !defined(_LIBCPP_HAS_NO_ASAN) && _LIBCPP_CLANG_VER >= 1600 + + _LIBCPP_HIDE_FROM_ABI + void __annotate_from_to(size_type __beg, size_type __end, __asan_annotation_type __annotation_type, __asan_annotation_place __place) const _NOEXCEPT { + // __beg - index of the first item to annotate + // __end - index behind the last item to annotate (so last item + 1) + // __annotation_type - __asan_unposion or __asan_poison + // __place - __asan_front_moved or __asan_back_moved + // Note: All indexes in __map_ + if (__beg == __end) + return; + // __annotations_beg_map - first chunk which annotations we want to modify + // __annotations_end_map - last chunk which annotations we want to modify + // NOTE: if __end % __block_size == 0, __annotations_end_map points at the next block, which may not exist + __map_const_iterator __annotations_beg_map = __map_.begin() + __beg / __block_size; + __map_const_iterator __annotations_end_map = __map_.begin() + __end / __block_size; + + bool const __poisoning = __annotation_type == __asan_poison; + // __old_c_beg_index - index of the first element in old container + // __old_c_end_index - index of the end of old container (last + 1) + // Note: may be outside the area we are annotating + size_t __old_c_beg_index = (__poisoning && __place == __asan_front_moved) ? __beg : __start_; + size_t __old_c_end_index = (__poisoning && __place == __asan_back_moved) ? __end : __start_ + size(); + bool const __front = __place == __asan_front_moved; + + if (__poisoning && empty()) { + // Special case: we shouldn't trust __start_ + __old_c_beg_index = __beg; + __old_c_end_index = __end; + } + // __old_c_beg_map - memory block (chunk) with first element + // __old_c_end_map - memory block (chunk) with end of old container + // Note: if __old_c_end_index % __block_size == 0, __old_c_end_map points at the next block, + // which may not exist + __map_const_iterator __old_c_beg_map = __map_.begin() + __old_c_beg_index / __block_size; + __map_const_iterator __old_c_end_map = __map_.begin() + __old_c_end_index / __block_size; + + // One edge (front/end) of the container was moved and one was not modified. + // __new_edge_index - index of new edge + // __new_edge_map - memory block (chunk) with new edge, it always equals to + // __annotations_beg_map or __annotations_end_map + // __old_edge_map - memory block (chunk) with old edge, it always equals to + // __old_c_beg_map or __old_c_end_map + size_t __new_edge_index = (__poisoning ^ __front) ? __beg : __end; + __map_const_iterator __new_edge_map = __map_.begin() + __new_edge_index / __block_size; + __map_const_iterator __old_edge_map = __front ? __old_c_end_map : __old_c_beg_map; + + // We iterate over map pointers (chunks) and fully poison all memory blocks between the first and the last. + // First and last chunk may be partially poisoned. + // __annotate_end_map may point at not existing chunk, therefore we have to have a check for it. + for (__map_const_iterator __map_it = __annotations_beg_map; __map_it <= __annotations_end_map; ++__map_it) { + if (__map_it == __annotations_end_map && __end % __block_size == 0) + // Chunk may not exist, but nothing to do here anyway + break; + + // The beginning and the end of the current memory block + const void* __mem_beg = std::__to_address(*__map_it); + const void* __mem_end = std::__to_address(*__map_it + __block_size); + + // The beginning of memory-in-use in the memory block before container modification + const void* __old_beg = + (__map_it == __old_c_beg_map) ? std::__to_address(*__map_it + (__old_c_beg_index % __block_size)) : __mem_beg; + + // The end of memory-in-use in the memory block before container modification + const void* __old_end; + if (__map_it < __old_c_beg_map || __map_it > __old_c_end_map || (!__poisoning && empty())) + __old_end = __old_beg; + else + __old_end = (__map_it == __old_c_end_map) ? std::__to_address(*__map_it + (__old_c_end_index % __block_size)) + : __mem_end; + + // New edge of the container in current memory block + // If the edge is in a different chunk it points on corresponding end of the memory block + const void* __new_edge; + if (__map_it == __new_edge_map) + __new_edge = std::__to_address(*__map_it + (__new_edge_index % __block_size)); + else + __new_edge = (__poisoning ^ __front) ? __mem_beg : __mem_end; + + // Not modified edge of the container + // If the edge is in a different chunk it points on corresponding end of the memory block + const void* __old_edge; + if (__map_it == __old_edge_map) + __old_edge = __front ? __old_end : __old_beg; + else + __old_edge = __front ? __mem_end : __mem_beg; + + // __new_beg - the beginning of memory-in-use in the memory block after container modification + // __new_end - the end of memory-in-use in the memory block after container modification + const void* __new_beg = __front ? __new_edge : __old_edge; + const void* __new_end = __front ? __old_edge : __new_edge; + + __annotate_double_ended_contiguous_container(__mem_beg, __mem_end, __old_beg, __old_end, __new_beg, __new_end); + } + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_new(size_type __current_size) const _NOEXCEPT { + if (__current_size == 0) + __annotate_from_to(0, __map_.size() * __block_size, __asan_poison, __asan_back_moved); + else { + __annotate_from_to(0, __start_, __asan_poison, __asan_front_moved); + __annotate_from_to(__start_ + __current_size, __map_.size() * __block_size, __asan_poison, __asan_back_moved); + } + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_delete() const _NOEXCEPT { + if (empty()) { + for(size_t __i = 0; __i < __map_.size(); ++__i) { + __annotate_whole_block(__i, __asan_unposion); + } + } + else { + __annotate_from_to(0, __start_, __asan_unposion, __asan_front_moved); + __annotate_from_to(__start_ + size(), __map_.size() * __block_size, __asan_unposion, __asan_back_moved); + } + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_increase_front(size_type __n) const _NOEXCEPT { + __annotate_from_to(__start_ - __n, __start_, __asan_unposion, __asan_front_moved); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_increase_back(size_type __n) const _NOEXCEPT { + __annotate_from_to(__start_ + size(), __start_ + size() + __n, __asan_unposion, __asan_back_moved); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_shrink_front(size_type __old_size, size_type __old_start) const _NOEXCEPT { + __annotate_from_to(__old_start, __old_start + (__old_size - size()), __asan_poison, __asan_front_moved); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_shrink_back(size_type __old_size, size_type __old_start) const _NOEXCEPT { + __annotate_from_to(__old_start + size(), __old_start + __old_size, __asan_poison, __asan_back_moved); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_poison_block(const void *__beginning, const void *__end) const _NOEXCEPT { + __annotate_double_ended_contiguous_container(__beginning, __end, __beginning, __end, __end, __end); + } + + _LIBCPP_HIDE_FROM_ABI + void __annotate_whole_block(size_t __block_index, __asan_annotation_type __annotation_type) const _NOEXCEPT { + __map_const_iterator __block_it = __map_.begin() + __block_index; + const void* __block_start = std::__to_address(*__block_it); + const void* __block_end = std::__to_address(*__block_it + __block_size); + + if(__annotation_type == __asan_poison) + __annotate_poison_block(__block_start, __block_end); + else { + __annotate_double_ended_contiguous_container( + __block_start, __block_end, __block_start, __block_start, __block_start, __block_end); + } + } +#if !defined(_LIBCPP_HAS_NO_ASAN) + + public: + _LIBCPP_HIDE_FROM_ABI + bool __verify_asan_annotations() const _NOEXCEPT { + // This function tests deque object annotations. + if (empty()) { + for (__map_const_iterator __it = __map_.begin(); __it != __map_.end(); ++__it) { + if (!__sanitizer_verify_double_ended_contiguous_container( + std::__to_address(*__it), + std::__to_address(*__it), + std::__to_address(*__it), + std::__to_address(*__it + __block_size))) + return false; + } + + return true; + } + + size_type __end = __start_ + size(); + __map_const_iterator __first_mp = __map_.begin() + __start_ / __block_size; + __map_const_iterator __last_mp = __map_.begin() + (__end - 1) / __block_size; + + // Pointers to first and after last elements + // Those can be in different deque blocks + const void* __p_beg = std::__to_address(*__first_mp + (__start_ % __block_size)); + const void* __p_end = + std::__to_address(*__last_mp + ((__end % __block_size == 0) ? __block_size : __end % __block_size)); + + for (__map_const_iterator __it = __map_.begin(); __it != __map_.end(); ++__it) { + // Go over all blocks, find the place we are in and verify its annotations + // Note that __p_end points *behind* the last item. + + // - blocks before the first block with container elements + // - first block with items + // - last block with items + // - blocks after last block with ciontainer elements + + // Is the block before or after deque blocks that contain elements? + if (__it < __first_mp || __it > __last_mp) { + if (!__sanitizer_verify_double_ended_contiguous_container( + std::__to_address(*__it), + std::__to_address(*__it), + std::__to_address(*__it), + std::__to_address(*__it + __block_size))) + return false; + } else { + const void* __containers_buffer_beg = (__it == __first_mp) ? __p_beg : (const void*)std::__to_address(*__it); + const void* __containers_buffer_end = + (__it == __last_mp) ? __p_end : (const void*)std::__to_address(*__it + __block_size); + if (!__sanitizer_verify_double_ended_contiguous_container( + std::__to_address(*__it), + __containers_buffer_beg, + __containers_buffer_end, + std::__to_address(*__it + __block_size))) { + return false; + } + } + } + return true; + } + + private: +#endif // _LIBCPP_VERIFY_ASAN_DEQUE_ANNOTATIONS _LIBCPP_HIDE_FROM_ABI bool __maybe_remove_front_spare(bool __keep_one = true) { if (__front_spare_blocks() >= 2 || (!__keep_one && __front_spare_blocks())) { + __annotate_whole_block(0, __asan_unposion); __alloc_traits::deallocate(__alloc(), __map_.front(), __block_size); __map_.pop_front(); @@ -866,6 +1227,7 @@ public: _LIBCPP_HIDE_FROM_ABI bool __maybe_remove_back_spare(bool __keep_one = true) { if (__back_spare_blocks() >= 2 || (!__keep_one && __back_spare_blocks())) { + __annotate_whole_block(__map_.size() - 1, __asan_unposion); __alloc_traits::deallocate(__alloc(), __map_.back(), __block_size); __map_.pop_back(); @@ -874,12 +1236,44 @@ public: return false; } + template <class _Iterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI + void __assign_with_sentinel(_Iterator __f, _Sentinel __l); + + template <class _RandomAccessIterator> + _LIBCPP_HIDE_FROM_ABI + void __assign_with_size_random_access(_RandomAccessIterator __f, difference_type __n); + template <class _Iterator> + _LIBCPP_HIDE_FROM_ABI + void __assign_with_size(_Iterator __f, difference_type __n); + + template <class _Iterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI + iterator __insert_with_sentinel(const_iterator __p, _Iterator __f, _Sentinel __l); + + template <class _Iterator> + _LIBCPP_HIDE_FROM_ABI + iterator __insert_with_size(const_iterator __p, _Iterator __f, size_type __n); + + template <class _BiIter, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI + iterator __insert_bidirectional(const_iterator __p, _BiIter __f, _Sentinel __sent, size_type __n); + template <class _BiIter> + _LIBCPP_HIDE_FROM_ABI + iterator __insert_bidirectional(const_iterator __p, _BiIter __f, _BiIter __l, size_type __n); + template <class _InpIter> _LIBCPP_HIDE_FROM_ABI void __append(_InpIter __f, _InpIter __l, - typename enable_if<__is_exactly_cpp17_input_iterator<_InpIter>::value>::type* = 0); + typename enable_if<__has_exactly_input_iterator_category<_InpIter>::value>::type* = 0); template <class _ForIter> _LIBCPP_HIDE_FROM_ABI void __append(_ForIter __f, _ForIter __l, - typename enable_if<__is_cpp17_forward_iterator<_ForIter>::value>::type* = 0); + typename enable_if<__has_forward_iterator_category<_ForIter>::value>::type* = 0); + + template <class _InputIterator> + _LIBCPP_HIDE_FROM_ABI void __append_with_size(_InputIterator __from, size_type __n); + template <class _InputIterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI void __append_with_sentinel(_InputIterator __f, _Sentinel __l); + _LIBCPP_HIDE_FROM_ABI void __append(size_type __n); _LIBCPP_HIDE_FROM_ABI void __append(size_type __n, const value_type& __v); _LIBCPP_HIDE_FROM_ABI void __erase_to_end(const_iterator __f); @@ -929,7 +1323,7 @@ _LIBCPP_CONSTEXPR const typename allocator_traits<_Alloc>::difference_type deque #if _LIBCPP_STD_VER >= 17 template<class _InputIterator, class _Alloc = allocator<__iter_value_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Alloc>::value> > deque(_InputIterator, _InputIterator) @@ -937,26 +1331,37 @@ deque(_InputIterator, _InputIterator) template<class _InputIterator, class _Alloc, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Alloc>::value> > deque(_InputIterator, _InputIterator, _Alloc) -> deque<__iter_value_type<_InputIterator>, _Alloc>; #endif +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, + class _Alloc = allocator<ranges::range_value_t<_Range>>, + class = enable_if_t<__is_allocator<_Alloc>::value> + > +deque(from_range_t, _Range&&, _Alloc = _Alloc()) + -> deque<ranges::range_value_t<_Range>, _Alloc>; +#endif + template <class _Tp, class _Allocator> deque<_Tp, _Allocator>::deque(size_type __n) : __start_(0), __size_(0, __default_init_tag()) { + __annotate_new(0); if (__n > 0) __append(__n); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp, class _Allocator> deque<_Tp, _Allocator>::deque(size_type __n, const _Allocator& __a) : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { + __annotate_new(0); if (__n > 0) __append(__n); } @@ -966,6 +1371,7 @@ template <class _Tp, class _Allocator> deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) : __start_(0), __size_(0, __default_init_tag()) { + __annotate_new(0); if (__n > 0) __append(__n, __v); } @@ -973,18 +1379,20 @@ deque<_Tp, _Allocator>::deque(size_type __n, const value_type& __v) template <class _Tp, class _Allocator> template <class _InputIter> deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l, - typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) + typename enable_if<__has_input_iterator_category<_InputIter>::value>::type*) : __start_(0), __size_(0, __default_init_tag()) { + __annotate_new(0); __append(__f, __l); } template <class _Tp, class _Allocator> template <class _InputIter> deque<_Tp, _Allocator>::deque(_InputIter __f, _InputIter __l, const allocator_type& __a, - typename enable_if<__is_cpp17_input_iterator<_InputIter>::value>::type*) + typename enable_if<__has_input_iterator_category<_InputIter>::value>::type*) : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { + __annotate_new(0); __append(__f, __l); } @@ -994,6 +1402,7 @@ deque<_Tp, _Allocator>::deque(const deque& __c) __start_(0), __size_(0, __map_.__alloc()) { + __annotate_new(0); __append(__c.begin(), __c.end()); } @@ -1001,6 +1410,7 @@ template <class _Tp, class _Allocator> deque<_Tp, _Allocator>::deque(const deque& __c, const __type_identity_t<allocator_type>& __a) : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { + __annotate_new(0); __append(__c.begin(), __c.end()); } @@ -1022,6 +1432,7 @@ template <class _Tp, class _Allocator> deque<_Tp, _Allocator>::deque(initializer_list<value_type> __il) : __start_(0), __size_(0, __default_init_tag()) { + __annotate_new(0); __append(__il.begin(), __il.end()); } @@ -1029,6 +1440,7 @@ template <class _Tp, class _Allocator> deque<_Tp, _Allocator>::deque(initializer_list<value_type> __il, const allocator_type& __a) : __map_(__pointer_allocator(__a)), __start_(0), __size_(0, __a) { + __annotate_new(0); __append(__il.begin(), __il.end()); } @@ -1105,15 +1517,22 @@ template <class _Tp, class _Allocator> template <class _InputIter> void deque<_Tp, _Allocator>::assign(_InputIter __f, _InputIter __l, - typename enable_if<__is_cpp17_input_iterator<_InputIter>::value && - !__is_cpp17_random_access_iterator<_InputIter>::value>::type*) + typename enable_if<__has_input_iterator_category<_InputIter>::value && + !__has_random_access_iterator_category<_InputIter>::value>::type*) { + __assign_with_sentinel(__f, __l); +} + +template <class _Tp, class _Allocator> +template <class _Iterator, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI +void deque<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __f, _Sentinel __l) { iterator __i = begin(); iterator __e = end(); for (; __f != __l && __i != __e; ++__f, (void) ++__i) *__i = *__f; if (__f != __l) - __append(__f, __l); + __append_with_sentinel(std::move(__f), std::move(__l)); else __erase_to_end(__i); } @@ -1122,16 +1541,42 @@ template <class _Tp, class _Allocator> template <class _RAIter> void deque<_Tp, _Allocator>::assign(_RAIter __f, _RAIter __l, - typename enable_if<__is_cpp17_random_access_iterator<_RAIter>::value>::type*) + typename enable_if<__has_random_access_iterator_category<_RAIter>::value>::type*) { - if (static_cast<size_type>(__l - __f) > size()) + __assign_with_size_random_access(__f, __l - __f); +} + +template <class _Tp, class _Allocator> +template <class _RandomAccessIterator> +_LIBCPP_HIDE_FROM_ABI +void deque<_Tp, _Allocator>::__assign_with_size_random_access(_RandomAccessIterator __f, difference_type __n) { + if (static_cast<size_type>(__n) > size()) { - _RAIter __m = __f + size(); - _VSTD::copy(__f, __m, begin()); - __append(__m, __l); + auto __l = __f + size(); + std::copy(__f, __l, begin()); + __append_with_size(__l, __n - size()); } else - __erase_to_end(_VSTD::copy(__f, __l, begin())); + __erase_to_end(std::copy_n(__f, __n, begin())); +} + +template <class _Tp, class _Allocator> +template <class _Iterator> +_LIBCPP_HIDE_FROM_ABI +void deque<_Tp, _Allocator>::__assign_with_size(_Iterator __f, difference_type __n) { + if (static_cast<size_type>(__n) > size()) { + auto __added_size = __n - size(); + + auto __i = begin(); + for (auto __count = size(); __count != 0; --__count) { + *__i++ = *__f++; + } + + __append_with_size(__f, __added_size); + + } else { + __erase_to_end(std::copy_n(__f, __n, begin())); + } } template <class _Tp, class _Allocator> @@ -1183,6 +1628,7 @@ deque<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT allocator_type& __a = __alloc(); if (empty()) { + __annotate_delete(); while (__map_.size() > 0) { __alloc_traits::deallocate(__a, __map_.back(), __block_size); @@ -1282,6 +1728,7 @@ deque<_Tp, _Allocator>::push_back(const value_type& __v) if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*end()), __v); ++__size(); } @@ -1294,6 +1741,7 @@ deque<_Tp, _Allocator>::push_front(const value_type& __v) if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), __v); --__start_; ++__size(); @@ -1308,13 +1756,14 @@ deque<_Tp, _Allocator>::push_back(value_type&& __v) if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*end()), _VSTD::move(__v)); ++__size(); } template <class _Tp, class _Allocator> template <class... _Args> -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typename deque<_Tp, _Allocator>::reference #else void @@ -1325,10 +1774,11 @@ deque<_Tp, _Allocator>::emplace_back(_Args&&... __args) if (__back_spare() == 0) __add_back_capacity(); // __back_spare() >= 1 + __annotate_increase_back(1); __alloc_traits::construct(__a, _VSTD::addressof(*end()), _VSTD::forward<_Args>(__args)...); ++__size(); -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return *--end(); #endif } @@ -1341,6 +1791,7 @@ deque<_Tp, _Allocator>::push_front(value_type&& __v) if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::move(__v)); --__start_; ++__size(); @@ -1349,7 +1800,7 @@ deque<_Tp, _Allocator>::push_front(value_type&& __v) template <class _Tp, class _Allocator> template <class... _Args> -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typename deque<_Tp, _Allocator>::reference #else void @@ -1360,10 +1811,11 @@ deque<_Tp, _Allocator>::emplace_front(_Args&&... __args) if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::forward<_Args>(__args)...); --__start_; ++__size(); -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return *begin(); #endif } @@ -1380,6 +1832,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, value_type&& __v) if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::move(__v)); @@ -1403,6 +1856,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, value_type&& __v) if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = size() - __pos; if (__de == 0) { @@ -1436,6 +1890,7 @@ deque<_Tp, _Allocator>::emplace(const_iterator __p, _Args&&... __args) if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), _VSTD::forward<_Args>(__args)...); @@ -1460,6 +1915,7 @@ deque<_Tp, _Allocator>::emplace(const_iterator __p, _Args&&... __args) if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = size() - __pos; if (__de == 0) { @@ -1496,6 +1952,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, const value_type& __v) if (__front_spare() == 0) __add_front_capacity(); // __front_spare() >= 1 + __annotate_increase_front(1); if (__pos == 0) { __alloc_traits::construct(__a, _VSTD::addressof(*--begin()), __v); @@ -1522,6 +1979,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, const value_type& __v) if (__back_spare() == 0) __add_back_capacity(); // __back_capacity >= 1 + __annotate_increase_back(1); size_type __de = size() - __pos; if (__de == 0) { @@ -1557,6 +2015,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, size_type __n, const value_ty if (__n > __front_spare()) __add_front_capacity(__n - __front_spare()); // __n <= __front_spare() + __annotate_increase_front(__n); iterator __old_begin = begin(); iterator __i = __old_begin; if (__n > __pos) @@ -1581,6 +2040,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, size_type __n, const value_ty if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); iterator __old_end = end(); iterator __i = __old_end; size_type __de = size() - __pos; @@ -1607,10 +2067,18 @@ template <class _Tp, class _Allocator> template <class _InputIter> typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::insert(const_iterator __p, _InputIter __f, _InputIter __l, - typename enable_if<__is_exactly_cpp17_input_iterator<_InputIter>::value>::type*) + typename enable_if<__has_exactly_input_iterator_category<_InputIter>::value>::type*) { + return __insert_with_sentinel(__p, __f, __l); +} + +template <class _Tp, class _Allocator> +template <class _Iterator, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI +typename deque<_Tp, _Allocator>::iterator +deque<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __p, _Iterator __f, _Sentinel __l) { __split_buffer<value_type, allocator_type&> __buf(__alloc()); - __buf.__construct_at_end(__f, __l); + __buf.__construct_at_end_with_sentinel(std::move(__f), std::move(__l)); typedef typename __split_buffer<value_type, allocator_type&>::iterator __bi; return insert(__p, move_iterator<__bi>(__buf.begin()), move_iterator<__bi>(__buf.end())); } @@ -1619,11 +2087,18 @@ template <class _Tp, class _Allocator> template <class _ForwardIterator> typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::insert(const_iterator __p, _ForwardIterator __f, _ForwardIterator __l, - typename enable_if<__is_exactly_cpp17_forward_iterator<_ForwardIterator>::value>::type*) + typename enable_if<__has_exactly_forward_iterator_category<_ForwardIterator>::value>::type*) { - size_type __n = _VSTD::distance(__f, __l); + return __insert_with_size(__p, __f, std::distance(__f, __l)); +} + +template <class _Tp, class _Allocator> +template <class _Iterator> +_LIBCPP_HIDE_FROM_ABI +typename deque<_Tp, _Allocator>::iterator +deque<_Tp, _Allocator>::__insert_with_size(const_iterator __p, _Iterator __f, size_type __n) { __split_buffer<value_type, allocator_type&> __buf(__n, 0, __alloc()); - __buf.__construct_at_end(__f, __l); + __buf.__construct_at_end_with_size(__f, __n); typedef typename __split_buffer<value_type, allocator_type&>::iterator __fwd; return insert(__p, move_iterator<__fwd>(__buf.begin()), move_iterator<__fwd>(__buf.end())); } @@ -1632,9 +2107,24 @@ template <class _Tp, class _Allocator> template <class _BiIter> typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::insert(const_iterator __p, _BiIter __f, _BiIter __l, - typename enable_if<__is_cpp17_bidirectional_iterator<_BiIter>::value>::type*) + typename enable_if<__has_bidirectional_iterator_category<_BiIter>::value>::type*) { - size_type __n = _VSTD::distance(__f, __l); + return __insert_bidirectional(__p, __f, __l, std::distance(__f, __l)); +} + +template <class _Tp, class _Allocator> +template <class _BiIter, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI +typename deque<_Tp, _Allocator>::iterator +deque<_Tp, _Allocator>::__insert_bidirectional(const_iterator __p, _BiIter __f, _Sentinel, size_type __n) { + return __insert_bidirectional(__p, __f, std::next(__f, __n), __n); +} + +template <class _Tp, class _Allocator> +template <class _BiIter> +_LIBCPP_HIDE_FROM_ABI +typename deque<_Tp, _Allocator>::iterator +deque<_Tp, _Allocator>::__insert_bidirectional(const_iterator __p, _BiIter __f, _BiIter __l, size_type __n) { size_type __pos = __p - begin(); size_type __to_end = size() - __pos; allocator_type& __a = __alloc(); @@ -1643,6 +2133,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, _BiIter __f, _BiIter __l, if (__n > __front_spare()) __add_front_capacity(__n - __front_spare()); // __n <= __front_spare() + __annotate_increase_front(__n); iterator __old_begin = begin(); iterator __i = __old_begin; _BiIter __m = __f; @@ -1673,6 +2164,7 @@ deque<_Tp, _Allocator>::insert(const_iterator __p, _BiIter __f, _BiIter __l, if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); iterator __old_end = end(); iterator __i = __old_end; _BiIter __m = __l; @@ -1701,8 +2193,15 @@ template <class _Tp, class _Allocator> template <class _InpIter> void deque<_Tp, _Allocator>::__append(_InpIter __f, _InpIter __l, - typename enable_if<__is_exactly_cpp17_input_iterator<_InpIter>::value>::type*) + typename enable_if<__has_exactly_input_iterator_category<_InpIter>::value>::type*) { + __append_with_sentinel(__f, __l); +} + +template <class _Tp, class _Allocator> +template <class _InputIterator, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI +void deque<_Tp, _Allocator>::__append_with_sentinel(_InputIterator __f, _Sentinel __l) { for (; __f != __l; ++__f) #ifdef _LIBCPP_CXX03_LANG push_back(*__f); @@ -1715,14 +2214,22 @@ template <class _Tp, class _Allocator> template <class _ForIter> void deque<_Tp, _Allocator>::__append(_ForIter __f, _ForIter __l, - typename enable_if<__is_cpp17_forward_iterator<_ForIter>::value>::type*) + typename enable_if<__has_forward_iterator_category<_ForIter>::value>::type*) { - size_type __n = _VSTD::distance(__f, __l); + __append_with_size(__f, std::distance(__f, __l)); +} + +template <class _Tp, class _Allocator> +template <class _InputIterator> +_LIBCPP_HIDE_FROM_ABI +void deque<_Tp, _Allocator>::__append_with_size(_InputIterator __f, size_type __n) { allocator_type& __a = __alloc(); size_type __back_capacity = __back_spare(); if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); + // __n <= __back_capacity + __annotate_increase_back(__n); for (__deque_block_range __br : __deque_range(end(), end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__f) { @@ -1740,6 +2247,7 @@ deque<_Tp, _Allocator>::__append(size_type __n) if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); for (__deque_block_range __br : __deque_range(end(), end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { @@ -1757,6 +2265,7 @@ deque<_Tp, _Allocator>::__append(size_type __n, const value_type& __v) if (__n > __back_capacity) __add_back_capacity(__n - __back_capacity); // __n <= __back_capacity + __annotate_increase_back(__n); for (__deque_block_range __br : __deque_range(end(), end() + __n)) { _ConstructTransaction __tx(this, __br); for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) { @@ -1824,6 +2333,7 @@ deque<_Tp, _Allocator>::__add_front_capacity() __block_size / 2 : __start_ + __block_size; } + __annotate_whole_block(0, __asan_poison); } // Create front capacity for __n elements. @@ -1859,6 +2369,7 @@ deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) if (__map_.__front_spare() == 0) break; __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __annotate_whole_block(0, __asan_poison); } for (; __nb > 0; --__nb, ++__back_capacity) __map_.push_back(__alloc_traits::allocate(__a, __block_size)); @@ -1869,6 +2380,7 @@ deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) pointer __pt = __map_.back(); __map_.pop_back(); __map_.push_front(__pt); + __annotate_whole_block(0, __asan_poison); } } // Else need to allocate __nb buffers, *and* we need to reallocate __map_. @@ -1879,22 +2391,28 @@ deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) __buf(std::max<size_type>(2* __map_.capacity(), __nb + __map_.size()), 0, __map_.__alloc()); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS - for (; __nb > 0; --__nb) +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + for (; __nb > 0; --__nb) { __buf.push_back(__alloc_traits::allocate(__a, __block_size)); -#ifndef _LIBCPP_NO_EXCEPTIONS + // ASan: this is empty container, we have to poison whole block + __annotate_poison_block( + std::__to_address(__buf.back()), + std::__to_address(__buf.back() + __block_size)); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { + __annotate_delete(); for (__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) __alloc_traits::deallocate(__a, *__i, __block_size); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __back_capacity > 0; --__back_capacity) { __buf.push_back(__map_.back()); @@ -1940,6 +2458,7 @@ deque<_Tp, _Allocator>::__add_back_capacity() __map_.pop_front(); __map_.push_back(__pt); } + __annotate_whole_block(__map_.size() - 1, __asan_poison); } // Else need to allocate 1 buffer, *and* we need to reallocate __map_. else @@ -1963,6 +2482,7 @@ deque<_Tp, _Allocator>::__add_back_capacity() _VSTD::swap(__map_.__begin_, __buf.__begin_); _VSTD::swap(__map_.__end_, __buf.__end_); _VSTD::swap(__map_.__end_cap(), __buf.__end_cap()); + __annotate_whole_block(__map_.size() - 1, __asan_poison); } } @@ -1999,10 +2519,13 @@ deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) if (__map_.__back_spare() == 0) break; __map_.push_back(__alloc_traits::allocate(__a, __block_size)); + __annotate_whole_block(__map_.size() - 1, __asan_poison); } for (; __nb > 0; --__nb, ++__front_capacity, __start_ += - __block_size - (__map_.size() == 1)) + __block_size - (__map_.size() == 1)) { __map_.push_front(__alloc_traits::allocate(__a, __block_size)); + __annotate_whole_block(0, __asan_poison); + } // Done allocating, reorder capacity __start_ -= __block_size * __front_capacity; for (; __front_capacity > 0; --__front_capacity) @@ -2021,22 +2544,28 @@ deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) __nb + __map_.size()), __map_.size() - __front_capacity, __map_.__alloc()); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS - for (; __nb > 0; --__nb) +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + for (; __nb > 0; --__nb) { __buf.push_back(__alloc_traits::allocate(__a, __block_size)); -#ifndef _LIBCPP_NO_EXCEPTIONS + // ASan: this is an empty container, we have to poison the whole block + __annotate_poison_block( + std::__to_address(__buf.back()), + std::__to_address(__buf.back() + __block_size)); + } +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { + __annotate_delete(); for (__map_pointer __i = __buf.begin(); __i != __buf.end(); ++__i) __alloc_traits::deallocate(__a, *__i, __block_size); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __front_capacity > 0; --__front_capacity) { __buf.push_back(__map_.front()); @@ -2057,12 +2586,15 @@ template <class _Tp, class _Allocator> void deque<_Tp, _Allocator>::pop_front() { + size_type __old_sz = size(); + size_type __old_start = __start_; allocator_type& __a = __alloc(); __alloc_traits::destroy(__a, _VSTD::__to_address(*(__map_.begin() + __start_ / __block_size) + __start_ % __block_size)); --__size(); ++__start_; + __annotate_shrink_front(__old_sz, __old_start); __maybe_remove_front_spare(); } @@ -2070,13 +2602,16 @@ template <class _Tp, class _Allocator> void deque<_Tp, _Allocator>::pop_back() { - _LIBCPP_ASSERT(!empty(), "deque::pop_back called on an empty deque"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "deque::pop_back called on an empty deque"); + size_type __old_sz = size(); + size_type __old_start = __start_; allocator_type& __a = __alloc(); size_type __p = size() + __start_ - 1; __alloc_traits::destroy(__a, _VSTD::__to_address(*(__map_.begin() + __p / __block_size) + __p % __block_size)); --__size(); + __annotate_shrink_back(__old_sz, __old_start); __maybe_remove_back_spare(); } @@ -2216,6 +2751,8 @@ template <class _Tp, class _Allocator> typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f) { + size_type __old_sz = size(); + size_type __old_start = __start_; iterator __b = begin(); difference_type __pos = __f - __b; iterator __p = __b + __pos; @@ -2226,6 +2763,7 @@ deque<_Tp, _Allocator>::erase(const_iterator __f) __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); --__size(); ++__start_; + __annotate_shrink_front(__old_sz, __old_start); __maybe_remove_front_spare(); } else @@ -2233,6 +2771,7 @@ deque<_Tp, _Allocator>::erase(const_iterator __f) iterator __i = _VSTD::move(_VSTD::next(__p), end(), __p); __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); --__size(); + __annotate_shrink_back(__old_sz, __old_start); __maybe_remove_back_spare(); } return begin() + __pos; @@ -2242,6 +2781,8 @@ template <class _Tp, class _Allocator> typename deque<_Tp, _Allocator>::iterator deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) { + size_type __old_sz = size(); + size_type __old_start = __start_; difference_type __n = __l - __f; iterator __b = begin(); difference_type __pos = __f - __b; @@ -2256,6 +2797,7 @@ deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) __alloc_traits::destroy(__a, _VSTD::addressof(*__b)); __size() -= __n; __start_ += __n; + __annotate_shrink_front(__old_sz, __old_start); while (__maybe_remove_front_spare()) { } } @@ -2265,6 +2807,7 @@ deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l) for (iterator __e = end(); __i != __e; ++__i) __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); __size() -= __n; + __annotate_shrink_back(__old_sz, __old_start); while (__maybe_remove_back_spare()) { } } @@ -2276,6 +2819,8 @@ template <class _Tp, class _Allocator> void deque<_Tp, _Allocator>::__erase_to_end(const_iterator __f) { + size_type __old_sz = size(); + size_type __old_start = __start_; iterator __e = end(); difference_type __n = __e - __f; if (__n > 0) @@ -2286,6 +2831,7 @@ deque<_Tp, _Allocator>::__erase_to_end(const_iterator __f) for (iterator __p = __b + __pos; __p != __e; ++__p) __alloc_traits::destroy(__a, _VSTD::addressof(*__p)); __size() -= __n; + __annotate_shrink_back(__old_sz, __old_start); while (__maybe_remove_back_spare()) { } } @@ -2313,6 +2859,7 @@ inline void deque<_Tp, _Allocator>::clear() _NOEXCEPT { + __annotate_delete(); allocator_type& __a = __alloc(); for (iterator __i = begin(), __e = end(); __i != __e; ++__i) __alloc_traits::destroy(__a, _VSTD::addressof(*__i)); @@ -2331,6 +2878,7 @@ deque<_Tp, _Allocator>::clear() _NOEXCEPT __start_ = __block_size; break; } + __annotate_new(0); } template <class _Tp, class _Allocator> @@ -2342,6 +2890,8 @@ operator==(const deque<_Tp, _Allocator>& __x, const deque<_Tp, _Allocator>& __y) return __sz == __y.size() && _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template <class _Tp, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI bool @@ -2382,6 +2932,17 @@ operator<=(const deque<_Tp, _Allocator>& __x, const deque<_Tp, _Allocator>& __y) return !(__y < __x); } +#else // _LIBCPP_STD_VER <= 17 + +template <class _Tp, class _Allocator> +_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Tp> +operator<=>(const deque<_Tp, _Allocator>& __x, const deque<_Tp, _Allocator>& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>); +} + +#endif // _LIBCPP_STD_VER <= 17 + template <class _Tp, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI void @@ -2391,7 +2952,7 @@ swap(deque<_Tp, _Allocator>& __x, deque<_Tp, _Allocator>& __y) __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Allocator, class _Up> inline _LIBCPP_HIDE_FROM_ABI typename deque<_Tp, _Allocator>::size_type erase(deque<_Tp, _Allocator>& __c, const _Up& __v) { @@ -2415,15 +2976,15 @@ template <> inline constexpr bool __format::__enable_insertable<std::deque<wchar_t>> = true; #endif -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template <class _ValueT> -using deque = std::deque<_ValueT, polymorphic_allocator<_ValueT>>; +using deque _LIBCPP_AVAILABILITY_PMR = std::deque<_ValueT, polymorphic_allocator<_ValueT>>; } // namespace pmr _LIBCPP_END_NAMESPACE_STD #endif @@ -2434,9 +2995,11 @@ _LIBCPP_POP_MACROS # include <algorithm> # include <atomic> # include <concepts> +# include <cstdlib> # include <functional> # include <iosfwd> # include <iterator> +# include <type_traits> # include <typeinfo> #endif diff --git a/libcxx/include/exception b/libcxx/include/exception index e0f42682b579..97fee977690d 100644 --- a/libcxx/include/exception +++ b/libcxx/include/exception @@ -77,307 +77,20 @@ template <class E> void rethrow_if_nested(const E& e); */ #include <__assert> // all public C++ headers provide the assertion handler -#include <__availability> #include <__config> -#include <__memory/addressof.h> -#include <__type_traits/decay.h> -#include <__type_traits/is_base_of.h> -#include <__type_traits/is_class.h> -#include <__type_traits/is_convertible.h> -#include <__type_traits/is_copy_constructible.h> -#include <__type_traits/is_final.h> -#include <__type_traits/is_polymorphic.h> -#include <cstddef> -#include <cstdlib> +#include <__exception/exception.h> +#include <__exception/exception_ptr.h> +#include <__exception/nested_exception.h> +#include <__exception/operations.h> +#include <__exception/terminate.h> #include <version> -// <vcruntime_exception.h> defines its own std::exception and std::bad_exception types, -// which we use in order to be ABI-compatible with other STLs on Windows. -#if defined(_LIBCPP_ABI_VCRUNTIME) -# include <vcruntime_exception.h> -#endif - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -namespace std // purposefully not using versioning namespace -{ - -#if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0) -// The std::exception class was already included above, but we're explicit about this condition here for clarity. - -#elif defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0 -// However, <vcruntime_exception.h> does not define std::exception and std::bad_exception -// when _HAS_EXCEPTIONS == 0. -// -// Since libc++ still wants to provide the std::exception hierarchy even when _HAS_EXCEPTIONS == 0 -// (after all those are simply types like any other), we define an ABI-compatible version -// of the VCRuntime std::exception and std::bad_exception types in that mode. - -struct __std_exception_data { - char const* _What; - bool _DoFree; -}; - -class exception { // base of all library exceptions -public: - exception() _NOEXCEPT : __data_() {} - - explicit exception(char const* __message) _NOEXCEPT : __data_() { - __data_._What = __message; - __data_._DoFree = true; - } - - exception(exception const&) _NOEXCEPT {} - - exception& operator=(exception const&) _NOEXCEPT { return *this; } - - virtual ~exception() _NOEXCEPT {} - - virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; } - -private: - __std_exception_data __data_; -}; - -class bad_exception : public exception { -public: - bad_exception() _NOEXCEPT : exception("bad exception") {} -}; - -#else // !defined(_LIBCPP_ABI_VCRUNTIME) -// On all other platforms, we define our own std::exception and std::bad_exception types -// regardless of whether exceptions are turned on as a language feature. - -class _LIBCPP_EXCEPTION_ABI exception { -public: - _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {} - _LIBCPP_INLINE_VISIBILITY exception(const exception&) _NOEXCEPT = default; - - virtual ~exception() _NOEXCEPT; - virtual const char* what() const _NOEXCEPT; -}; - -class _LIBCPP_EXCEPTION_ABI bad_exception : public exception { -public: - _LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {} - ~bad_exception() _NOEXCEPT override; - const char* what() const _NOEXCEPT override; -}; -#endif // !_LIBCPP_ABI_VCRUNTIME - -#if _LIBCPP_STD_VER <= 14 \ - || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \ - || defined(_LIBCPP_BUILDING_LIBRARY) -typedef void (*unexpected_handler)(); -_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT; -_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT; -_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected(); -#endif - -typedef void (*terminate_handler)(); -_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT; -_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT; -_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT; - -_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT; -_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT; - -class _LIBCPP_TYPE_VIS exception_ptr; - -_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; -_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); - -#ifndef _LIBCPP_ABI_MICROSOFT - -class _LIBCPP_TYPE_VIS exception_ptr -{ - void* __ptr_; -public: - _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} - _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} - - exception_ptr(const exception_ptr&) _NOEXCEPT; - exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; - ~exception_ptr() _NOEXCEPT; - - _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT - {return __ptr_ != nullptr;} - - friend _LIBCPP_INLINE_VISIBILITY - bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT - {return __x.__ptr_ == __y.__ptr_;} - - friend _LIBCPP_INLINE_VISIBILITY - bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT - {return !(__x == __y);} - - friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; - friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); -}; - -template<class _Ep> -_LIBCPP_INLINE_VISIBILITY exception_ptr -make_exception_ptr(_Ep __e) _NOEXCEPT -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { - throw __e; - } - catch (...) - { - return current_exception(); - } -#else - ((void)__e); - _VSTD::abort(); -#endif -} - -#else // _LIBCPP_ABI_MICROSOFT - -class _LIBCPP_TYPE_VIS exception_ptr -{ -_LIBCPP_DIAGNOSTIC_PUSH -_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field") - void* __ptr1_; - void* __ptr2_; -_LIBCPP_DIAGNOSTIC_POP -public: - exception_ptr() _NOEXCEPT; - exception_ptr(nullptr_t) _NOEXCEPT; - exception_ptr(const exception_ptr& __other) _NOEXCEPT; - exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; - exception_ptr& operator=(nullptr_t) _NOEXCEPT; - ~exception_ptr() _NOEXCEPT; - explicit operator bool() const _NOEXCEPT; -}; - -_LIBCPP_FUNC_VIS -bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; - -inline _LIBCPP_INLINE_VISIBILITY -bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT - {return !(__x == __y);} - -_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; - -_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr); -_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT; -_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); - -// This is a built-in template function which automagically extracts the required -// information. -template <class _E> void *__GetExceptionInfo(_E); - -template<class _Ep> -_LIBCPP_INLINE_VISIBILITY exception_ptr -make_exception_ptr(_Ep __e) _NOEXCEPT -{ - return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e)); -} - -#endif // _LIBCPP_ABI_MICROSOFT -// nested_exception - -class _LIBCPP_EXCEPTION_ABI nested_exception -{ - exception_ptr __ptr_; -public: - nested_exception() _NOEXCEPT; -// nested_exception(const nested_exception&) noexcept = default; -// nested_exception& operator=(const nested_exception&) noexcept = default; - virtual ~nested_exception() _NOEXCEPT; - - // access functions - _LIBCPP_NORETURN void rethrow_nested() const; - _LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;} -}; - -template <class _Tp> -struct __nested - : public _Tp, - public nested_exception -{ - _LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {} -}; - -#ifndef _LIBCPP_NO_EXCEPTIONS -template <class _Tp, class _Up, bool> -struct __throw_with_nested; - -template <class _Tp, class _Up> -struct __throw_with_nested<_Tp, _Up, true> { - _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void - __do_throw(_Tp&& __t) - { - throw __nested<_Up>(static_cast<_Tp&&>(__t)); - } -}; - -template <class _Tp, class _Up> -struct __throw_with_nested<_Tp, _Up, false> { - _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void -#ifndef _LIBCPP_CXX03_LANG - __do_throw(_Tp&& __t) -#else - __do_throw (_Tp& __t) -#endif // _LIBCPP_CXX03_LANG - { - throw static_cast<_Tp&&>(__t); - } -}; -#endif - -template <class _Tp> -_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI -void -throw_with_nested(_Tp&& __t) -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - typedef typename decay<_Tp>::type _Up; - static_assert( is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible"); - __throw_with_nested<_Tp, _Up, - is_class<_Up>::value && - !is_base_of<nested_exception, _Up>::value && - !__libcpp_is_final<_Up>::value>:: - __do_throw(static_cast<_Tp&&>(__t)); -#else - ((void)__t); - // FIXME: Make this abort -#endif -} - -template <class _From, class _To> -struct __can_dynamic_cast : _BoolConstant< - is_polymorphic<_From>::value && - (!is_base_of<_To, _From>::value || - is_convertible<const _From*, const _To*>::value)> {}; - -template <class _Ep> -inline _LIBCPP_INLINE_VISIBILITY -void -rethrow_if_nested(const _Ep& __e, - __enable_if_t< __can_dynamic_cast<_Ep, nested_exception>::value>* = 0) -{ - const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e)); - if (__nep) - __nep->rethrow_nested(); -} - -template <class _Ep> -inline _LIBCPP_INLINE_VISIBILITY -void -rethrow_if_nested(const _Ep&, - __enable_if_t<!__can_dynamic_cast<_Ep, nested_exception>::value>* = 0) -{ -} - -} // namespace std - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstdlib> # include <type_traits> #endif diff --git a/libcxx/include/execution b/libcxx/include/execution index 040297038637..56facc87379e 100644 --- a/libcxx/include/execution +++ b/libcxx/include/execution @@ -10,16 +10,137 @@ #ifndef _LIBCPP_EXECUTION #define _LIBCPP_EXECUTION +/* +namespace std::execution { + struct sequenced_policy; + struct parallel_policy; + struct parallel_unsequenced_policy; + struct unsequenced_policy; // since C++20 + + inline constexpr sequenced_policy seq = implementation-defined; + inline constexpr parallel_policy par = implementation-defined; + inline constexpr parallel_unsequenced_policy par_unseq = implementation-defined; + inline constexpr unsequenced_policy unseq = implementation-defined; // since C++20 +} + +namespace std { + template <class T> + struct is_execution_policy; + + template <class T> + inline constexpr bool is_execution_policy_v; +} +*/ + #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__type_traits/is_execution_policy.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cvref.h> #include <version> -#if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17 -# include <__pstl_execution> -#endif - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace execution { +struct sequenced_policy { + _LIBCPP_HIDE_FROM_ABI constexpr explicit sequenced_policy(__disable_user_instantiations_tag) {} + sequenced_policy(const sequenced_policy&) = delete; + sequenced_policy& operator=(const sequenced_policy&) = delete; +}; + +inline constexpr sequenced_policy seq{__disable_user_instantiations_tag{}}; + +struct parallel_policy { + _LIBCPP_HIDE_FROM_ABI constexpr explicit parallel_policy(__disable_user_instantiations_tag) {} + parallel_policy(const parallel_policy&) = delete; + parallel_policy& operator=(const parallel_policy&) = delete; +}; + +inline constexpr parallel_policy par{__disable_user_instantiations_tag{}}; + +struct parallel_unsequenced_policy { + _LIBCPP_HIDE_FROM_ABI constexpr explicit parallel_unsequenced_policy(__disable_user_instantiations_tag) {} + parallel_unsequenced_policy(const parallel_unsequenced_policy&) = delete; + parallel_unsequenced_policy& operator=(const parallel_unsequenced_policy&) = delete; +}; + +inline constexpr parallel_unsequenced_policy par_unseq{__disable_user_instantiations_tag{}}; + +struct __unsequenced_policy { + _LIBCPP_HIDE_FROM_ABI constexpr explicit __unsequenced_policy(__disable_user_instantiations_tag) {} + __unsequenced_policy(const __unsequenced_policy&) = delete; + __unsequenced_policy& operator=(const __unsequenced_policy&) = delete; +}; + +constexpr __unsequenced_policy __unseq{__disable_user_instantiations_tag{}}; + +# if _LIBCPP_STD_VER >= 20 + +struct unsequenced_policy { + _LIBCPP_HIDE_FROM_ABI constexpr explicit unsequenced_policy(__disable_user_instantiations_tag) {} + unsequenced_policy(const unsequenced_policy&) = delete; + unsequenced_policy& operator=(const unsequenced_policy&) = delete; +}; + +inline constexpr unsequenced_policy unseq{__disable_user_instantiations_tag{}}; + +# endif // _LIBCPP_STD_VER >= 20 + +} // namespace execution + +template <> +inline constexpr bool is_execution_policy_v<execution::sequenced_policy> = true; + +template <> +inline constexpr bool is_execution_policy_v<execution::parallel_policy> = true; + +template <> +inline constexpr bool is_execution_policy_v<execution::parallel_unsequenced_policy> = true; + +template <> +inline constexpr bool is_execution_policy_v<execution::__unsequenced_policy> = true; + +template <> +inline constexpr bool __is_parallel_execution_policy_impl<execution::parallel_policy> = true; + +template <> +inline constexpr bool __is_parallel_execution_policy_impl<execution::parallel_unsequenced_policy> = true; + +template <> +inline constexpr bool __is_unsequenced_execution_policy_impl<execution::__unsequenced_policy> = true; + +template <> +inline constexpr bool __is_unsequenced_execution_policy_impl<execution::parallel_unsequenced_policy> = true; + +# if _LIBCPP_STD_VER >= 20 +template <> +inline constexpr bool is_execution_policy_v<execution::unsequenced_policy> = true; + +template <> +inline constexpr bool __is_unsequenced_execution_policy_impl<execution::unsequenced_policy> = true; + +# endif + +template <class _Tp> +struct is_execution_policy : bool_constant<is_execution_policy_v<_Tp>> {}; + +template <class _ExecutionPolicy> +_LIBCPP_HIDE_FROM_ABI auto __remove_parallel_policy(const _ExecutionPolicy&) { + if constexpr (is_same_v<_ExecutionPolicy, execution::parallel_policy>) { + return execution::sequenced_policy(execution::__disable_user_instantiations_tag{}); + } else if constexpr (is_same_v<_ExecutionPolicy, execution::parallel_unsequenced_policy>) { + return execution::__unsequenced_policy{execution::__disable_user_instantiations_tag{}}; + } +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 + #endif // _LIBCPP_EXECUTION diff --git a/libcxx/include/experimental/__config b/libcxx/include/experimental/__config index a71b348c0490..839b80aa6398 100644 --- a/libcxx/include/experimental/__config +++ b/libcxx/include/experimental/__config @@ -32,18 +32,6 @@ #define _LIBCPP_END_NAMESPACE_LFTS_PMR _LIBCPP_END_NAMESPACE_LFTS } #define _VSTD_LFTS_PMR _VSTD_LFTS::pmr -#if !defined(__cpp_coroutines) || __cpp_coroutines < 201703L -#define _LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES -#endif - -#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_COROUTINES \ - _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace coroutines_v1 { - -#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL_COROUTINES \ - } _LIBCPP_END_NAMESPACE_EXPERIMENTAL - -#define _VSTD_CORO _VSTD_EXPERIMENTAL::coroutines_v1 - #define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD \ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace parallelism_v2 { diff --git a/libcxx/include/experimental/__memory b/libcxx/include/experimental/__memory index b36f31eebb7c..b11369632ae1 100644 --- a/libcxx/include/experimental/__memory +++ b/libcxx/include/experimental/__memory @@ -12,9 +12,12 @@ #include <__memory/allocator_arg_t.h> #include <__memory/uses_allocator.h> +#include <__type_traits/conditional.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_same.h> #include <experimental/__config> #include <experimental/utility> // for erased_type -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -90,7 +93,7 @@ template <class _Tp, class _Allocator, class... _Args> inline _LIBCPP_INLINE_VISIBILITY void __user_alloc_construct_impl (integral_constant<int, 1>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) { - new (__storage) _Tp (allocator_arg, __a, _VSTD::forward<_Args>(__args)...); + new (__storage) _Tp (allocator_arg_t(), __a, _VSTD::forward<_Args>(__args)...); } // FIXME: This should have a version which takes a non-const alloc. diff --git a/libcxx/include/experimental/algorithm b/libcxx/include/experimental/algorithm deleted file mode 100644 index e0ca3c73be6b..000000000000 --- a/libcxx/include/experimental/algorithm +++ /dev/null @@ -1,53 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP_EXPERIMENTAL_ALGORITHM -#define _LIBCPP_EXPERIMENTAL_ALGORITHM - -/* - experimental/algorithm synopsis - -#include <algorithm> - -namespace std { -namespace experimental { -inline namespace fundamentals_v1 { - -template <class ForwardIterator, class Searcher> -ForwardIterator search(ForwardIterator first, ForwardIterator last, - const Searcher &searcher); - -// sample removed because it's now part of C++17 - -} // namespace fundamentals_v1 -} // namespace experimental -} // namespace std - -*/ - -#include <__assert> // all public C++ headers provide the assertion handler -#include <__debug> -#include <algorithm> -#include <experimental/__config> -#include <type_traits> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_LFTS - -template <class _ForwardIterator, class _Searcher> -_LIBCPP_INLINE_VISIBILITY -_ForwardIterator search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher &__s) -{ return __s(__f, __l).first; } - -_LIBCPP_END_NAMESPACE_LFTS - -#endif /* _LIBCPP_EXPERIMENTAL_ALGORITHM */ diff --git a/libcxx/include/experimental/coroutine b/libcxx/include/experimental/coroutine deleted file mode 100644 index d9f368535024..000000000000 --- a/libcxx/include/experimental/coroutine +++ /dev/null @@ -1,344 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP_EXPERIMENTAL_COROUTINE -#define _LIBCPP_EXPERIMENTAL_COROUTINE - -/** - experimental/coroutine synopsis - -// C++next - -namespace std { -namespace experimental { -inline namespace coroutines_v1 { - - // 18.11.1 coroutine traits -template <typename R, typename... ArgTypes> -class coroutine_traits; -// 18.11.2 coroutine handle -template <typename Promise = void> -class coroutine_handle; -// 18.11.2.7 comparison operators: -bool operator==(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT; -bool operator!=(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT; -bool operator<(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT; -bool operator<=(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT; -bool operator>=(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT; -bool operator>(coroutine_handle<> x, coroutine_handle<> y) _NOEXCEPT; -// 18.11.3 trivial awaitables -struct suspend_never; -struct suspend_always; -// 18.11.2.8 hash support: -template <class T> struct hash; -template <class P> struct hash<coroutine_handle<P>>; - -} // namespace coroutines_v1 -} // namespace experimental -} // namespace std - - */ - -#include <__assert> // all public C++ headers provide the assertion handler -#include <__functional/hash.h> -#include <__functional/operations.h> -#include <cstddef> -#include <experimental/__config> -#include <new> -#include <type_traits> - -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 -# include <atomic> -# include <climits> -# include <cmath> -# include <compare> -# include <concepts> -# include <ctime> -# include <initializer_list> -# include <iosfwd> -# include <iterator> -# include <memory> -# include <ratio> -# include <stdexcept> -# include <tuple> -# include <typeinfo> -# include <utility> -# include <variant> -#endif - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#ifndef _LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES - -_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_COROUTINES - -template <class _Tp, class = void> -struct __coroutine_traits_sfinae {}; - -template <class _Tp> -struct __coroutine_traits_sfinae<_Tp, __void_t<typename _Tp::promise_type> > -{ - using promise_type = typename _Tp::promise_type; -}; - -template <typename _Ret, typename... _Args> -struct coroutine_traits - : public __coroutine_traits_sfinae<_Ret> -{ -}; - -template <typename _Promise = void> -class _LIBCPP_TEMPLATE_VIS coroutine_handle; - -template <> -class _LIBCPP_TEMPLATE_VIS coroutine_handle<void> { -public: - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR coroutine_handle() _NOEXCEPT : __handle_(nullptr) {} - - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR coroutine_handle(nullptr_t) _NOEXCEPT : __handle_(nullptr) {} - - _LIBCPP_INLINE_VISIBILITY - coroutine_handle& operator=(nullptr_t) _NOEXCEPT { - __handle_ = nullptr; - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR void* address() const _NOEXCEPT { return __handle_; } - - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR explicit operator bool() const _NOEXCEPT { return __handle_; } - - _LIBCPP_INLINE_VISIBILITY - void operator()() { resume(); } - - _LIBCPP_INLINE_VISIBILITY - void resume() { - _LIBCPP_ASSERT(__is_suspended(), - "resume() can only be called on suspended coroutines"); - _LIBCPP_ASSERT(!done(), - "resume() has undefined behavior when the coroutine is done"); - __builtin_coro_resume(__handle_); - } - - _LIBCPP_INLINE_VISIBILITY - void destroy() { - _LIBCPP_ASSERT(__is_suspended(), - "destroy() can only be called on suspended coroutines"); - __builtin_coro_destroy(__handle_); - } - - _LIBCPP_INLINE_VISIBILITY - bool done() const { - _LIBCPP_ASSERT(__is_suspended(), - "done() can only be called on suspended coroutines"); - return __builtin_coro_done(__handle_); - } - -public: - _LIBCPP_INLINE_VISIBILITY - static coroutine_handle from_address(void* __addr) _NOEXCEPT { - coroutine_handle __tmp; - __tmp.__handle_ = __addr; - return __tmp; - } - - // FIXME: Should from_address(nullptr) be allowed? - _LIBCPP_INLINE_VISIBILITY - static coroutine_handle from_address(nullptr_t) _NOEXCEPT { - return coroutine_handle(nullptr); - } - - template <class _Tp, bool _CallIsValid = false> - static coroutine_handle from_address(_Tp*) { - static_assert(_CallIsValid, - "coroutine_handle<void>::from_address cannot be called with " - "non-void pointers"); - } - -private: - bool __is_suspended() const _NOEXCEPT { - // FIXME actually implement a check for if the coro is suspended. - return __handle_; - } - - template <class _PromiseT> friend class coroutine_handle; - void* __handle_; -}; - -// 18.11.2.7 comparison operators: -inline _LIBCPP_INLINE_VISIBILITY -bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT { - return __x.address() == __y.address(); -} -inline _LIBCPP_INLINE_VISIBILITY -bool operator!=(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT { - return !(__x == __y); -} -inline _LIBCPP_INLINE_VISIBILITY -bool operator<(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT { - return less<void*>()(__x.address(), __y.address()); -} -inline _LIBCPP_INLINE_VISIBILITY -bool operator>(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT { - return __y < __x; -} -inline _LIBCPP_INLINE_VISIBILITY -bool operator<=(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT { - return !(__x > __y); -} -inline _LIBCPP_INLINE_VISIBILITY -bool operator>=(coroutine_handle<> __x, coroutine_handle<> __y) _NOEXCEPT { - return !(__x < __y); -} - -template <typename _Promise> -class _LIBCPP_TEMPLATE_VIS coroutine_handle : public coroutine_handle<> { - using _Base = coroutine_handle<>; -public: -#ifndef _LIBCPP_CXX03_LANG - // 18.11.2.1 construct/reset - using coroutine_handle<>::coroutine_handle; -#else - _LIBCPP_INLINE_VISIBILITY coroutine_handle() _NOEXCEPT : _Base() {} - _LIBCPP_INLINE_VISIBILITY coroutine_handle(nullptr_t) _NOEXCEPT : _Base(nullptr) {} -#endif - _LIBCPP_INLINE_VISIBILITY - coroutine_handle& operator=(nullptr_t) _NOEXCEPT { - _Base::operator=(nullptr); - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - _Promise& promise() const { - return *static_cast<_Promise*>( - __builtin_coro_promise(this->__handle_, _LIBCPP_ALIGNOF(_Promise), false)); - } - -public: - _LIBCPP_INLINE_VISIBILITY - static coroutine_handle from_address(void* __addr) _NOEXCEPT { - coroutine_handle __tmp; - __tmp.__handle_ = __addr; - return __tmp; - } - - // NOTE: this overload isn't required by the standard but is needed so - // the deleted _Promise* overload doesn't make from_address(nullptr) - // ambiguous. - // FIXME: should from_address work with nullptr? - _LIBCPP_INLINE_VISIBILITY - static coroutine_handle from_address(nullptr_t) _NOEXCEPT { - return coroutine_handle(nullptr); - } - - template <class _Tp, bool _CallIsValid = false> - static coroutine_handle from_address(_Tp*) { - static_assert(_CallIsValid, - "coroutine_handle<promise_type>::from_address cannot be called with " - "non-void pointers"); - } - - template <bool _CallIsValid = false> - static coroutine_handle from_address(_Promise*) { - static_assert(_CallIsValid, - "coroutine_handle<promise_type>::from_address cannot be used with " - "pointers to the coroutine's promise type; use 'from_promise' instead"); - } - - _LIBCPP_INLINE_VISIBILITY - static coroutine_handle from_promise(_Promise& __promise) _NOEXCEPT { - typedef __remove_cv_t<_Promise> _RawPromise; - coroutine_handle __tmp; - __tmp.__handle_ = __builtin_coro_promise( - _VSTD::addressof(const_cast<_RawPromise&>(__promise)), - _LIBCPP_ALIGNOF(_Promise), true); - return __tmp; - } -}; - -#if __has_builtin(__builtin_coro_noop) -struct noop_coroutine_promise {}; - -template <> -class _LIBCPP_TEMPLATE_VIS coroutine_handle<noop_coroutine_promise> - : public coroutine_handle<> { - using _Base = coroutine_handle<>; - using _Promise = noop_coroutine_promise; -public: - - _LIBCPP_INLINE_VISIBILITY - _Promise& promise() const { - return *static_cast<_Promise*>( - __builtin_coro_promise(this->__handle_, _LIBCPP_ALIGNOF(_Promise), false)); - } - - _LIBCPP_CONSTEXPR explicit operator bool() const _NOEXCEPT { return true; } - _LIBCPP_CONSTEXPR bool done() const _NOEXCEPT { return false; } - - _LIBCPP_CONSTEXPR_SINCE_CXX20 void operator()() const _NOEXCEPT {} - _LIBCPP_CONSTEXPR_SINCE_CXX20 void resume() const _NOEXCEPT {} - _LIBCPP_CONSTEXPR_SINCE_CXX20 void destroy() const _NOEXCEPT {} - -private: - _LIBCPP_INLINE_VISIBILITY - friend coroutine_handle<noop_coroutine_promise> noop_coroutine() _NOEXCEPT; - - _LIBCPP_INLINE_VISIBILITY coroutine_handle() _NOEXCEPT { - this->__handle_ = __builtin_coro_noop(); - } -}; - -using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>; - -inline _LIBCPP_INLINE_VISIBILITY -noop_coroutine_handle noop_coroutine() _NOEXCEPT { - return noop_coroutine_handle(); -} -#endif // __has_builtin(__builtin_coro_noop) - -struct suspend_never { - _LIBCPP_INLINE_VISIBILITY - bool await_ready() const _NOEXCEPT { return true; } - _LIBCPP_INLINE_VISIBILITY - void await_suspend(coroutine_handle<>) const _NOEXCEPT {} - _LIBCPP_INLINE_VISIBILITY - void await_resume() const _NOEXCEPT {} -}; - -struct suspend_always { - _LIBCPP_INLINE_VISIBILITY - bool await_ready() const _NOEXCEPT { return false; } - _LIBCPP_INLINE_VISIBILITY - void await_suspend(coroutine_handle<>) const _NOEXCEPT {} - _LIBCPP_INLINE_VISIBILITY - void await_resume() const _NOEXCEPT {} -}; - -_LIBCPP_END_NAMESPACE_EXPERIMENTAL_COROUTINES - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct hash<_VSTD_CORO::coroutine_handle<_Tp> > { - using __arg_type = _VSTD_CORO::coroutine_handle<_Tp>; - _LIBCPP_INLINE_VISIBILITY - size_t operator()(__arg_type const& __v) const _NOEXCEPT - {return hash<void*>()(__v.address());} -}; - -_LIBCPP_END_NAMESPACE_STD - -#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES) - -#endif /* _LIBCPP_EXPERIMENTAL_COROUTINE */ diff --git a/libcxx/include/experimental/functional b/libcxx/include/experimental/functional deleted file mode 100644 index cb9a5efac3f8..000000000000 --- a/libcxx/include/experimental/functional +++ /dev/null @@ -1,436 +0,0 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP_EXPERIMENTAL_FUNCTIONAL -#define _LIBCPP_EXPERIMENTAL_FUNCTIONAL - -/* - experimental/functional synopsis - -#include <algorithm> - -namespace std { -namespace experimental { -inline namespace fundamentals_v1 { - // 4.3, Searchers - template<class ForwardIterator, class BinaryPredicate = equal_to<>> - class default_searcher; - - template<class RandomAccessIterator, - class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, - class BinaryPredicate = equal_to<>> - class boyer_moore_searcher; - - template<class RandomAccessIterator, - class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, - class BinaryPredicate = equal_to<>> - class boyer_moore_horspool_searcher; - - template<class ForwardIterator, class BinaryPredicate = equal_to<>> - default_searcher<ForwardIterator, BinaryPredicate> - make_default_searcher(ForwardIterator pat_first, ForwardIterator pat_last, - BinaryPredicate pred = BinaryPredicate()); - - template<class RandomAccessIterator, - class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, - class BinaryPredicate = equal_to<>> - boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate> - make_boyer_moore_searcher( - RandomAccessIterator pat_first, RandomAccessIterator pat_last, - Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate()); - - template<class RandomAccessIterator, - class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, - class BinaryPredicate = equal_to<>> - boyer_moore_horspool_searcher<RandomAccessIterator, Hash, BinaryPredicate> - make_boyer_moore_horspool_searcher( - RandomAccessIterator pat_first, RandomAccessIterator pat_last, - Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate()); - - } // namespace fundamentals_v1 - } // namespace experimental - -} // namespace std - -*/ - -#include <__assert> // all public C++ headers provide the assertion handler -#include <__debug> -#include <__functional/identity.h> -#include <__memory/uses_allocator.h> -#include <array> -#include <experimental/__config> -#include <functional> -#include <type_traits> -#include <unordered_map> -#include <vector> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - -_LIBCPP_BEGIN_NAMESPACE_LFTS - -#ifdef _LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_SEARCHERS -# define _LIBCPP_DEPRECATED_DEFAULT_SEARCHER -# define _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER -# define _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER -#else -# define _LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_DEPRECATED_("std::experimental::default_searcher will be removed in LLVM 17. Use std::default_searcher instead") -# define _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_DEPRECATED_("std::experimental::boyer_moore_searcher will be removed in LLVM 17. Use std::boyer_moore_searcher instead") -# define _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_DEPRECATED_("std::experimental::boyer_moore_horspool_searcher will be removed in LLVM 17. Use std::boyer_moore_horspool_searcher instead") -#endif - -#if _LIBCPP_STD_VER > 11 -// default searcher -template<class _ForwardIterator, class _BinaryPredicate = equal_to<>> -class _LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_TEMPLATE_VIS default_searcher { -public: - _LIBCPP_INLINE_VISIBILITY - default_searcher(_ForwardIterator __f, _ForwardIterator __l, - _BinaryPredicate __p = _BinaryPredicate()) - : __first_(__f), __last_(__l), __pred_(__p) {} - - template <typename _ForwardIterator2> - _LIBCPP_INLINE_VISIBILITY - pair<_ForwardIterator2, _ForwardIterator2> - operator () (_ForwardIterator2 __f, _ForwardIterator2 __l) const - { - auto __proj = __identity(); - return std::__search_impl(__f, __l, __first_, __last_, __pred_, __proj, __proj); - } - -private: - _ForwardIterator __first_; - _ForwardIterator __last_; - _BinaryPredicate __pred_; - }; - -template<class _ForwardIterator, class _BinaryPredicate = equal_to<>> -_LIBCPP_DEPRECATED_DEFAULT_SEARCHER _LIBCPP_INLINE_VISIBILITY -default_searcher<_ForwardIterator, _BinaryPredicate> -make_default_searcher( _ForwardIterator __f, _ForwardIterator __l, _BinaryPredicate __p = _BinaryPredicate ()) -{ - return default_searcher<_ForwardIterator, _BinaryPredicate>(__f, __l, __p); -} - -template<class _Key, class _Value, class _Hash, class _BinaryPredicate, bool /*useArray*/> class _BMSkipTable; - -// General case for BM data searching; use a map -template<class _Key, typename _Value, class _Hash, class _BinaryPredicate> -class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, false> { - typedef _Value value_type; - typedef _Key key_type; - - const _Value __default_value_; - std::unordered_map<_Key, _Value, _Hash, _BinaryPredicate> __table_; - -public: - _LIBCPP_INLINE_VISIBILITY - _BMSkipTable(size_t __sz, _Value __default, _Hash __hf, _BinaryPredicate __pred) - : __default_value_(__default), __table_(__sz, __hf, __pred) {} - - _LIBCPP_INLINE_VISIBILITY - void insert(const key_type &__key, value_type __val) - { - __table_ [__key] = __val; // Would skip_.insert (val) be better here? - } - - _LIBCPP_INLINE_VISIBILITY - value_type operator [](const key_type & __key) const - { - auto __it = __table_.find (__key); - return __it == __table_.end() ? __default_value_ : __it->second; - } -}; - - -// Special case small numeric values; use an array -template<class _Key, typename _Value, class _Hash, class _BinaryPredicate> -class _BMSkipTable<_Key, _Value, _Hash, _BinaryPredicate, true> { -private: - typedef _Value value_type; - typedef _Key key_type; - - typedef __make_unsigned_t<key_type> unsigned_key_type; - typedef std::array<value_type, 256> skip_map; - skip_map __table_; - -public: - _LIBCPP_INLINE_VISIBILITY - _BMSkipTable(size_t /*__sz*/, _Value __default, _Hash /*__hf*/, _BinaryPredicate /*__pred*/) - { - std::fill_n(__table_.begin(), __table_.size(), __default); - } - - _LIBCPP_INLINE_VISIBILITY - void insert(key_type __key, value_type __val) - { - __table_[static_cast<unsigned_key_type>(__key)] = __val; - } - - _LIBCPP_INLINE_VISIBILITY - value_type operator [](key_type __key) const - { - return __table_[static_cast<unsigned_key_type>(__key)]; - } -}; - - -template <class _RandomAccessIterator1, - class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>, - class _BinaryPredicate = equal_to<>> -class _LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_TEMPLATE_VIS boyer_moore_searcher { -private: - typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type; - typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type value_type; - typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate, - is_integral<value_type>::value && // what about enums? - sizeof(value_type) == 1 && - is_same<_Hash, hash<value_type>>::value && - is_same<_BinaryPredicate, equal_to<>>::value - > skip_table_type; - -public: - boyer_moore_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l, - _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate()) - : __first_(__f), __last_(__l), __pred_(__pred), - __pattern_length_(_VSTD::distance(__first_, __last_)), - __skip_{std::make_shared<skip_table_type>(__pattern_length_, -1, __hf, __pred_)}, - __suffix_{std::make_shared<vector<difference_type>>(__pattern_length_ + 1)} - { - // build the skip table - for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i ) - __skip_->insert(*__f, __i); - - this->__build_suffix_table ( __first_, __last_, __pred_ ); - } - - template <typename _RandomAccessIterator2> - pair<_RandomAccessIterator2, _RandomAccessIterator2> - operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const - { - static_assert(__is_same_uncvref<typename iterator_traits<_RandomAccessIterator1>::value_type, - typename iterator_traits<_RandomAccessIterator2>::value_type>::value, - "Corpus and Pattern iterators must point to the same type"); - - if (__f == __l ) return std::make_pair(__l, __l); // empty corpus - if (__first_ == __last_) return std::make_pair(__f, __f); // empty pattern - - // If the pattern is larger than the corpus, we can't find it! - if ( __pattern_length_ > _VSTD::distance(__f, __l)) - return std::make_pair(__l, __l); - - // Do the search - return this->__search(__f, __l); - } - -private: - _RandomAccessIterator1 __first_; - _RandomAccessIterator1 __last_; - _BinaryPredicate __pred_; - difference_type __pattern_length_; - shared_ptr<skip_table_type> __skip_; - shared_ptr<vector<difference_type>> __suffix_; - - template <typename _RandomAccessIterator2> - pair<_RandomAccessIterator2, _RandomAccessIterator2> - __search(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const - { - _RandomAccessIterator2 __cur = __f; - const _RandomAccessIterator2 __last = __l - __pattern_length_; - const skip_table_type & __skip = *__skip_.get(); - const vector<difference_type> & __suffix = *__suffix_.get(); - - while (__cur <= __last) - { - - // Do we match right where we are? - difference_type __j = __pattern_length_; - while (__pred_(__first_ [__j-1], __cur [__j-1])) { - __j--; - // We matched - we're done! - if ( __j == 0 ) - return std::make_pair(__cur, __cur + __pattern_length_); - } - - // Since we didn't match, figure out how far to skip forward - difference_type __k = __skip[__cur [ __j - 1 ]]; - difference_type __m = __j - __k - 1; - if (__k < __j && __m > __suffix[ __j ]) - __cur += __m; - else - __cur += __suffix[ __j ]; - } - - return std::make_pair(__l, __l); // We didn't find anything - } - - - template<typename _Iterator, typename _Container> - void __compute_bm_prefix ( _Iterator __f, _Iterator __l, _BinaryPredicate __pred, _Container &__prefix ) - { - const size_t __count = _VSTD::distance(__f, __l); - - __prefix[0] = 0; - size_t __k = 0; - for ( size_t __i = 1; __i < __count; ++__i ) - { - while ( __k > 0 && !__pred ( __f[__k], __f[__i] )) - __k = __prefix [ __k - 1 ]; - - if ( __pred ( __f[__k], __f[__i] )) - __k++; - __prefix [ __i ] = __k; - } - } - - void __build_suffix_table(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l, - _BinaryPredicate __pred) - { - const size_t __count = _VSTD::distance(__f, __l); - vector<difference_type> & __suffix = *__suffix_.get(); - if (__count > 0) - { - vector<difference_type> __scratch(__count); - - __compute_bm_prefix(__f, __l, __pred, __scratch); - for ( size_t __i = 0; __i <= __count; __i++ ) - __suffix[__i] = __count - __scratch[__count-1]; - - typedef reverse_iterator<_RandomAccessIterator1> _RevIter; - __compute_bm_prefix(_RevIter(__l), _RevIter(__f), __pred, __scratch); - - for ( size_t __i = 0; __i < __count; __i++ ) - { - const size_t __j = __count - __scratch[__i]; - const difference_type __k = __i - __scratch[__i] + 1; - - if (__suffix[__j] > __k) - __suffix[__j] = __k; - } - } - } - -}; - -template<class _RandomAccessIterator, - class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>, - class _BinaryPredicate = equal_to<>> -_LIBCPP_DEPRECATED_BOYER_MOORE_SEARCHER _LIBCPP_INLINE_VISIBILITY -boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate> -make_boyer_moore_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l, - _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ()) -{ - return boyer_moore_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p); -} - -// boyer-moore-horspool -template <class _RandomAccessIterator1, - class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>, - class _BinaryPredicate = equal_to<>> -class _LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher { -private: - typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type difference_type; - typedef typename std::iterator_traits<_RandomAccessIterator1>::value_type value_type; - typedef _BMSkipTable<value_type, difference_type, _Hash, _BinaryPredicate, - is_integral<value_type>::value && // what about enums? - sizeof(value_type) == 1 && - is_same<_Hash, hash<value_type>>::value && - is_same<_BinaryPredicate, equal_to<>>::value - > skip_table_type; - -public: - boyer_moore_horspool_searcher(_RandomAccessIterator1 __f, _RandomAccessIterator1 __l, - _Hash __hf = _Hash(), _BinaryPredicate __pred = _BinaryPredicate()) - : __first_(__f), __last_(__l), __pred_(__pred), - __pattern_length_(_VSTD::distance(__first_, __last_)), - __skip_{_VSTD::make_shared<skip_table_type>(__pattern_length_, __pattern_length_, __hf, __pred_)} - { - // build the skip table - if ( __f != __l ) - { - __l = __l - 1; - for ( difference_type __i = 0; __f != __l; ++__f, (void) ++__i ) - __skip_->insert(*__f, __pattern_length_ - 1 - __i); - } - } - - template <typename _RandomAccessIterator2> - pair<_RandomAccessIterator2, _RandomAccessIterator2> - operator ()(_RandomAccessIterator2 __f, _RandomAccessIterator2 __l) const - { - static_assert(__is_same_uncvref<typename std::iterator_traits<_RandomAccessIterator1>::value_type, - typename std::iterator_traits<_RandomAccessIterator2>::value_type>::value, - "Corpus and Pattern iterators must point to the same type"); - - if (__f == __l ) return std::make_pair(__l, __l); // empty corpus - if (__first_ == __last_) return std::make_pair(__f, __f); // empty pattern - - // If the pattern is larger than the corpus, we can't find it! - if ( __pattern_length_ > _VSTD::distance(__f, __l)) - return std::make_pair(__l, __l); - - // Do the search - return this->__search(__f, __l); - } - -private: - _RandomAccessIterator1 __first_; - _RandomAccessIterator1 __last_; - _BinaryPredicate __pred_; - difference_type __pattern_length_; - shared_ptr<skip_table_type> __skip_; - - template <typename _RandomAccessIterator2> - pair<_RandomAccessIterator2, _RandomAccessIterator2> - __search ( _RandomAccessIterator2 __f, _RandomAccessIterator2 __l ) const { - _RandomAccessIterator2 __cur = __f; - const _RandomAccessIterator2 __last = __l - __pattern_length_; - const skip_table_type & __skip = *__skip_.get(); - - while (__cur <= __last) - { - // Do we match right where we are? - difference_type __j = __pattern_length_; - while (__pred_(__first_[__j-1], __cur[__j-1])) - { - __j--; - // We matched - we're done! - if ( __j == 0 ) - return std::make_pair(__cur, __cur + __pattern_length_); - } - __cur += __skip[__cur[__pattern_length_-1]]; - } - - return std::make_pair(__l, __l); - } -}; - -template<class _RandomAccessIterator, - class _Hash = hash<typename iterator_traits<_RandomAccessIterator>::value_type>, - class _BinaryPredicate = equal_to<>> -_LIBCPP_DEPRECATED_BOYER_MOORE_HORSPOOL_SEARCHER _LIBCPP_INLINE_VISIBILITY -boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate> -make_boyer_moore_horspool_searcher( _RandomAccessIterator __f, _RandomAccessIterator __l, - _Hash __hf = _Hash(), _BinaryPredicate __p = _BinaryPredicate ()) -{ - return boyer_moore_horspool_searcher<_RandomAccessIterator, _Hash, _BinaryPredicate>(__f, __l, __hf, __p); -} - -#endif // _LIBCPP_STD_VER > 11 - -_LIBCPP_END_NAMESPACE_LFTS - -_LIBCPP_POP_MACROS - -#endif /* _LIBCPP_EXPERIMENTAL_FUNCTIONAL */ diff --git a/libcxx/include/experimental/iterator b/libcxx/include/experimental/iterator index cf73b74e887e..a5e3dffba980 100644 --- a/libcxx/include/experimental/iterator +++ b/libcxx/include/experimental/iterator @@ -65,7 +65,7 @@ namespace std { # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _LIBCPP_BEGIN_NAMESPACE_LFTS @@ -82,15 +82,15 @@ public: typedef void pointer; typedef void reference; - ostream_joiner(ostream_type& __os, _Delim&& __d) + _LIBCPP_HIDE_FROM_ABI ostream_joiner(ostream_type& __os, _Delim&& __d) : __output_iter_(_VSTD::addressof(__os)), __delim_(_VSTD::move(__d)), __first_(true) {} - ostream_joiner(ostream_type& __os, const _Delim& __d) + _LIBCPP_HIDE_FROM_ABI ostream_joiner(ostream_type& __os, const _Delim& __d) : __output_iter_(_VSTD::addressof(__os)), __delim_(__d), __first_(true) {} template<typename _Tp> - ostream_joiner& operator=(const _Tp& __v) + _LIBCPP_HIDE_FROM_ABI ostream_joiner& operator=(const _Tp& __v) { if (!__first_) *__output_iter_ << __delim_; @@ -99,9 +99,9 @@ public: return *this; } - ostream_joiner& operator*() _NOEXCEPT { return *this; } - ostream_joiner& operator++() _NOEXCEPT { return *this; } - ostream_joiner& operator++(int) _NOEXCEPT { return *this; } + _LIBCPP_HIDE_FROM_ABI ostream_joiner& operator*() _NOEXCEPT { return *this; } + _LIBCPP_HIDE_FROM_ABI ostream_joiner& operator++() _NOEXCEPT { return *this; } + _LIBCPP_HIDE_FROM_ABI ostream_joiner& operator++(int) _NOEXCEPT { return *this; } private: ostream_type* __output_iter_; @@ -111,13 +111,13 @@ private: template <class _CharT, class _Traits, class _Delim> -_LIBCPP_HIDE_FROM_ABI ostream_joiner<typename decay<_Delim>::type, _CharT, _Traits> +_LIBCPP_HIDE_FROM_ABI ostream_joiner<__decay_t<_Delim>, _CharT, _Traits> make_ostream_joiner(basic_ostream<_CharT, _Traits>& __os, _Delim && __d) -{ return ostream_joiner<typename decay<_Delim>::type, _CharT, _Traits>(__os, _VSTD::forward<_Delim>(__d)); } +{ return ostream_joiner<__decay_t<_Delim>, _CharT, _Traits>(__os, _VSTD::forward<_Delim>(__d)); } _LIBCPP_END_NAMESPACE_LFTS -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <type_traits> diff --git a/libcxx/include/experimental/memory_resource b/libcxx/include/experimental/memory_resource index f107f109203f..8ae8322ae1a6 100644 --- a/libcxx/include/experimental/memory_resource +++ b/libcxx/include/experimental/memory_resource @@ -66,16 +66,15 @@ namespace pmr { #include <__assert> // all public C++ headers provide the assertion handler #include <__memory/allocator_traits.h> +#include <__type_traits/aligned_storage.h> #include <__utility/move.h> #include <cstddef> -#include <cstdlib> #include <experimental/__config> #include <experimental/__memory> #include <limits> #include <new> #include <stdexcept> #include <tuple> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -96,18 +95,18 @@ _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR inline _LIBCPP_INLINE_VISIBILITY size_t __aligned_allocation_size(size_t __s, size_t __a) _NOEXCEPT { - _LIBCPP_ASSERT(__s + __a > __s, "aligned allocation size overflows"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s + __a > __s, "aligned allocation size overflows"); return (__s + __a - 1) & ~(__a - 1); } // 8.5, memory.resource -class _LIBCPP_DEPCREATED_MEMORY_RESOURCE("memory_resource") _LIBCPP_TYPE_VIS memory_resource +class _LIBCPP_DEPCREATED_MEMORY_RESOURCE("memory_resource") _LIBCPP_EXPORTED_FROM_ABI memory_resource { static const size_t __max_align = _LIBCPP_ALIGNOF(max_align_t); // 8.5.2, memory.resource.public public: - virtual ~memory_resource() = default; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual ~memory_resource() = default; _LIBCPP_INLINE_VISIBILITY void* allocate(size_t __bytes, size_t __align = __max_align) @@ -143,16 +142,16 @@ bool operator!=(memory_resource const & __lhs, return !(__lhs == __rhs); } -_LIBCPP_DEPCREATED_MEMORY_RESOURCE("new_delete_resource()") _LIBCPP_FUNC_VIS +_LIBCPP_DEPCREATED_MEMORY_RESOURCE("new_delete_resource()") _LIBCPP_EXPORTED_FROM_ABI memory_resource * new_delete_resource() _NOEXCEPT; -_LIBCPP_DEPCREATED_MEMORY_RESOURCE("null_memory_resource()") _LIBCPP_FUNC_VIS +_LIBCPP_DEPCREATED_MEMORY_RESOURCE("null_memory_resource()") _LIBCPP_EXPORTED_FROM_ABI memory_resource * null_memory_resource() _NOEXCEPT; -_LIBCPP_DEPCREATED_MEMORY_RESOURCE("get_default_resource()") _LIBCPP_FUNC_VIS +_LIBCPP_DEPCREATED_MEMORY_RESOURCE("get_default_resource()") _LIBCPP_EXPORTED_FROM_ABI memory_resource * get_default_resource() _NOEXCEPT; -_LIBCPP_DEPCREATED_MEMORY_RESOURCE("set_default_resource()") _LIBCPP_FUNC_VIS +_LIBCPP_DEPCREATED_MEMORY_RESOURCE("set_default_resource()") _LIBCPP_EXPORTED_FROM_ABI memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT; // 8.6, memory.polymorphic.allocator.class @@ -175,7 +174,7 @@ public: : __res_(__r) {} - polymorphic_allocator(polymorphic_allocator const &) = default; + _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(polymorphic_allocator const &) = default; template <class _Tp> _LIBCPP_INLINE_VISIBILITY @@ -198,8 +197,8 @@ public: _LIBCPP_INLINE_VISIBILITY void deallocate(_ValueType * __p, size_t __n) _NOEXCEPT { - _LIBCPP_ASSERT(__n <= __max_size(), - "deallocate called for size which exceeds max_size()"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n <= __max_size(), + "deallocate called for size which exceeds max_size()"); __res_->deallocate(__p, __n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType)); } @@ -363,9 +362,9 @@ class _LIBCPP_TEMPLATE_VIS __resource_adaptor_imp public: typedef _CharAlloc allocator_type; - __resource_adaptor_imp() = default; - __resource_adaptor_imp(__resource_adaptor_imp const &) = default; - __resource_adaptor_imp(__resource_adaptor_imp &&) = default; + _LIBCPP_HIDE_FROM_ABI __resource_adaptor_imp() = default; + _LIBCPP_HIDE_FROM_ABI __resource_adaptor_imp(__resource_adaptor_imp const &) = default; + _LIBCPP_HIDE_FROM_ABI __resource_adaptor_imp(__resource_adaptor_imp &&) = default; // 8.7.2, memory.resource.adaptor.ctor @@ -379,7 +378,7 @@ public: : __alloc_(_VSTD::move(__a)) {} - __resource_adaptor_imp & + _LIBCPP_HIDE_FROM_ABI __resource_adaptor_imp & operator=(__resource_adaptor_imp const &) = default; _LIBCPP_INLINE_VISIBILITY @@ -388,7 +387,7 @@ public: // 8.7.3, memory.resource.adaptor.mem private: - void * do_allocate(size_t __bytes, size_t) override + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void * do_allocate(size_t __bytes, size_t) override { if (__bytes > __max_size()) __throw_bad_array_new_length(); @@ -396,15 +395,15 @@ private: return __alloc_.allocate(__s); } - void do_deallocate(void * __p, size_t __bytes, size_t) override + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void do_deallocate(void * __p, size_t __bytes, size_t) override { - _LIBCPP_ASSERT(__bytes <= __max_size(), + _LIBCPP_ASSERT_UNCATEGORIZED(__bytes <= __max_size(), "do_deallocate called for size which exceeds the maximum allocation size"); size_t __s = __aligned_allocation_size(__bytes, _MaxAlign) / _MaxAlign; __alloc_.deallocate((_ValueType*)__p, __s); } - bool do_is_equal(memory_resource const & __other) const _NOEXCEPT override { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL bool do_is_equal(memory_resource const & __other) const _NOEXCEPT override { __resource_adaptor_imp const * __p = dynamic_cast<__resource_adaptor_imp const *>(&__other); return __p ? __alloc_ == __p->__alloc_ : false; @@ -432,11 +431,13 @@ _LIBCPP_POP_MACROS # include <atomic> # include <climits> # include <concepts> +# include <cstdlib> # include <cstring> # include <ctime> # include <iterator> # include <memory> # include <ratio> +# include <type_traits> # include <variant> #endif diff --git a/libcxx/include/experimental/propagate_const b/libcxx/include/experimental/propagate_const index 34e917da5154..4fc8286465d9 100644 --- a/libcxx/include/experimental/propagate_const +++ b/libcxx/include/experimental/propagate_const @@ -110,17 +110,35 @@ #include <__assert> // all public C++ headers provide the assertion handler #include <__functional/operations.h> #include <__fwd/hash.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_function.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/remove_cv.h> +#include <__type_traits/remove_pointer.h> +#include <__type_traits/remove_reference.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> +#include <cstddef> #include <experimental/__config> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 11 +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 14 _LIBCPP_BEGIN_NAMESPACE_LFTS_V2 @@ -152,25 +170,25 @@ public: private: template <class _Up> - static _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up* __u) + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up* __u) { return __u; } template <class _Up> - static _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up& __u) + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up& __u) { return __get_pointer(__u.get()); } template <class _Up> - static _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up* __u) + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up* __u) { return __u; } template <class _Up> - static _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up& __u) + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up& __u) { return __get_pointer(__u.get()); } @@ -192,22 +210,22 @@ public: template <class _Up> friend _LIBCPP_CONSTEXPR const _Up& ::_VSTD_LFTS_V2::get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT; template <class _Up> friend _LIBCPP_CONSTEXPR _Up& ::_VSTD_LFTS_V2::get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT; - _LIBCPP_CONSTEXPR propagate_const() = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const() = default; propagate_const(const propagate_const&) = delete; - _LIBCPP_CONSTEXPR propagate_const(propagate_const&&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const(propagate_const&&) = default; template <class _Up, enable_if_t<!is_convertible<_Up, _Tp>::value && is_constructible<_Tp, _Up&&>::value,bool> = true> - explicit _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu) + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu) : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu))) { } template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value,bool> = false> - _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu) : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu))) { } @@ -215,7 +233,7 @@ public: template <class _Up, enable_if_t<!is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value && !__is_propagate_const<decay_t<_Up>>::value,bool> = true> - explicit _LIBCPP_CONSTEXPR propagate_const(_Up&& __u) + explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const(_Up&& __u) : __t_(std::forward<_Up>(__u)) { } @@ -223,78 +241,78 @@ public: template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value && !__is_propagate_const<decay_t<_Up>>::value,bool> = false> - _LIBCPP_CONSTEXPR propagate_const(_Up&& __u) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const(_Up&& __u) : __t_(std::forward<_Up>(__u)) { } propagate_const& operator=(const propagate_const&) = delete; - _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const&&) = default; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const&&) = default; template <class _Up> - _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const<_Up>&& __pu) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const<_Up>&& __pu) { __t_ = std::move(_VSTD_LFTS_V2::get_underlying(__pu)); return *this; } template <class _Up, class _Vp = enable_if_t<!__is_propagate_const<decay_t<_Up>>::value>> - _LIBCPP_CONSTEXPR propagate_const& operator=(_Up&& __u) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const& operator=(_Up&& __u) { __t_ = std::forward<_Up>(__u); return *this; } - _LIBCPP_CONSTEXPR const element_type* get() const + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const element_type* get() const { return __get_pointer(__t_); } - _LIBCPP_CONSTEXPR element_type* get() + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type* get() { return __get_pointer(__t_); } - explicit _LIBCPP_CONSTEXPR operator bool() const + _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR operator bool() const { return get() != nullptr; } - _LIBCPP_CONSTEXPR const element_type* operator->() const + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const element_type* operator->() const { return get(); } - template <class _Tp_ = _Tp, class _Up = enable_if_t<is_convertible< - const _Tp_, const element_type *>::value>> - _LIBCPP_CONSTEXPR operator const element_type *() const { + template <class _Dummy = _Tp, class _Up = enable_if_t<is_convertible< + const _Dummy, const element_type *>::value>> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR operator const element_type *() const { return get(); } - _LIBCPP_CONSTEXPR const element_type& operator*() const + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const element_type& operator*() const { return *get(); } - _LIBCPP_CONSTEXPR element_type* operator->() + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type* operator->() { return get(); } - template <class _Tp_ = _Tp, class _Up = enable_if_t< - is_convertible<_Tp_, element_type *>::value>> - _LIBCPP_CONSTEXPR operator element_type *() { + template <class _Dummy = _Tp, class _Up = enable_if_t< + is_convertible<_Dummy, element_type *>::value>> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR operator element_type *() { return get(); } - _LIBCPP_CONSTEXPR element_type& operator*() + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type& operator*() { return *get(); } - _LIBCPP_CONSTEXPR void swap(propagate_const& __pt) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) - { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR void swap(propagate_const& __pt) + _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) { using _VSTD::swap; swap(__t_, __pt.__t_); } @@ -491,7 +509,7 @@ struct hash<experimental::fundamentals_v2::propagate_const<_Tp>> typedef size_t result_type; typedef experimental::fundamentals_v2::propagate_const<_Tp> argument_type; - size_t operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1) const + _LIBCPP_HIDE_FROM_ABI size_t operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1) const { return std::hash<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1)); } @@ -503,7 +521,7 @@ struct equal_to<experimental::fundamentals_v2::propagate_const<_Tp>> typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type; typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type; - bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, + _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const { return std::equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2)); @@ -516,7 +534,7 @@ struct not_equal_to<experimental::fundamentals_v2::propagate_const<_Tp>> typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type; typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type; - bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, + _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const { return std::not_equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2)); @@ -529,7 +547,7 @@ struct less<experimental::fundamentals_v2::propagate_const<_Tp>> typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type; typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type; - bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, + _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const { return std::less<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2)); @@ -542,7 +560,7 @@ struct greater<experimental::fundamentals_v2::propagate_const<_Tp>> typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type; typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type; - bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, + _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const { return std::greater<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2)); @@ -555,7 +573,7 @@ struct less_equal<experimental::fundamentals_v2::propagate_const<_Tp>> typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type; typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type; - bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, + _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const { return std::less_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2)); @@ -568,7 +586,7 @@ struct greater_equal<experimental::fundamentals_v2::propagate_const<_Tp>> typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type; typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type; - bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, + _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1, const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const { return std::greater_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2)); @@ -577,5 +595,12 @@ struct greater_equal<experimental::fundamentals_v2::propagate_const<_Tp>> _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 + +_LIBCPP_POP_MACROS + +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <type_traits> +#endif + #endif // _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST diff --git a/libcxx/include/experimental/simd b/libcxx/include/experimental/simd index 4ca67d212b23..11047d12f7d3 100644 --- a/libcxx/include/experimental/simd +++ b/libcxx/include/experimental/simd @@ -691,8 +691,8 @@ class __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> { friend struct simd_mask; public: - _Tp __get(size_t __index) const noexcept { return __storage_[__index]; } - void __set(size_t __index, _Tp __val) noexcept { + _LIBCPP_HIDE_FROM_ABI _Tp __get(size_t __index) const noexcept { return __storage_[__index]; } + _LIBCPP_HIDE_FROM_ABI void __set(size_t __index, _Tp __val) noexcept { __storage_[__index] = __val; } }; @@ -708,8 +708,8 @@ class __simd_storage<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> { friend struct simd_mask; public: - _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; } - void __set(size_t __index, _Tp __val) noexcept { + _LIBCPP_HIDE_FROM_ABI _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; } + _LIBCPP_HIDE_FROM_ABI void __set(size_t __index, _Tp __val) noexcept { (&__storage_)[__index] = __val; } }; @@ -810,8 +810,8 @@ class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> { friend struct simd_mask; public: - _Tp __get(size_t __index) const noexcept { return __storage_[__index]; } - void __set(size_t __index, _Tp __val) noexcept { + _LIBCPP_HIDE_FROM_ABI _Tp __get(size_t __index) const noexcept { return __storage_[__index]; } + _LIBCPP_HIDE_FROM_ABI void __set(size_t __index, _Tp __val) noexcept { __storage_[__index] = __val; } }; @@ -831,79 +831,79 @@ class __simd_reference { __simd_storage<_Tp, _Abi>* __ptr_; size_t __index_; - __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) + _LIBCPP_HIDE_FROM_ABI __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) : __ptr_(__ptr), __index_(__index) {} - __simd_reference(const __simd_reference&) = default; + _LIBCPP_HIDE_FROM_ABI __simd_reference(const __simd_reference&) = default; public: __simd_reference() = delete; __simd_reference& operator=(const __simd_reference&) = delete; - operator _Vp() const { return __ptr_->__get(__index_); } + _LIBCPP_HIDE_FROM_ABI operator _Vp() const { return __ptr_->__get(__index_); } - __simd_reference operator=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator=(_Vp __value) && { __ptr_->__set(__index_, __value); return *this; } - __simd_reference operator++() && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator++() && { return std::move(*this) = __ptr_->__get(__index_) + 1; } - _Vp operator++(int) && { + _LIBCPP_HIDE_FROM_ABI _Vp operator++(int) && { auto __val = __ptr_->__get(__index_); __ptr_->__set(__index_, __val + 1); return __val; } - __simd_reference operator--() && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator--() && { return std::move(*this) = __ptr_->__get(__index_) - 1; } - _Vp operator--(int) && { + _LIBCPP_HIDE_FROM_ABI _Vp operator--(int) && { auto __val = __ptr_->__get(__index_); __ptr_->__set(__index_, __val - 1); return __val; } - __simd_reference operator+=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator+=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) + __value; } - __simd_reference operator-=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator-=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) - __value; } - __simd_reference operator*=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator*=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) * __value; } - __simd_reference operator/=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator/=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) / __value; } - __simd_reference operator%=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator%=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) % __value; } - __simd_reference operator>>=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator>>=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) >> __value; } - __simd_reference operator<<=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator<<=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) << __value; } - __simd_reference operator&=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator&=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) & __value; } - __simd_reference operator|=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator|=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) | __value; } - __simd_reference operator^=(_Vp __value) && { + _LIBCPP_HIDE_FROM_ABI __simd_reference operator^=(_Vp __value) && { return std::move(*this) = __ptr_->__get(__index_) ^ __value; } }; @@ -1350,11 +1350,11 @@ public: using mask_type = simd_mask<_Tp, _Abi>; using abi_type = _Abi; - simd() = default; - simd(const simd&) = default; - simd& operator=(const simd&) = default; + _LIBCPP_HIDE_FROM_ABI simd() = default; + _LIBCPP_HIDE_FROM_ABI simd(const simd&) = default; + _LIBCPP_HIDE_FROM_ABI simd& operator=(const simd&) = default; - static constexpr size_t size() noexcept { + static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return simd_size<_Tp, _Abi>::value; } @@ -1362,7 +1362,7 @@ private: __simd_storage<_Tp, _Abi> __s_; template <class _Up> - static constexpr bool __can_broadcast() { + static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_broadcast() { return (std::is_arithmetic<_Up>::value && __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()) || (!std::is_arithmetic<_Up>::value && @@ -1374,7 +1374,7 @@ private: } template <class _Generator, size_t... __indicies> - static constexpr decltype( + static _LIBCPP_HIDE_FROM_ABI constexpr decltype( std::forward_as_tuple(std::declval<_Generator>()( std::integral_constant<size_t, __indicies>())...), bool()) @@ -1385,12 +1385,12 @@ private: } template <class _Generator> - static bool __can_generate(...) { + static _LIBCPP_HIDE_FROM_ABI bool __can_generate(...) { return false; } template <class _Generator, size_t... __indicies> - void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) { + _LIBCPP_HIDE_FROM_ABI void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) { int __not_used[]{((*this)[__indicies] = __g(std::integral_constant<size_t, __indicies>()), 0)...}; @@ -1403,7 +1403,7 @@ public: class = typename std::enable_if< std::is_same<_Abi, simd_abi::fixed_size<size()>>::value && __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()>::type> - simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) { + _LIBCPP_HIDE_FROM_ABI simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) { for (size_t __i = 0; __i < size(); __i++) { (*this)[__i] = static_cast<_Tp>(__v[__i]); } @@ -1412,7 +1412,7 @@ public: // implicit broadcast constructor template <class _Up, class = typename std::enable_if<__can_broadcast<_Up>()>::type> - simd(_Up&& __rv) { + _LIBCPP_HIDE_FROM_ABI simd(_Up&& __rv) { auto __v = static_cast<_Tp>(__rv); for (size_t __i = 0; __i < size(); __i++) { (*this)[__i] = __v; @@ -1424,7 +1424,7 @@ public: int = typename std::enable_if< __can_generate<_Generator>(std::make_index_sequence<size()>()), int>::type()> - explicit simd(_Generator&& __g) { + explicit _LIBCPP_HIDE_FROM_ABI simd(_Generator&& __g) { __generator_init(std::forward<_Generator>(__g), std::make_index_sequence<size()>()); } @@ -1434,7 +1434,7 @@ public: class _Up, class _Flags, class = typename std::enable_if<__vectorizable<_Up>()>::type, class = typename std::enable_if<is_simd_flag_type<_Flags>::value>::type> - simd(const _Up* __buffer, _Flags) { + _LIBCPP_HIDE_FROM_ABI simd(const _Up* __buffer, _Flags) { // TODO: optimize for overaligned flags for (size_t __i = 0; __i < size(); __i++) { (*this)[__i] = static_cast<_Tp>(__buffer[__i]); @@ -1445,7 +1445,7 @@ public: template <class _Up, class _Flags> typename std::enable_if<__vectorizable<_Up>() && is_simd_flag_type<_Flags>::value>::type - copy_from(const _Up* __buffer, _Flags) { + _LIBCPP_HIDE_FROM_ABI copy_from(const _Up* __buffer, _Flags) { *this = simd(__buffer, _Flags()); } @@ -1453,7 +1453,7 @@ public: template <class _Up, class _Flags> typename std::enable_if<__vectorizable<_Up>() && is_simd_flag_type<_Flags>::value>::type - copy_to(_Up* __buffer, _Flags) const { + _LIBCPP_HIDE_FROM_ABI copy_to(_Up* __buffer, _Flags) const { // TODO: optimize for overaligned flags for (size_t __i = 0; __i < size(); __i++) { __buffer[__i] = static_cast<_Up>((*this)[__i]); @@ -1461,9 +1461,9 @@ public: } // scalar access [simd.subscr] - reference operator[](size_t __i) { return reference(&__s_, __i); } + _LIBCPP_HIDE_FROM_ABI reference operator[](size_t __i) { return reference(&__s_, __i); } - value_type operator[](size_t __i) const { return __s_.__get(__i); } + _LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const { return __s_.__get(__i); } // unary operators [simd.unary] simd& operator++(); @@ -1526,7 +1526,7 @@ public: using simd_type = simd<_Tp, _Abi>; using abi_type = _Abi; static constexpr size_t size() noexcept; - simd_mask() = default; + _LIBCPP_HIDE_FROM_ABI simd_mask() = default; // broadcast constructor explicit simd_mask(value_type) noexcept; diff --git a/libcxx/include/experimental/type_traits b/libcxx/include/experimental/type_traits index dd4c53963640..bebd86d54da3 100644 --- a/libcxx/include/experimental/type_traits +++ b/libcxx/include/experimental/type_traits @@ -71,7 +71,7 @@ inline namespace fundamentals_v1 { #include <__assert> // all public C++ headers provide the assertion handler #include <experimental/__config> -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 #include <initializer_list> #include <type_traits> @@ -132,24 +132,24 @@ template <template<class...> class _Op, class... _Args> template <template<class...> class _Op, class... _Args> _LIBCPP_CONSTEXPR bool is_detected_v = is_detected<_Op, _Args...>::value; -template <class Default, template<class...> class _Op, class... _Args> - using detected_or = _DETECTOR<Default, void, _Op, _Args...>; -template <class Default, template<class...> class _Op, class... _Args> - using detected_or_t = typename detected_or<Default, _Op, _Args...>::type; +template <class _Default, template<class...> class _Op, class... _Args> + using detected_or = _DETECTOR<_Default, void, _Op, _Args...>; +template <class _Default, template<class...> class _Op, class... _Args> + using detected_or_t = typename detected_or<_Default, _Op, _Args...>::type; -template <class Expected, template<class...> class _Op, class... _Args> - using is_detected_exact = is_same<Expected, detected_t<_Op, _Args...>>; -template <class Expected, template<class...> class _Op, class... _Args> - _LIBCPP_CONSTEXPR bool is_detected_exact_v = is_detected_exact<Expected, _Op, _Args...>::value; +template <class _Expected, template<class...> class _Op, class... _Args> + using is_detected_exact = is_same<_Expected, detected_t<_Op, _Args...>>; +template <class _Expected, template<class...> class _Op, class... _Args> + _LIBCPP_CONSTEXPR bool is_detected_exact_v = is_detected_exact<_Expected, _Op, _Args...>::value; -template <class To, template<class...> class _Op, class... _Args> - using is_detected_convertible = is_convertible<detected_t<_Op, _Args...>, To>; -template <class To, template<class...> class _Op, class... _Args> - _LIBCPP_CONSTEXPR bool is_detected_convertible_v = is_detected_convertible<To, _Op, _Args...>::value; +template <class _To, template<class...> class _Op, class... _Args> + using is_detected_convertible = is_convertible<detected_t<_Op, _Args...>, _To>; +template <class _To, template<class...> class _Op, class... _Args> + _LIBCPP_CONSTEXPR bool is_detected_convertible_v = is_detected_convertible<_To, _Op, _Args...>::value; _LIBCPP_END_NAMESPACE_LFTS -#endif /* _LIBCPP_STD_VER > 11 */ +#endif /* _LIBCPP_STD_VER >= 14 */ #endif /* _LIBCPP_EXPERIMENTAL_TYPE_TRAITS */ diff --git a/libcxx/include/ext/hash_map b/libcxx/include/ext/hash_map index 3ad4b166865a..116b6a72f2c1 100644 --- a/libcxx/include/ext/hash_map +++ b/libcxx/include/ext/hash_map @@ -208,7 +208,6 @@ template <class Key, class T, class Hash, class Pred, class Alloc> #include <ext/__hash> #include <functional> #include <stdexcept> -#include <type_traits> #if defined(__DEPRECATED) && __DEPRECATED #if defined(_LIBCPP_WARNING) @@ -324,7 +323,7 @@ public: bool __first_constructed; bool __second_constructed; - __hash_map_node_destructor(__hash_map_node_destructor const&) = default; + _LIBCPP_HIDE_FROM_ABI __hash_map_node_destructor(__hash_map_node_destructor const&) = default; __hash_map_node_destructor& operator=(const __hash_map_node_destructor&) = delete; _LIBCPP_INLINE_VISIBILITY @@ -508,23 +507,23 @@ public: typedef __hash_map_const_iterator<typename __table::const_iterator> const_iterator; _LIBCPP_INLINE_VISIBILITY hash_map() { } - explicit hash_map(size_type __n, const hasher& __hf = hasher(), + explicit _LIBCPP_HIDE_FROM_ABI hash_map(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - hash_map(size_type __n, const hasher& __hf, + _LIBCPP_HIDE_FROM_ABI hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template <class _InputIterator> - hash_map(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI hash_map(_InputIterator __first, _InputIterator __last); template <class _InputIterator> - hash_map(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI hash_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template <class _InputIterator> - hash_map(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI hash_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); - hash_map(const hash_map& __u); + _LIBCPP_HIDE_FROM_ABI hash_map(const hash_map& __u); _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const @@ -588,7 +587,7 @@ public: std::pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {return __table_.__equal_range_unique(__k);} - mapped_type& operator[](const key_type& __k); + _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __k); _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const {return __table_.bucket_count();} @@ -603,7 +602,7 @@ public: void resize(size_type __n) {__table_.__rehash_unique(__n);} private: - __node_holder __construct_node(const key_type& __k); + _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(const key_type& __k); }; template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> @@ -780,23 +779,23 @@ public: _LIBCPP_INLINE_VISIBILITY hash_multimap() { } - explicit hash_multimap(size_type __n, const hasher& __hf = hasher(), + explicit _LIBCPP_HIDE_FROM_ABI hash_multimap(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - hash_multimap(size_type __n, const hasher& __hf, + _LIBCPP_HIDE_FROM_ABI hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template <class _InputIterator> - hash_multimap(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI hash_multimap(_InputIterator __first, _InputIterator __last); template <class _InputIterator> - hash_multimap(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI hash_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template <class _InputIterator> - hash_multimap(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI hash_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); - hash_multimap(const hash_multimap& __u); + _LIBCPP_HIDE_FROM_ABI hash_multimap(const hash_multimap& __u); _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const @@ -985,6 +984,7 @@ operator!=(const hash_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> # include <iterator> +# include <type_traits> #endif #endif // _LIBCPP_HASH_MAP diff --git a/libcxx/include/ext/hash_set b/libcxx/include/ext/hash_set index dc8b78645384..c0c2ba241206 100644 --- a/libcxx/include/ext/hash_set +++ b/libcxx/include/ext/hash_set @@ -244,21 +244,21 @@ public: _LIBCPP_INLINE_VISIBILITY hash_set() { } - explicit hash_set(size_type __n, const hasher& __hf = hasher(), + _LIBCPP_HIDE_FROM_ABI explicit hash_set(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, + _LIBCPP_HIDE_FROM_ABI hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template <class _InputIterator> - hash_set(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI hash_set(_InputIterator __first, _InputIterator __last); template <class _InputIterator> - hash_set(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI hash_set(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template <class _InputIterator> - hash_set(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI hash_set(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); - hash_set(const hash_set& __u); + _LIBCPP_HIDE_FROM_ABI hash_set(const hash_set& __u); _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const @@ -465,21 +465,21 @@ public: _LIBCPP_INLINE_VISIBILITY hash_multiset() { } - explicit hash_multiset(size_type __n, const hasher& __hf = hasher(), + explicit _LIBCPP_HIDE_FROM_ABI hash_multiset(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - hash_multiset(size_type __n, const hasher& __hf, + _LIBCPP_HIDE_FROM_ABI hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template <class _InputIterator> - hash_multiset(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI hash_multiset(_InputIterator __first, _InputIterator __last); template <class _InputIterator> - hash_multiset(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI hash_multiset(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template <class _InputIterator> - hash_multiset(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI hash_multiset(_InputIterator __first, _InputIterator __last, size_type __n , const hasher& __hf, const key_equal& __eql, const allocator_type& __a); - hash_multiset(const hash_multiset& __u); + _LIBCPP_HIDE_FROM_ABI hash_multiset(const hash_multiset& __u); _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const @@ -665,6 +665,7 @@ operator!=(const hash_multiset<_Value, _Hash, _Pred, _Alloc>& __x, #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> # include <iterator> +# include <type_traits> #endif #endif // _LIBCPP_HASH_SET diff --git a/libcxx/include/filesystem b/libcxx/include/filesystem index 7efa4ed2b39f..99ba713ad07b 100644 --- a/libcxx/include/filesystem +++ b/libcxx/include/filesystem @@ -159,6 +159,9 @@ void swap(path& lhs, path& rhs) noexcept; size_t hash_value(const path& p) noexcept; + // [fs.path.hash], hash support + template<> struct hash<filesystem::path>; + template <class Source> path u8path(const Source& source); template <class InputIterator> @@ -233,19 +236,120 @@ friend class directory_iterator; // exposition only }; - class directory_iterator; + class directory_iterator { + public: + using iterator_category = input_iterator_tag; + using value_type = directory_entry; + using difference_type = ptrdiff_t; + using pointer = const directory_entry*; + using reference = const directory_entry&; + + // [fs.dir.itr.members], member functions + directory_iterator() noexcept; + explicit directory_iterator(const path& p); + directory_iterator(const path& p, directory_options options); + directory_iterator(const path& p, error_code& ec); + directory_iterator(const path& p, directory_options options, + error_code& ec); + directory_iterator(const directory_iterator& rhs); + directory_iterator(directory_iterator&& rhs) noexcept; + ~directory_iterator(); + + directory_iterator& operator=(const directory_iterator& rhs); + directory_iterator& operator=(directory_iterator&& rhs) noexcept; + + const directory_entry& operator*() const; + const directory_entry* operator->() const; + directory_iterator& operator++(); + directory_iterator& increment(error_code& ec); + + bool operator==(default_sentinel_t) const noexcept { // since C++20 + return *this == directory_iterator(); + } + + // other members as required by [input.iterators], input iterators + }; // enable directory_iterator range-based for statements directory_iterator begin(directory_iterator iter) noexcept; directory_iterator end(directory_iterator) noexcept; - class recursive_directory_iterator; +class recursive_directory_iterator { + public: + using iterator_category = input_iterator_tag; + using value_type = directory_entry; + using difference_type = ptrdiff_t; + using pointer = const directory_entry*; + using reference = const directory_entry&; + + // [fs.rec.dir.itr.members], constructors and destructor + recursive_directory_iterator() noexcept; + explicit recursive_directory_iterator(const path& p); + recursive_directory_iterator(const path& p, directory_options options); + recursive_directory_iterator(const path& p, directory_options options, + error_code& ec); + recursive_directory_iterator(const path& p, error_code& ec); + recursive_directory_iterator(const recursive_directory_iterator& rhs); + recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept; + ~recursive_directory_iterator(); + + // [fs.rec.dir.itr.members], observers + directory_options options() const; + int depth() const; + bool recursion_pending() const; + + const directory_entry& operator*() const; + const directory_entry* operator->() const; + + // [fs.rec.dir.itr.members], modifiers + recursive_directory_iterator& + operator=(const recursive_directory_iterator& rhs); + recursive_directory_iterator& + operator=(recursive_directory_iterator&& rhs) noexcept; + + recursive_directory_iterator& operator++(); + recursive_directory_iterator& increment(error_code& ec); + + void pop(); + void pop(error_code& ec); + void disable_recursion_pending(); + + bool operator==(default_sentinel_t) const noexcept { // since C++20 + return *this == recursive_directory_iterator(); + } + + // other members as required by [input.iterators], input iterators + }; // enable recursive_directory_iterator range-based for statements recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept; recursive_directory_iterator end(recursive_directory_iterator) noexcept; - class file_status; + class file_status { + public: + // [fs.file.status.cons], constructors and destructor + file_status() noexcept : file_status(file_type::none) {} + explicit file_status(file_type ft, + perms prms = perms::unknown) noexcept; + file_status(const file_status&) noexcept = default; + file_status(file_status&&) noexcept = default; + ~file_status(); + + // assignments + file_status& operator=(const file_status&) noexcept = default; + file_status& operator=(file_status&&) noexcept = default; + + // [fs.file.status.mods], modifiers + void type(file_type ft) noexcept; + void permissions(perms prms) noexcept; + + // [fs.file.status.obs], observers + file_type type() const noexcept; + perms permissions() const noexcept; + + friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept + { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); } // C++20 + }; struct space_info { @@ -454,16 +558,14 @@ inline constexpr bool std::ranges::enable_view<std::filesystem::recursive_direct // [fs.filesystem.syn] #include <compare> -#if defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) -# error "The <filesystem> library is not supported since libc++ has been configured without support for a filesystem." -#endif - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> +# include <cstdlib> +# include <system_error> #endif #endif // _LIBCPP_FILESYSTEM diff --git a/libcxx/include/format b/libcxx/include/format index 2c583c1065ba..c48bcf6e8403 100644 --- a/libcxx/include/format +++ b/libcxx/include/format @@ -170,11 +170,6 @@ namespace std { */ #include <__assert> // all public C++ headers provide the assertion handler -// Make sure all feature-test macros are available. -#include <version> -// Enable the contents of the header only when libc++ was built with experimental features enabled. -#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) - #include <__config> #include <__format/buffer.h> #include <__format/concepts.h> @@ -202,11 +197,10 @@ namespace std { #include <__format/range_default_formatter.h> #include <__format/range_formatter.h> #include <__format/unicode.h> +#include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) - #endif // _LIBCPP_FORMAT diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list index 61dde8167dfc..6cb794070b7b 100644 --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -44,6 +44,8 @@ public: forward_list(InputIterator first, InputIterator last); template <class InputIterator> forward_list(InputIterator first, InputIterator last, const allocator_type& a); + template<container-compatible-range<T> R> + forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); // C++23 forward_list(const forward_list& x); forward_list(const forward_list& x, const allocator_type& a); forward_list(forward_list&& x) @@ -63,6 +65,8 @@ public: template <class InputIterator> void assign(InputIterator first, InputIterator last); + template<container-compatible-range<T> R> + void assign_range(R&& rg); // C++23 void assign(size_type n, const value_type& v); void assign(initializer_list<value_type> il); @@ -89,6 +93,8 @@ public: template <class... Args> reference emplace_front(Args&&... args); // reference in C++17 void push_front(const value_type& v); void push_front(value_type&& v); + template<container-compatible-range<T> R> + void prepend_range(R&& rg); // C++23 void pop_front(); @@ -100,6 +106,8 @@ public: template <class InputIterator> iterator insert_after(const_iterator p, InputIterator first, InputIterator last); + template<container-compatible-range<T> R> + iterator insert_range_after(const_iterator position, R&& rg); // C++23 iterator insert_after(const_iterator p, initializer_list<value_type> il); iterator erase_after(const_iterator p); @@ -140,29 +148,37 @@ template <class InputIterator, class Allocator = allocator<typename iterator_tra forward_list(InputIterator, InputIterator, Allocator = Allocator()) -> forward_list<typename iterator_traits<InputIterator>::value_type, Allocator>; // C++17 +template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> + forward_list(from_range_t, R&&, Allocator = Allocator()) + -> forward_list<ranges::range_value_t<R>, Allocator>; // C++23 + template <class T, class Allocator> bool operator==(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y); template <class T, class Allocator> bool operator< (const forward_list<T, Allocator>& x, - const forward_list<T, Allocator>& y); + const forward_list<T, Allocator>& y); // removed in C++20 template <class T, class Allocator> bool operator!=(const forward_list<T, Allocator>& x, - const forward_list<T, Allocator>& y); + const forward_list<T, Allocator>& y); // removed in C++20 template <class T, class Allocator> bool operator> (const forward_list<T, Allocator>& x, - const forward_list<T, Allocator>& y); + const forward_list<T, Allocator>& y); // removed in C++20 template <class T, class Allocator> bool operator>=(const forward_list<T, Allocator>& x, - const forward_list<T, Allocator>& y); + const forward_list<T, Allocator>& y); // removed in C++20 template <class T, class Allocator> bool operator<=(const forward_list<T, Allocator>& x, - const forward_list<T, Allocator>& y); + const forward_list<T, Allocator>& y); // removed in C++20 + +template<class T, class Allocator> + synth-three-way-result<T> operator<=>(const forward_list<T, Allocator>& x, + const forward_list<T, Allocator>& y); // since C++20 template <class T, class Allocator> void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y) @@ -181,14 +197,17 @@ template <class T, class Allocator, class Predicate> #include <__algorithm/comp.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/min.h> #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> #include <__config> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/move_iterator.h> #include <__iterator/next.h> #include <__memory/addressof.h> +#include <__memory/allocation_guard.h> #include <__memory/allocator.h> #include <__memory/allocator_destructor.h> #include <__memory/allocator_traits.h> @@ -197,11 +216,22 @@ template <class T, class Allocator, class Predicate> #include <__memory/swap_allocator.h> #include <__memory/unique_ptr.h> #include <__memory_resource/polymorphic_allocator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> +#include <__type_traits/conditional.h> #include <__type_traits/is_allocator.h> +#include <__type_traits/is_const.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_same.h> +#include <__type_traits/type_identity.h> #include <__utility/forward.h> #include <__utility/move.h> #include <limits> -#include <type_traits> #include <version> // standard-mandated includes @@ -279,6 +309,7 @@ struct __forward_begin_node pointer __next_; _LIBCPP_INLINE_VISIBILITY __forward_begin_node() : __next_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY explicit __forward_begin_node(pointer __n) : __next_(__n) {} _LIBCPP_INLINE_VISIBILITY __begin_node_pointer __next_as_begin() const { @@ -294,8 +325,13 @@ struct _LIBCPP_STANDALONE_DEBUG __forward_list_node : public __begin_node_of<_Tp, _VoidPtr> { typedef _Tp value_type; + typedef __begin_node_of<_Tp, _VoidPtr> _Base; + typedef typename _Base::pointer _NodePtr; value_type __value_; + + _LIBCPP_HIDE_FROM_ABI __forward_list_node() = default; + _LIBCPP_HIDE_FROM_ABI __forward_list_node(const value_type& __v, _NodePtr __next) : _Base(__next), __value_(__v) {} }; @@ -395,11 +431,11 @@ class _LIBCPP_TEMPLATE_VIS __forward_list_const_iterator __iter_node_pointer __ptr_; - __begin_node_pointer __get_begin() const { + _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __get_begin() const { return static_cast<__begin_node_pointer>( static_cast<__void_pointer>(__ptr_)); } - __node_pointer __get_unsafe_node_pointer() const { + _LIBCPP_HIDE_FROM_ABI __node_pointer __get_unsafe_node_pointer() const { return static_cast<__node_pointer>( static_cast<__void_pointer>(__ptr_)); } @@ -482,14 +518,6 @@ protected: typedef typename allocator_traits<__begin_node_allocator>::pointer __begin_node_pointer; - static_assert((!is_same<allocator_type, __node_allocator>::value), - "internal allocator type must differ from user-specified " - "type; otherwise overload resolution breaks"); - - static_assert(is_same<allocator_type, __rebind_alloc<__node_traits, value_type> >::value, - "[allocator.requirements] states that rebinding an allocator to the same type should result in the " - "original allocator"); - __compressed_pair<__begin_node, __node_allocator> __before_begin_; _LIBCPP_INLINE_VISIBILITY @@ -533,7 +561,7 @@ private: __forward_list_base& operator=(const __forward_list_base&); public: - ~__forward_list_base(); + _LIBCPP_HIDE_FROM_ABI ~__forward_list_base(); protected: _LIBCPP_INLINE_VISIBILITY @@ -558,7 +586,7 @@ public: __is_nothrow_swappable<__node_allocator>::value); #endif protected: - void clear() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT; private: _LIBCPP_INLINE_VISIBILITY @@ -659,9 +687,17 @@ public: typedef _Tp value_type; typedef _Alloc allocator_type; - static_assert((is_same<typename allocator_type::value_type, value_type>::value), + static_assert(is_same<value_type, typename allocator_type::value_type>::value, "Allocator::value_type must be same type as value_type"); + static_assert(is_same<allocator_type, __rebind_alloc<allocator_traits<allocator_type>, value_type> >::value, + "[allocator.requirements] states that rebinding an allocator to the same type should result in the " + "original allocator"); + + static_assert((!is_same<allocator_type, __node_allocator>::value), + "internal allocator type must differ from user-specified " + "type; otherwise overload resolution breaks"); + typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits<allocator_type>::pointer pointer; @@ -671,7 +707,7 @@ public: typedef typename base::iterator iterator; typedef typename base::const_iterator const_iterator; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef size_type __remove_return_type; #else typedef void __remove_return_type; @@ -683,39 +719,48 @@ public: {} // = default; _LIBCPP_INLINE_VISIBILITY explicit forward_list(const allocator_type& __a); - explicit forward_list(size_type __n); -#if _LIBCPP_STD_VER > 11 - explicit forward_list(size_type __n, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI explicit forward_list(size_type __n); +#if _LIBCPP_STD_VER >= 14 + _LIBCPP_HIDE_FROM_ABI explicit forward_list(size_type __n, const allocator_type& __a); #endif - forward_list(size_type __n, const value_type& __v); + _LIBCPP_HIDE_FROM_ABI forward_list(size_type __n, const value_type& __v); template <class = __enable_if_t<__is_allocator<_Alloc>::value> > - forward_list(size_type __n, const value_type& __v, const allocator_type& __a) : base(__a) + _LIBCPP_HIDE_FROM_ABI forward_list(size_type __n, const value_type& __v, const allocator_type& __a) : base(__a) { insert_after(cbefore_begin(), __n, __v); } template <class _InputIterator> - forward_list(_InputIterator __f, _InputIterator __l, - __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>* = nullptr); + _LIBCPP_HIDE_FROM_ABI forward_list(_InputIterator __f, _InputIterator __l, + __enable_if_t<__has_input_iterator_category<_InputIterator>::value>* = nullptr); template <class _InputIterator> - forward_list(_InputIterator __f, _InputIterator __l, + _LIBCPP_HIDE_FROM_ABI forward_list(_InputIterator __f, _InputIterator __l, const allocator_type& __a, - __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>* = nullptr); - forward_list(const forward_list& __x); - forward_list(const forward_list& __x, const __type_identity_t<allocator_type>& __a); + __enable_if_t<__has_input_iterator_category<_InputIterator>::value>* = nullptr); - forward_list& operator=(const forward_list& __x); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI forward_list(from_range_t, _Range&& __range, + const allocator_type& __a = allocator_type()) : base(__a) { + prepend_range(std::forward<_Range>(__range)); + } +#endif + + _LIBCPP_HIDE_FROM_ABI forward_list(const forward_list& __x); + _LIBCPP_HIDE_FROM_ABI forward_list(const forward_list& __x, const __type_identity_t<allocator_type>& __a); + + _LIBCPP_HIDE_FROM_ABI forward_list& operator=(const forward_list& __x); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY forward_list(forward_list&& __x) _NOEXCEPT_(is_nothrow_move_constructible<base>::value) : base(_VSTD::move(__x)) {} - forward_list(forward_list&& __x, const __type_identity_t<allocator_type>& __a); + _LIBCPP_HIDE_FROM_ABI forward_list(forward_list&& __x, const __type_identity_t<allocator_type>& __a); - forward_list(initializer_list<value_type> __il); - forward_list(initializer_list<value_type> __il, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI forward_list(initializer_list<value_type> __il); + _LIBCPP_HIDE_FROM_ABI forward_list(initializer_list<value_type> __il, const allocator_type& __a); _LIBCPP_INLINE_VISIBILITY forward_list& operator=(forward_list&& __x) @@ -733,9 +778,18 @@ public: // ~forward_list() = default; template <class _InputIterator> - __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void> - assign(_InputIterator __f, _InputIterator __l); - void assign(size_type __n, const value_type& __v); + __enable_if_t<__has_input_iterator_category<_InputIterator>::value, void> + _LIBCPP_HIDE_FROM_ABI assign(_InputIterator __f, _InputIterator __l); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void assign_range(_Range&& __range) { + __assign_with_sentinel(ranges::begin(__range), ranges::end(__range)); + } +#endif + + _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const value_type& __v); _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT @@ -787,34 +841,56 @@ public: const_reference front() const {return base::__before_begin()->__next_->__value_;} #ifndef _LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 14 - template <class... _Args> reference emplace_front(_Args&&... __args); +#if _LIBCPP_STD_VER >= 17 + template <class... _Args> + _LIBCPP_HIDE_FROM_ABI reference emplace_front(_Args&&... __args); #else - template <class... _Args> void emplace_front(_Args&&... __args); + template <class... _Args> + _LIBCPP_HIDE_FROM_ABI void emplace_front(_Args&&... __args); #endif - void push_front(value_type&& __v); + _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __v); #endif // _LIBCPP_CXX03_LANG - void push_front(const value_type& __v); + _LIBCPP_HIDE_FROM_ABI void push_front(const value_type& __v); - void pop_front(); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void prepend_range(_Range&& __range) { + insert_range_after(cbefore_begin(), std::forward<_Range>(__range)); + } +#endif + + _LIBCPP_HIDE_FROM_ABI void pop_front(); #ifndef _LIBCPP_CXX03_LANG template <class... _Args> - iterator emplace_after(const_iterator __p, _Args&&... __args); + _LIBCPP_HIDE_FROM_ABI iterator emplace_after(const_iterator __p, _Args&&... __args); - iterator insert_after(const_iterator __p, value_type&& __v); - iterator insert_after(const_iterator __p, initializer_list<value_type> __il) + _LIBCPP_HIDE_FROM_ABI iterator insert_after(const_iterator __p, value_type&& __v); + _LIBCPP_HIDE_FROM_ABI iterator insert_after(const_iterator __p, initializer_list<value_type> __il) {return insert_after(__p, __il.begin(), __il.end());} #endif // _LIBCPP_CXX03_LANG - iterator insert_after(const_iterator __p, const value_type& __v); - iterator insert_after(const_iterator __p, size_type __n, const value_type& __v); + _LIBCPP_HIDE_FROM_ABI iterator insert_after(const_iterator __p, const value_type& __v); + _LIBCPP_HIDE_FROM_ABI iterator insert_after(const_iterator __p, size_type __n, const value_type& __v); template <class _InputIterator> _LIBCPP_INLINE_VISIBILITY - __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, iterator> + __enable_if_t<__has_input_iterator_category<_InputIterator>::value, iterator> insert_after(const_iterator __p, _InputIterator __f, _InputIterator __l); - iterator erase_after(const_iterator __p); - iterator erase_after(const_iterator __f, const_iterator __l); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + iterator insert_range_after(const_iterator __position, _Range&& __range) { + return __insert_after_with_sentinel(__position, ranges::begin(__range), ranges::end(__range)); + } +#endif + + template <class _InputIterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI + iterator __insert_after_with_sentinel(const_iterator __p, _InputIterator __f, _Sentinel __l); + + _LIBCPP_HIDE_FROM_ABI iterator erase_after(const_iterator __p); + _LIBCPP_HIDE_FROM_ABI iterator erase_after(const_iterator __f, const_iterator __l); _LIBCPP_INLINE_VISIBILITY void swap(forward_list& __x) @@ -826,8 +902,8 @@ public: #endif {base::swap(__x);} - void resize(size_type __n); - void resize(size_type __n, const value_type& __v); + _LIBCPP_HIDE_FROM_ABI void resize(size_type __n); + _LIBCPP_HIDE_FROM_ABI void resize(size_type __n, const value_type& __v); _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {base::clear();} @@ -838,46 +914,54 @@ public: _LIBCPP_INLINE_VISIBILITY void splice_after(const_iterator __p, forward_list&& __x, const_iterator __f, const_iterator __l); - void splice_after(const_iterator __p, forward_list& __x); - void splice_after(const_iterator __p, forward_list& __x, const_iterator __i); - void splice_after(const_iterator __p, forward_list& __x, + _LIBCPP_HIDE_FROM_ABI void splice_after(const_iterator __p, forward_list& __x); + _LIBCPP_HIDE_FROM_ABI void splice_after(const_iterator __p, forward_list& __x, const_iterator __i); + _LIBCPP_HIDE_FROM_ABI void splice_after(const_iterator __p, forward_list& __x, const_iterator __f, const_iterator __l); - __remove_return_type remove(const value_type& __v); - template <class _Predicate> __remove_return_type remove_if(_Predicate __pred); + _LIBCPP_HIDE_FROM_ABI __remove_return_type remove(const value_type& __v); + template <class _Predicate> + _LIBCPP_HIDE_FROM_ABI __remove_return_type remove_if(_Predicate __pred); _LIBCPP_INLINE_VISIBILITY __remove_return_type unique() { return unique(__equal_to()); } - template <class _BinaryPredicate> __remove_return_type unique(_BinaryPredicate __binary_pred); + template <class _BinaryPredicate> + _LIBCPP_HIDE_FROM_ABI __remove_return_type unique(_BinaryPredicate __binary_pred); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY - void merge(forward_list&& __x) {merge(__x, __less<value_type>());} + void merge(forward_list&& __x) {merge(__x, __less<>());} template <class _Compare> _LIBCPP_INLINE_VISIBILITY void merge(forward_list&& __x, _Compare __comp) {merge(__x, _VSTD::move(__comp));} #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY - void merge(forward_list& __x) {merge(__x, __less<value_type>());} - template <class _Compare> void merge(forward_list& __x, _Compare __comp); + void merge(forward_list& __x) {merge(__x, __less<>());} + template <class _Compare> + _LIBCPP_HIDE_FROM_ABI void merge(forward_list& __x, _Compare __comp); _LIBCPP_INLINE_VISIBILITY - void sort() {sort(__less<value_type>());} + void sort() {sort(__less<>());} template <class _Compare> _LIBCPP_INLINE_VISIBILITY void sort(_Compare __comp); - void reverse() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void reverse() _NOEXCEPT; private: #ifndef _LIBCPP_CXX03_LANG - void __move_assign(forward_list& __x, true_type) + _LIBCPP_HIDE_FROM_ABI void __move_assign(forward_list& __x, true_type) _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value); - void __move_assign(forward_list& __x, false_type); + _LIBCPP_HIDE_FROM_ABI void __move_assign(forward_list& __x, false_type); #endif // _LIBCPP_CXX03_LANG + template <class _Iter, class _Sent> + _LIBCPP_HIDE_FROM_ABI + void __assign_with_sentinel(_Iter __f, _Sent __l); + template <class _Compare> - static + static _LIBCPP_HIDE_FROM_ABI __node_pointer __merge(__node_pointer __f1, __node_pointer __f2, _Compare& __comp); + // TODO: Make this _LIBCPP_HIDE_FROM_ABI template <class _Compare> - static + static _LIBCPP_HIDDEN __node_pointer __sort(__node_pointer __f, difference_type __sz, _Compare& __comp); }; @@ -886,7 +970,7 @@ private: #if _LIBCPP_STD_VER >= 17 template<class _InputIterator, class _Alloc = allocator<__iter_value_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Alloc>::value> > forward_list(_InputIterator, _InputIterator) @@ -894,13 +978,22 @@ forward_list(_InputIterator, _InputIterator) template<class _InputIterator, class _Alloc, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Alloc>::value> > forward_list(_InputIterator, _InputIterator, _Alloc) -> forward_list<__iter_value_type<_InputIterator>, _Alloc>; #endif +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, + class _Alloc = allocator<ranges::range_value_t<_Range>>, + class = enable_if_t<__is_allocator<_Alloc>::value> + > +forward_list(from_range_t, _Range&&, _Alloc = _Alloc()) + -> forward_list<ranges::range_value_t<_Range>, _Alloc>; +#endif + template <class _Tp, class _Alloc> inline forward_list<_Tp, _Alloc>::forward_list(const allocator_type& __a) @@ -927,7 +1020,7 @@ forward_list<_Tp, _Alloc>::forward_list(size_type __n) } } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp, class _Alloc> forward_list<_Tp, _Alloc>::forward_list(size_type __n, const allocator_type& __base_alloc) @@ -959,7 +1052,7 @@ forward_list<_Tp, _Alloc>::forward_list(size_type __n, const value_type& __v) template <class _Tp, class _Alloc> template <class _InputIterator> forward_list<_Tp, _Alloc>::forward_list(_InputIterator __f, _InputIterator __l, - __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>*) + __enable_if_t<__has_input_iterator_category<_InputIterator>::value>*) { insert_after(cbefore_begin(), __f, __l); } @@ -968,7 +1061,7 @@ template <class _Tp, class _Alloc> template <class _InputIterator> forward_list<_Tp, _Alloc>::forward_list(_InputIterator __f, _InputIterator __l, const allocator_type& __a, - __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>*) + __enable_if_t<__has_input_iterator_category<_InputIterator>::value>*) : base(__a) { insert_after(cbefore_begin(), __f, __l); @@ -1078,16 +1171,23 @@ forward_list<_Tp, _Alloc>::operator=(initializer_list<value_type> __il) template <class _Tp, class _Alloc> template <class _InputIterator> -__enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void> +__enable_if_t<__has_input_iterator_category<_InputIterator>::value, void> forward_list<_Tp, _Alloc>::assign(_InputIterator __f, _InputIterator __l) { + __assign_with_sentinel(__f, __l); +} + +template <class _Tp, class _Alloc> +template <class _Iter, class _Sent> +_LIBCPP_HIDE_FROM_ABI +void forward_list<_Tp, _Alloc>::__assign_with_sentinel(_Iter __f, _Sent __l) { iterator __i = before_begin(); iterator __j = _VSTD::next(__i); iterator __e = end(); for (; __j != __e && __f != __l; ++__i, (void) ++__j, ++__f) *__j = *__f; if (__j == __e) - insert_after(__i, __f, __l); + __insert_after_with_sentinel(__i, std::move(__f), std::move(__l)); else erase_after(__i, __e); } @@ -1119,7 +1219,7 @@ forward_list<_Tp, _Alloc>::assign(initializer_list<value_type> __il) template <class _Tp, class _Alloc> template <class... _Args> -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typename forward_list<_Tp, _Alloc>::reference #else void @@ -1133,7 +1233,7 @@ forward_list<_Tp, _Alloc>::emplace_front(_Args&&... __args) _VSTD::forward<_Args>(__args)...); __h->__next_ = base::__before_begin()->__next_; base::__before_begin()->__next_ = __h.release(); -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return base::__before_begin()->__next_->__value_; #endif } @@ -1228,26 +1328,33 @@ typename forward_list<_Tp, _Alloc>::iterator forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, size_type __n, const value_type& __v) { + using _Guard = __allocation_guard<__node_allocator>; + __begin_node_pointer __r = __p.__get_begin(); if (__n > 0) { __node_allocator& __a = base::__alloc(); - typedef __allocator_destructor<__node_allocator> _Dp; - unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1)); - __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v); - __node_pointer __first = __h.release(); + + __node_pointer __first = nullptr; + { + _Guard __h(__a, 1); + __node_traits::construct(__a, std::addressof(__h.__get()->__value_), __v); + __h.__get()->__next_ = nullptr; + __first = __h.__release_ptr(); + } __node_pointer __last = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (--__n; __n != 0; --__n, __last = __last->__next_) { - __h.reset(__node_traits::allocate(__a, 1)); - __node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v); - __last->__next_ = __h.release(); + _Guard __h(__a, 1); + __node_traits::construct(__a, std::addressof(__h.__get()->__value_), __v); + __h.__get()->__next_ = nullptr; + __last->__next_ = __h.__release_ptr(); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1260,7 +1367,7 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, size_type __n, } throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __last->__next_ = __r->__next_; __r->__next_ = __first; __r = static_cast<__begin_node_pointer>(__last); @@ -1270,30 +1377,45 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, size_type __n, template <class _Tp, class _Alloc> template <class _InputIterator> -__enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, typename forward_list<_Tp, _Alloc>::iterator> +__enable_if_t<__has_input_iterator_category<_InputIterator>::value, typename forward_list<_Tp, _Alloc>::iterator> forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, _InputIterator __f, _InputIterator __l) { + return __insert_after_with_sentinel(__p, std::move(__f), std::move(__l)); +} + +template <class _Tp, class _Alloc> +template <class _InputIterator, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI +typename forward_list<_Tp, _Alloc>::iterator +forward_list<_Tp, _Alloc>::__insert_after_with_sentinel(const_iterator __p, _InputIterator __f, _Sentinel __l) { + using _Guard = __allocation_guard<__node_allocator>; __begin_node_pointer __r = __p.__get_begin(); + if (__f != __l) { __node_allocator& __a = base::__alloc(); - typedef __allocator_destructor<__node_allocator> _Dp; - unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1)); - __node_traits::construct(__a, _VSTD::addressof(__h->__value_), *__f); - __node_pointer __first = __h.release(); + __node_pointer __first = nullptr; + { + _Guard __h(__a, 1); + __node_traits::construct(__a, std::addressof(__h.__get()->__value_), *__f); + __h.__get()->__next_ = nullptr; + __first = __h.__release_ptr(); + } __node_pointer __last = __first; -#ifndef _LIBCPP_NO_EXCEPTIONS + +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (++__f; __f != __l; ++__f, ((void)(__last = __last->__next_))) { - __h.reset(__node_traits::allocate(__a, 1)); - __node_traits::construct(__a, _VSTD::addressof(__h->__value_), *__f); - __last->__next_ = __h.release(); + _Guard __h(__a, 1); + __node_traits::construct(__a, std::addressof(__h.__get()->__value_), *__f); + __h.__get()->__next_ = nullptr; + __last->__next_ = __h.__release_ptr(); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1306,11 +1428,13 @@ forward_list<_Tp, _Alloc>::insert_after(const_iterator __p, } throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + __last->__next_ = __r->__next_; __r->__next_ = __first; __r = static_cast<__begin_node_pointer>(__last); } + return iterator(__r); } @@ -1711,6 +1835,8 @@ bool operator==(const forward_list<_Tp, _Alloc>& __x, return (__ix == __ex) == (__iy == __ey); } +#if _LIBCPP_STD_VER <= 17 + template <class _Tp, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const forward_list<_Tp, _Alloc>& __x, @@ -1752,6 +1878,17 @@ bool operator<=(const forward_list<_Tp, _Alloc>& __x, return !(__y < __x); } +#else // #if _LIBCPP_STD_VER <= 17 + +template <class _Tp, class _Allocator> +_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Tp> +operator<=>(const forward_list<_Tp, _Allocator>& __x, const forward_list<_Tp, _Allocator>& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>); +} + +#endif // #if _LIBCPP_STD_VER <= 17 + template <class _Tp, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY void @@ -1761,7 +1898,7 @@ swap(forward_list<_Tp, _Alloc>& __x, forward_list<_Tp, _Alloc>& __y) __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Allocator, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY typename forward_list<_Tp, _Allocator>::size_type @@ -1779,11 +1916,11 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template <class _ValueT> -using forward_list = std::forward_list<_ValueT, polymorphic_allocator<_ValueT>>; +using forward_list _LIBCPP_AVAILABILITY_PMR = std::forward_list<_ValueT, polymorphic_allocator<_ValueT>>; } // namespace pmr _LIBCPP_END_NAMESPACE_STD #endif @@ -1794,9 +1931,11 @@ _LIBCPP_POP_MACROS # include <algorithm> # include <atomic> # include <concepts> +# include <cstdlib> # include <functional> # include <iosfwd> # include <iterator> +# include <type_traits> # include <typeinfo> #endif diff --git a/libcxx/include/fstream b/libcxx/include/fstream index 41e95bf3dc66..d30575e22a46 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -183,22 +183,18 @@ typedef basic_fstream<wchar_t> wfstream; #include <__assert> // all public C++ headers provide the assertion handler #include <__availability> #include <__config> +#include <__fwd/fstream.h> #include <__locale> #include <__utility/move.h> #include <__utility/swap.h> #include <__utility/unreachable.h> #include <cstdio> -#include <cstdlib> -#include <cstring> +#include <filesystem> #include <istream> #include <ostream> #include <typeinfo> #include <version> -#if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) -# include <filesystem> -#endif - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif @@ -210,7 +206,7 @@ _LIBCPP_PUSH_MACROS # define _LIBCPP_HAS_NO_OFF_T_FUNCTIONS #endif -#if !defined(_LIBCPP_HAS_NO_FSTREAM) +#if !defined(_LIBCPP_HAS_NO_FILESYSTEM) _LIBCPP_BEGIN_NAMESPACE_STD @@ -246,8 +242,8 @@ public: _LIBCPP_INLINE_VISIBILITY basic_filebuf* open(const string& __s, ios_base::openmode __mode); -#if _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) - _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_INLINE_VISIBILITY +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_INLINE_VISIBILITY basic_filebuf* open(const _VSTD_FS::path& __p, ios_base::openmode __mode) { return open(__p.c_str(), __mode); } @@ -398,17 +394,17 @@ basic_filebuf<_CharT, _Traits>::operator=(basic_filebuf&& __rhs) template <class _CharT, class _Traits> basic_filebuf<_CharT, _Traits>::~basic_filebuf() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS close(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (__owns_eb_) delete [] __extbuf_; if (__owns_ib_) @@ -754,8 +750,8 @@ basic_filebuf<_CharT, _Traits>::underflow() else { if (__extbufend_ != __extbufnext_) { - _LIBCPP_ASSERT(__extbufnext_ != nullptr, "underflow moving from nullptr"); - _LIBCPP_ASSERT(__extbuf_ != nullptr, "underflow moving into nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__extbufnext_ != nullptr, "underflow moving from nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__extbuf_ != nullptr, "underflow moving into nullptr"); _VSTD::memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_); } __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_); @@ -1169,8 +1165,8 @@ public: #endif _LIBCPP_INLINE_VISIBILITY explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in); -#if _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) - _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_INLINE_VISIBILITY +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_INLINE_VISIBILITY explicit basic_ifstream(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in) : basic_ifstream(__p.c_str(), __mode) {} #endif // _LIBCPP_STD_VER >= 17 @@ -1190,8 +1186,8 @@ public: void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in); #endif void open(const string& __s, ios_base::openmode __mode = ios_base::in); -#if _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) - _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_INLINE_VISIBILITY +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_INLINE_VISIBILITY void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in) { return open(__p.c_str(), __mode); @@ -1370,8 +1366,8 @@ public: _LIBCPP_INLINE_VISIBILITY explicit basic_ofstream(const string& __s, ios_base::openmode __mode = ios_base::out); -#if _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) - _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_INLINE_VISIBILITY +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_INLINE_VISIBILITY explicit basic_ofstream(const filesystem::path& __p, ios_base::openmode __mode = ios_base::out) : basic_ofstream(__p.c_str(), __mode) {} #endif // _LIBCPP_STD_VER >= 17 @@ -1393,8 +1389,8 @@ public: #endif void open(const string& __s, ios_base::openmode __mode = ios_base::out); -#if _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) - _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_INLINE_VISIBILITY +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_INLINE_VISIBILITY void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::out) { return open(__p.c_str(), __mode); } #endif // _LIBCPP_STD_VER >= 17 @@ -1571,8 +1567,8 @@ public: _LIBCPP_INLINE_VISIBILITY explicit basic_fstream(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out); -#if _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) - _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_INLINE_VISIBILITY +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_INLINE_VISIBILITY explicit basic_fstream(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in | ios_base::out) : basic_fstream(__p.c_str(), __mode) {} #endif // _LIBCPP_STD_VER >= 17 @@ -1590,14 +1586,14 @@ public: basic_filebuf<char_type, traits_type>* rdbuf() const; _LIBCPP_INLINE_VISIBILITY bool is_open() const; - void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); + _LIBCPP_HIDE_FROM_ABI void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); #ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); #endif - void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out); + _LIBCPP_HIDE_FROM_ABI void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out); -#if _LIBCPP_STD_VER >= 17 && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) - _LIBCPP_AVAILABILITY_FILESYSTEM _LIBCPP_INLINE_VISIBILITY +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_AVAILABILITY_FILESYSTEM_LIBRARY _LIBCPP_INLINE_VISIBILITY void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in|ios_base::out) { return open(__p.c_str(), __mode); } #endif // _LIBCPP_STD_VER >= 17 @@ -1746,13 +1742,14 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_filebuf<char>; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_HAS_NO_FSTREAM +#endif // _LIBCPP_HAS_NO_FILESYSTEM _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <atomic> # include <concepts> +# include <cstdlib> # include <iosfwd> # include <limits> # include <new> diff --git a/libcxx/include/functional b/libcxx/include/functional index 8589d3a9d6a9..5c60b9fc39f4 100644 --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -43,20 +43,22 @@ public: // construct/copy/destroy template<class U> - reference_wrapper(U&&); - reference_wrapper(const reference_wrapper<T>& x) noexcept; + constexpr reference_wrapper(U&&); // constexpr since C++20 + constexpr reference_wrapper(const reference_wrapper<T>& x) noexcept; // constexpr since C++20 // assignment - reference_wrapper& operator=(const reference_wrapper<T>& x) noexcept; + constexpr reference_wrapper& + operator=(const reference_wrapper<T>& x) noexcept; // constexpr since C++20 // access - operator T& () const noexcept; - T& get() const noexcept; + constexpr operator T& () const noexcept; // constexpr since C++20 + constexpr T& get() const noexcept; // constexpr since C++20 // invoke template <class... ArgTypes> - typename result_of<T&(ArgTypes&&...)>::type - operator() (ArgTypes&&...) const; + constexpr typename result_of<T&(ArgTypes&&...)>::type // constexpr since C++20 + operator() (ArgTypes&&...) const + noexcept(is_nothrow_invocable_v<T&, ArgTypes...>); // noexcept since C++17 }; template <class T> @@ -220,11 +222,16 @@ template<class Fn, class... BoundArgs> template<class R, class Fn, class... BoundArgs> constexpr unspecified bind(Fn&&, BoundArgs&&...); // constexpr in C++20 +// [func.invoke] template<class F, class... Args> constexpr // constexpr in C++20 invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) // C++17 noexcept(is_nothrow_invocable_v<F, Args...>); +template<class R, class F, class... Args> + constexpr R invoke_r(F&& f, Args&&... args) // C++23 + noexcept(is_nothrow_invocable_r_v<R, F, Args...>); + namespace placeholders { // M is the implementation-defined number of placeholders extern unspecified _1; @@ -250,10 +257,10 @@ public: }; template <class Operation, class T> -binder1st<Operation> bind1st(const Operation& op, const T& x); // deprecated in C++11, removed in C++17 +binder1st<Operation> bind1st(const Operation& op, const T& x); // deprecated in C++11, removed in C++17 template <class Operation> -class binder2nd // deprecated in C++11, removed in C++17 +class binder2nd // deprecated in C++11, removed in C++17 : public unary_function<typename Operation::first_argument_type, typename Operation::result_type> { @@ -267,9 +274,9 @@ public: }; template <class Operation, class T> -binder2nd<Operation> bind2nd(const Operation& op, const T& x); // deprecated in C++11, removed in C++17 +binder2nd<Operation> bind2nd(const Operation& op, const T& x); // deprecated in C++11, removed in C++17 -template <class Arg, class Result> // deprecated in C++11, removed in C++17 +template <class Arg, class Result> // deprecated in C++11, removed in C++17 class pointer_to_unary_function : public unary_function<Arg, Result> { public: @@ -278,9 +285,9 @@ public: }; template <class Arg, class Result> -pointer_to_unary_function<Arg,Result> ptr_fun(Result (*f)(Arg)); // deprecated in C++11, removed in C++17 +pointer_to_unary_function<Arg,Result> ptr_fun(Result (*f)(Arg)); // deprecated in C++11, removed in C++17 -template <class Arg1, class Arg2, class Result> // deprecated in C++11, removed in C++17 +template <class Arg1, class Arg2, class Result> // deprecated in C++11, removed in C++17 class pointer_to_binary_function : public binary_function<Arg1, Arg2, Result> { public: @@ -289,9 +296,9 @@ public: }; template <class Arg1, class Arg2, class Result> -pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun(Result (*f)(Arg1,Arg2)); // deprecated in C++11, removed in C++17 +pointer_to_binary_function<Arg1,Arg2,Result> ptr_fun(Result (*f)(Arg1,Arg2)); // deprecated in C++11, removed in C++17 -template<class S, class T> // deprecated in C++11, removed in C++17 +template<class S, class T> // deprecated in C++11, removed in C++17 class mem_fun_t : public unary_function<T*, S> { public: @@ -300,18 +307,18 @@ public: }; template<class S, class T, class A> -class mem_fun1_t : public binary_function<T*, A, S> // deprecated in C++11, removed in C++17 +class mem_fun1_t : public binary_function<T*, A, S> // deprecated in C++11, removed in C++17 { public: explicit mem_fun1_t(S (T::*p)(A)); S operator()(T* p, A x) const; }; -template<class S, class T> mem_fun_t<S,T> mem_fun(S (T::*f)()); // deprecated in C++11, removed in C++17 -template<class S, class T, class A> mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A)); // deprecated in C++11, removed in C++17 +template<class S, class T> mem_fun_t<S,T> mem_fun(S (T::*f)()); // deprecated in C++11, removed in C++17 +template<class S, class T, class A> mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A)); // deprecated in C++11, removed in C++17 template<class S, class T> -class mem_fun_ref_t : public unary_function<T, S> // deprecated in C++11, removed in C++17 +class mem_fun_ref_t : public unary_function<T, S> // deprecated in C++11, removed in C++17 { public: explicit mem_fun_ref_t(S (T::*p)()); @@ -319,18 +326,20 @@ public: }; template<class S, class T, class A> -class mem_fun1_ref_t : public binary_function<T, A, S> // deprecated in C++11, removed in C++17 +class mem_fun1_ref_t : public binary_function<T, A, S> // deprecated in C++11, removed in C++17 { public: explicit mem_fun1_ref_t(S (T::*p)(A)); S operator()(T& p, A x) const; }; -template<class S, class T> mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)()); // deprecated in C++11, removed in C++17 -template<class S, class T, class A> mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A)); // deprecated in C++11, removed in C++17 +template<class S, class T> +mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)()); // deprecated in C++11, removed in C++17 +template<class S, class T, class A> +mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A)); // deprecated in C++11, removed in C++17 template <class S, class T> -class const_mem_fun_t : public unary_function<const T*, S> // deprecated in C++11, removed in C++17 +class const_mem_fun_t : public unary_function<const T*, S> // deprecated in C++11, removed in C++17 { public: explicit const_mem_fun_t(S (T::*p)() const); @@ -338,18 +347,20 @@ public: }; template <class S, class T, class A> -class const_mem_fun1_t : public binary_function<const T*, A, S> // deprecated in C++11, removed in C++17 +class const_mem_fun1_t : public binary_function<const T*, A, S> // deprecated in C++11, removed in C++17 { public: explicit const_mem_fun1_t(S (T::*p)(A) const); S operator()(const T* p, A x) const; }; -template <class S, class T> const_mem_fun_t<S,T> mem_fun(S (T::*f)() const); // deprecated in C++11, removed in C++17 -template <class S, class T, class A> const_mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A) const); // deprecated in C++11, removed in C++17 +template <class S, class T> +const_mem_fun_t<S,T> mem_fun(S (T::*f)() const); // deprecated in C++11, removed in C++17 +template <class S, class T, class A> +const_mem_fun1_t<S,T,A> mem_fun(S (T::*f)(A) const); // deprecated in C++11, removed in C++17 template <class S, class T> -class const_mem_fun_ref_t : public unary_function<T, S> // deprecated in C++11, removed in C++17 +class const_mem_fun_ref_t : public unary_function<T, S> // deprecated in C++11, removed in C++17 { public: explicit const_mem_fun_ref_t(S (T::*p)() const); @@ -357,18 +368,19 @@ public: }; template <class S, class T, class A> -class const_mem_fun1_ref_t : public binary_function<T, A, S> // deprecated in C++11, removed in C++17 +class const_mem_fun1_ref_t : public binary_function<T, A, S> // deprecated in C++11, removed in C++17 { public: explicit const_mem_fun1_ref_t(S (T::*p)(A) const); S operator()(const T& p, A x) const; }; -template <class S, class T> const_mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)() const); // deprecated in C++11, removed in C++17 -template <class S, class T, class A> const_mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A) const); // deprecated in C++11, removed in C++17 +template <class S, class T> +const_mem_fun_ref_t<S,T> mem_fun_ref(S (T::*f)() const); // deprecated in C++11, removed in C++17 +template <class S, class T, class A> +const_mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A) const); // deprecated in C++11, removed in C++17 -template<class R, class T> -constexpr unspecified mem_fn(R T::*); // constexpr in C++20 +template<class R, class T> constexpr unspecified mem_fn(R T::*); // constexpr in C++20 class bad_function_call : public exception @@ -444,13 +456,13 @@ template <class R, class ... ArgTypes> bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept; template <class R, class ... ArgTypes> - bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept; + bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept; // removed in C++20 template <class R, class ... ArgTypes> - bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept; + bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept; // removed in C++20 template <class R, class ... ArgTypes> - bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept; + bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept; // removed in C++20 // specialized algorithms: template <class R, class ... ArgTypes> @@ -504,8 +516,7 @@ POLICY: For non-variadic implementations, the number of arguments is limited #include <__assert> // all public C++ headers provide the assertion handler #include <__compare/compare_three_way.h> #include <__config> -#include <__debug> -#include <__functional/binary_function.h> // TODO: deprecate +#include <__functional/binary_function.h> #include <__functional/binary_negate.h> #include <__functional/bind.h> #include <__functional/bind_back.h> @@ -527,13 +538,11 @@ POLICY: For non-variadic implementations, the number of arguments is limited #include <__functional/pointer_to_unary_function.h> #include <__functional/ranges_operations.h> #include <__functional/reference_wrapper.h> -#include <__functional/unary_function.h> // TODO: deprecate +#include <__functional/unary_function.h> #include <__functional/unary_negate.h> -#include <__functional/unwrap_ref.h> +#include <__type_traits/unwrap_ref.h> #include <__utility/forward.h> -#include <exception> #include <memory> // TODO: find out why removing this breaks the modules build -#include <type_traits> #include <typeinfo> #include <version> @@ -542,8 +551,12 @@ POLICY: For non-variadic implementations, the number of arguments is limited #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <atomic> # include <concepts> +# include <cstdlib> +# include <exception> # include <tuple> +# include <type_traits> # include <utility> #endif diff --git a/libcxx/include/future b/libcxx/include/future index 2f14a471c458..273e4175e604 100644 --- a/libcxx/include/future +++ b/libcxx/include/future @@ -366,17 +366,29 @@ template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>; #include <__chrono/duration.h> #include <__chrono/time_point.h> #include <__config> +#include <__exception/exception_ptr.h> +#include <__memory/addressof.h> +#include <__memory/allocator.h> #include <__memory/allocator_arg_t.h> #include <__memory/allocator_destructor.h> +#include <__memory/allocator_traits.h> +#include <__memory/compressed_pair.h> +#include <__memory/pointer_traits.h> +#include <__memory/shared_ptr.h> +#include <__memory/unique_ptr.h> #include <__memory/uses_allocator.h> +#include <__system_error/error_category.h> +#include <__system_error/error_code.h> +#include <__system_error/error_condition.h> +#include <__type_traits/aligned_storage.h> +#include <__type_traits/alignment_of.h> #include <__type_traits/strip_signature.h> #include <__utility/auto_cast.h> #include <__utility/forward.h> #include <__utility/move.h> -#include <exception> #include <mutex> #include <new> -#include <system_error> +#include <stdexcept> #include <thread> #include <version> @@ -488,8 +500,7 @@ _LIBCPP_DECLARE_STRONG_ENUM(future_status) }; _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_status) -_LIBCPP_FUNC_VIS -const error_category& future_category() _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI const error_category& future_category() _NOEXCEPT; inline _LIBCPP_INLINE_VISIBILITY error_code @@ -505,7 +516,7 @@ make_error_condition(future_errc __e) _NOEXCEPT return error_condition(static_cast<int>(__e), future_category()); } -class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_FUTURE_ERROR future_error +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_FUTURE_ERROR future_error : public logic_error { error_code __ec_; @@ -515,25 +526,25 @@ public: _LIBCPP_INLINE_VISIBILITY const error_code& code() const _NOEXCEPT {return __ec_;} - future_error(const future_error&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI future_error(const future_error&) _NOEXCEPT = default; ~future_error() _NOEXCEPT override; }; _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS _LIBCPP_AVAILABILITY_FUTURE_ERROR #endif void __throw_future_error(future_errc __ev) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw future_error(make_error_code(__ev)); #else - ((void)__ev); - _VSTD::abort(); + (void)__ev; + _LIBCPP_VERBOSE_ABORT("future_error was thrown in -fno-exceptions mode"); #endif } -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state : public __shared_count { protected: @@ -631,17 +642,17 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP protected: _Up __value_; - void __on_zero_shared() _NOEXCEPT override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; public: template <class _Arg> - void set_value(_Arg&& __arg); + _LIBCPP_HIDE_FROM_ABI void set_value(_Arg&& __arg); template <class _Arg> - void set_value_at_thread_exit(_Arg&& __arg); + _LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(_Arg&& __arg); - _Rp move(); - __add_lvalue_reference_t<_Rp> copy(); + _LIBCPP_HIDE_FROM_ABI _Rp move(); + _LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t<_Rp> copy(); }; template <class _Rp> @@ -711,13 +722,13 @@ class _LIBCPP_AVAILABILITY_FUTURE __assoc_state<_Rp&> protected: _Up __value_; - void __on_zero_shared() _NOEXCEPT override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; public: - void set_value(_Rp& __arg); - void set_value_at_thread_exit(_Rp& __arg); + _LIBCPP_HIDE_FROM_ABI void set_value(_Rp& __arg); + _LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(_Rp& __arg); - _Rp& copy(); + _LIBCPP_HIDE_FROM_ABI _Rp& copy(); }; template <class _Rp> @@ -769,7 +780,7 @@ class _LIBCPP_AVAILABILITY_FUTURE __assoc_state_alloc typedef __assoc_state<_Rp> base; _Alloc __alloc_; - virtual void __on_zero_shared() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __on_zero_shared() _NOEXCEPT; public: _LIBCPP_INLINE_VISIBILITY explicit __assoc_state_alloc(const _Alloc& __a) @@ -797,7 +808,7 @@ class _LIBCPP_AVAILABILITY_FUTURE __assoc_state_alloc<_Rp&, _Alloc> typedef __assoc_state<_Rp&> base; _Alloc __alloc_; - virtual void __on_zero_shared() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __on_zero_shared() _NOEXCEPT; public: _LIBCPP_INLINE_VISIBILITY explicit __assoc_state_alloc(const _Alloc& __a) @@ -823,7 +834,7 @@ class _LIBCPP_AVAILABILITY_FUTURE __assoc_sub_state_alloc typedef __assoc_sub_state base; _Alloc __alloc_; - void __on_zero_shared() _NOEXCEPT override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; public: _LIBCPP_INLINE_VISIBILITY explicit __assoc_sub_state_alloc(const _Alloc& __a) @@ -854,7 +865,7 @@ public: _LIBCPP_INLINE_VISIBILITY explicit __deferred_assoc_state(_Fp&& __f); - virtual void __execute(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __execute(); }; template <class _Rp, class _Fp> @@ -869,18 +880,18 @@ template <class _Rp, class _Fp> void __deferred_assoc_state<_Rp, _Fp>::__execute() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS this->set_value(__func_()); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->set_exception(current_exception()); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template <class _Fp> @@ -895,7 +906,7 @@ public: _LIBCPP_INLINE_VISIBILITY explicit __deferred_assoc_state(_Fp&& __f); - void __execute() override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __execute() override; }; template <class _Fp> @@ -910,19 +921,19 @@ template <class _Fp> void __deferred_assoc_state<void, _Fp>::__execute() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __func_(); this->set_value(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->set_exception(current_exception()); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template <class _Rp, class _Fp> @@ -933,12 +944,12 @@ class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state _Fp __func_; - virtual void __on_zero_shared() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __on_zero_shared() _NOEXCEPT; public: _LIBCPP_INLINE_VISIBILITY explicit __async_assoc_state(_Fp&& __f); - virtual void __execute(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __execute(); }; template <class _Rp, class _Fp> @@ -952,18 +963,18 @@ template <class _Rp, class _Fp> void __async_assoc_state<_Rp, _Fp>::__execute() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS this->set_value(__func_()); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->set_exception(current_exception()); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template <class _Rp, class _Fp> @@ -982,12 +993,12 @@ class _LIBCPP_AVAILABILITY_FUTURE __async_assoc_state<void, _Fp> _Fp __func_; - void __on_zero_shared() _NOEXCEPT override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; public: _LIBCPP_INLINE_VISIBILITY explicit __async_assoc_state(_Fp&& __f); - void __execute() override; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __execute() override; }; template <class _Fp> @@ -1001,19 +1012,19 @@ template <class _Fp> void __async_assoc_state<void, _Fp>::__execute() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __func_(); this->set_value(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->set_exception(current_exception()); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template <class _Fp> @@ -1044,7 +1055,7 @@ class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future { __assoc_state<_Rp>* __state_; - explicit future(__assoc_state<_Rp>* __state); + explicit _LIBCPP_HIDE_FROM_ABI future(__assoc_state<_Rp>* __state); template <class> friend class promise; template <class> friend class shared_future; @@ -1069,12 +1080,12 @@ public: return *this; } - ~future(); + _LIBCPP_HIDE_FROM_ABI ~future(); _LIBCPP_INLINE_VISIBILITY shared_future<_Rp> share() _NOEXCEPT; // retrieving the value - _Rp get(); + _LIBCPP_HIDE_FROM_ABI _Rp get(); _LIBCPP_INLINE_VISIBILITY void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} @@ -1106,7 +1117,7 @@ future<_Rp>::future(__assoc_state<_Rp>* __state) struct __release_shared_count { - void operator()(__shared_count* __p) {__p->__release_shared();} + _LIBCPP_HIDE_FROM_ABI void operator()(__shared_count* __p) {__p->__release_shared();} }; template <class _Rp> @@ -1120,7 +1131,7 @@ template <class _Rp> _Rp future<_Rp>::get() { - unique_ptr<__shared_count, __release_shared_count> __(__state_); + unique_ptr<__shared_count, __release_shared_count> __guard(__state_); __assoc_state<_Rp>* __s = __state_; __state_ = nullptr; return __s->move(); @@ -1131,7 +1142,7 @@ class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE future<_Rp&> { __assoc_state<_Rp&>* __state_; - explicit future(__assoc_state<_Rp&>* __state); + explicit _LIBCPP_HIDE_FROM_ABI future(__assoc_state<_Rp&>* __state); template <class> friend class promise; template <class> friend class shared_future; @@ -1156,12 +1167,12 @@ public: return *this; } - ~future(); + _LIBCPP_HIDE_FROM_ABI ~future(); _LIBCPP_INLINE_VISIBILITY shared_future<_Rp&> share() _NOEXCEPT; // retrieving the value - _Rp& get(); + _LIBCPP_HIDE_FROM_ABI _Rp& get(); _LIBCPP_INLINE_VISIBILITY void swap(future& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} @@ -1202,14 +1213,14 @@ template <class _Rp> _Rp& future<_Rp&>::get() { - unique_ptr<__shared_count, __release_shared_count> __(__state_); + unique_ptr<__shared_count, __release_shared_count> __guard(__state_); __assoc_state<_Rp&>* __s = __state_; __state_ = nullptr; return __s->copy(); } template <> -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE future<void> +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_FUTURE future<void> { __assoc_sub_state* __state_; @@ -1288,14 +1299,14 @@ class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise template <class> friend class packaged_task; public: - promise(); + _LIBCPP_HIDE_FROM_ABI promise(); template <class _Alloc> - promise(allocator_arg_t, const _Alloc& __a); + _LIBCPP_HIDE_FROM_ABI promise(allocator_arg_t, const _Alloc& __a); _LIBCPP_INLINE_VISIBILITY promise(promise&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} promise(const promise& __rhs) = delete; - ~promise(); + _LIBCPP_HIDE_FROM_ABI ~promise(); // assignment _LIBCPP_INLINE_VISIBILITY @@ -1310,17 +1321,17 @@ public: void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} // retrieving the result - future<_Rp> get_future(); + _LIBCPP_HIDE_FROM_ABI future<_Rp> get_future(); // setting the result - void set_value(const _Rp& __r); - void set_value(_Rp&& __r); - void set_exception(exception_ptr __p); + _LIBCPP_HIDE_FROM_ABI void set_value(const _Rp& __r); + _LIBCPP_HIDE_FROM_ABI void set_value(_Rp&& __r); + _LIBCPP_HIDE_FROM_ABI void set_exception(exception_ptr __p); // setting the result with deferred notification - void set_value_at_thread_exit(const _Rp& __r); - void set_value_at_thread_exit(_Rp&& __r); - void set_exception_at_thread_exit(exception_ptr __p); + _LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(const _Rp& __r); + _LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(_Rp&& __r); + _LIBCPP_HIDE_FROM_ABI void set_exception_at_thread_exit(exception_ptr __p); }; template <class _Rp> @@ -1386,7 +1397,7 @@ template <class _Rp> void promise<_Rp>::set_exception(exception_ptr __p) { - _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception: received nullptr" ); + _LIBCPP_ASSERT_UNCATEGORIZED( __p != nullptr, "promise::set_exception: received nullptr" ); if (__state_ == nullptr) __throw_future_error(future_errc::no_state); __state_->set_exception(__p); @@ -1414,7 +1425,7 @@ template <class _Rp> void promise<_Rp>::set_exception_at_thread_exit(exception_ptr __p) { - _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); + _LIBCPP_ASSERT_UNCATEGORIZED( __p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); if (__state_ == nullptr) __throw_future_error(future_errc::no_state); __state_->set_exception_at_thread_exit(__p); @@ -1433,14 +1444,14 @@ class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<_Rp&> template <class> friend class packaged_task; public: - promise(); + _LIBCPP_HIDE_FROM_ABI promise(); template <class _Allocator> - promise(allocator_arg_t, const _Allocator& __a); + _LIBCPP_HIDE_FROM_ABI promise(allocator_arg_t, const _Allocator& __a); _LIBCPP_INLINE_VISIBILITY promise(promise&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} promise(const promise& __rhs) = delete; - ~promise(); + _LIBCPP_HIDE_FROM_ABI ~promise(); // assignment _LIBCPP_INLINE_VISIBILITY @@ -1455,15 +1466,15 @@ public: void swap(promise& __rhs) _NOEXCEPT {_VSTD::swap(__state_, __rhs.__state_);} // retrieving the result - future<_Rp&> get_future(); + _LIBCPP_HIDE_FROM_ABI future<_Rp&> get_future(); // setting the result - void set_value(_Rp& __r); - void set_exception(exception_ptr __p); + _LIBCPP_HIDE_FROM_ABI void set_value(_Rp& __r); + _LIBCPP_HIDE_FROM_ABI void set_exception(exception_ptr __p); // setting the result with deferred notification - void set_value_at_thread_exit(_Rp&); - void set_exception_at_thread_exit(exception_ptr __p); + _LIBCPP_HIDE_FROM_ABI void set_value_at_thread_exit(_Rp&); + _LIBCPP_HIDE_FROM_ABI void set_exception_at_thread_exit(exception_ptr __p); }; template <class _Rp> @@ -1520,7 +1531,7 @@ template <class _Rp> void promise<_Rp&>::set_exception(exception_ptr __p) { - _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception: received nullptr" ); + _LIBCPP_ASSERT_UNCATEGORIZED( __p != nullptr, "promise::set_exception: received nullptr" ); if (__state_ == nullptr) __throw_future_error(future_errc::no_state); __state_->set_exception(__p); @@ -1539,7 +1550,7 @@ template <class _Rp> void promise<_Rp&>::set_exception_at_thread_exit(exception_ptr __p) { - _LIBCPP_ASSERT( __p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); + _LIBCPP_ASSERT_UNCATEGORIZED( __p != nullptr, "promise::set_exception_at_thread_exit: received nullptr" ); if (__state_ == nullptr) __throw_future_error(future_errc::no_state); __state_->set_exception_at_thread_exit(__p); @@ -1548,7 +1559,7 @@ promise<_Rp&>::set_exception_at_thread_exit(exception_ptr __p) // promise<void> template <> -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE promise<void> +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_FUTURE promise<void> { __assoc_sub_state* __state_; @@ -1654,10 +1665,10 @@ public: _LIBCPP_INLINE_VISIBILITY __packaged_task_func(_Fp&& __f, const _Alloc& __a) : __f_(_VSTD::move(__f), __a) {} - virtual void __move_to(__packaged_task_base<_Rp(_ArgTypes...)>*) _NOEXCEPT; - virtual void destroy(); - virtual void destroy_deallocate(); - virtual _Rp operator()(_ArgTypes&& ... __args); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __move_to(__packaged_task_base<_Rp(_ArgTypes...)>*) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy_deallocate(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual _Rp operator()(_ArgTypes&& ... __args); }; template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> @@ -1716,22 +1727,22 @@ public: _LIBCPP_INLINE_VISIBILITY __packaged_task_function() _NOEXCEPT : __f_(nullptr) {} template<class _Fp> - __packaged_task_function(_Fp&& __f); + _LIBCPP_HIDE_FROM_ABI __packaged_task_function(_Fp&& __f); template<class _Fp, class _Alloc> - __packaged_task_function(allocator_arg_t, const _Alloc& __a, _Fp&& __f); + _LIBCPP_HIDE_FROM_ABI __packaged_task_function(allocator_arg_t, const _Alloc& __a, _Fp&& __f); - __packaged_task_function(__packaged_task_function&&) _NOEXCEPT; - __packaged_task_function& operator=(__packaged_task_function&&) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI __packaged_task_function(__packaged_task_function&&) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI __packaged_task_function& operator=(__packaged_task_function&&) _NOEXCEPT; __packaged_task_function(const __packaged_task_function&) = delete; __packaged_task_function& operator=(const __packaged_task_function&) = delete; - ~__packaged_task_function(); + _LIBCPP_HIDE_FROM_ABI ~__packaged_task_function(); - void swap(__packaged_task_function&) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void swap(__packaged_task_function&) _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY - _Rp operator()(_ArgTypes...) const; + _LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes...) const; }; template<class _Rp, class ..._ArgTypes> @@ -1756,7 +1767,7 @@ template <class _Fp> __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f) : __f_(nullptr) { - typedef __libcpp_remove_reference_t<typename decay<_Fp>::type> _FR; + typedef __libcpp_remove_reference_t<__decay_t<_Fp> > _FR; typedef __packaged_task_func<_FR, allocator<_FR>, _Rp(_ArgTypes...)> _FF; if (sizeof(_FF) <= sizeof(__buf_)) { @@ -1780,7 +1791,7 @@ __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function( allocator_arg_t, const _Alloc& __a0, _Fp&& __f) : __f_(nullptr) { - typedef __libcpp_remove_reference_t<typename decay<_Fp>::type> _FR; + typedef __libcpp_remove_reference_t<__decay_t<_Fp> > _FR; typedef __packaged_task_func<_FR, _Alloc, _Rp(_ArgTypes...)> _FF; if (sizeof(_FF) <= sizeof(__buf_)) { @@ -1902,8 +1913,8 @@ public: class = __enable_if_t<!is_same<__remove_cvref_t<_Fp>, packaged_task>::value> > _LIBCPP_INLINE_VISIBILITY packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) - : __f_(allocator_arg, __a, _VSTD::forward<_Fp>(__f)), - __p_(allocator_arg, __a) {} + : __f_(allocator_arg_t(), __a, _VSTD::forward<_Fp>(__f)), + __p_(allocator_arg_t(), __a) {} // ~packaged_task() = default; // no copy @@ -1936,10 +1947,10 @@ public: future<result_type> get_future() {return __p_.get_future();} // execution - void operator()(_ArgTypes... __args); - void make_ready_at_thread_exit(_ArgTypes... __args); + _LIBCPP_HIDE_FROM_ABI void operator()(_ArgTypes... __args); + _LIBCPP_HIDE_FROM_ABI void make_ready_at_thread_exit(_ArgTypes... __args); - void reset(); + _LIBCPP_HIDE_FROM_ABI void reset(); }; template<class _Rp, class ..._ArgTypes> @@ -1950,18 +1961,18 @@ packaged_task<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __args) __throw_future_error(future_errc::no_state); if (__p_.__state_->__has_value()) __throw_future_error(future_errc::promise_already_satisfied); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __p_.set_value(__f_(_VSTD::forward<_ArgTypes>(__args)...)); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __p_.set_exception(current_exception()); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template<class _Rp, class ..._ArgTypes> @@ -1972,18 +1983,18 @@ packaged_task<_Rp(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args) __throw_future_error(future_errc::no_state); if (__p_.__state_->__has_value()) __throw_future_error(future_errc::promise_already_satisfied); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __p_.set_value_at_thread_exit(__f_(_VSTD::forward<_ArgTypes>(__args)...)); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __p_.set_exception_at_thread_exit(current_exception()); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template<class _Rp, class ..._ArgTypes> @@ -2017,8 +2028,8 @@ public: class = __enable_if_t<!is_same<__remove_cvref_t<_Fp>, packaged_task>::value> > _LIBCPP_INLINE_VISIBILITY packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) - : __f_(allocator_arg, __a, _VSTD::forward<_Fp>(__f)), - __p_(allocator_arg, __a) {} + : __f_(allocator_arg_t(), __a, _VSTD::forward<_Fp>(__f)), + __p_(allocator_arg_t(), __a) {} // ~packaged_task() = default; // no copy @@ -2051,10 +2062,10 @@ public: future<result_type> get_future() {return __p_.get_future();} // execution - void operator()(_ArgTypes... __args); - void make_ready_at_thread_exit(_ArgTypes... __args); + _LIBCPP_HIDE_FROM_ABI void operator()(_ArgTypes... __args); + _LIBCPP_HIDE_FROM_ABI void make_ready_at_thread_exit(_ArgTypes... __args); - void reset(); + _LIBCPP_HIDE_FROM_ABI void reset(); }; #if _LIBCPP_STD_VER >= 17 @@ -2075,19 +2086,19 @@ packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args) __throw_future_error(future_errc::no_state); if (__p_.__state_->__has_value()) __throw_future_error(future_errc::promise_already_satisfied); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __f_(_VSTD::forward<_ArgTypes>(__args)...); __p_.set_value(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __p_.set_exception(current_exception()); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template<class ..._ArgTypes> @@ -2098,19 +2109,19 @@ packaged_task<void(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __args __throw_future_error(future_errc::no_state); if (__p_.__state_->__has_value()) __throw_future_error(future_errc::promise_already_satisfied); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __f_(_VSTD::forward<_ArgTypes>(__args)...); __p_.set_value_at_thread_exit(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __p_.set_exception_at_thread_exit(current_exception()); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template<class ..._ArgTypes> @@ -2170,14 +2181,14 @@ public: _LIBCPP_INLINE_VISIBILITY __async_func(__async_func&& __f) : __f_(_VSTD::move(__f.__f_)) {} - _Rp operator()() + _LIBCPP_HIDE_FROM_ABI _Rp operator()() { typedef typename __make_tuple_indices<1+sizeof...(_Args), 1>::type _Index; return __execute(_Index()); } private: template <size_t ..._Indices> - _Rp + _LIBCPP_HIDE_FROM_ABI _Rp __execute(__tuple_indices<_Indices...>) { return _VSTD::__invoke(_VSTD::move(_VSTD::get<0>(__f_)), _VSTD::move(_VSTD::get<_Indices>(__f_))...); @@ -2189,20 +2200,20 @@ inline _LIBCPP_INLINE_VISIBILITY bool __does_policy_contain(launch __policy, lau template <class _Fp, class... _Args> _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI -future<typename __invoke_of<typename decay<_Fp>::type, typename decay<_Args>::type...>::type> +future<typename __invoke_of<__decay_t<_Fp>, __decay_t<_Args>...>::type> async(launch __policy, _Fp&& __f, _Args&&... __args) { - typedef __async_func<typename decay<_Fp>::type, typename decay<_Args>::type...> _BF; + typedef __async_func<__decay_t<_Fp>, __decay_t<_Args>...> _BF; typedef typename _BF::_Rp _Rp; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif if (__does_policy_contain(__policy, launch::async)) return _VSTD::__make_async_assoc_state<_Rp>(_BF(_LIBCPP_AUTO_CAST(_VSTD::forward<_Fp>(__f)), _LIBCPP_AUTO_CAST(_VSTD::forward<_Args>(__args))...)); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch ( ... ) { if (__policy == launch::async) throw ; } #endif @@ -2215,7 +2226,7 @@ async(launch __policy, _Fp&& __f, _Args&&... __args) template <class _Fp, class... _Args> _LIBCPP_NODISCARD_AFTER_CXX17 inline _LIBCPP_INLINE_VISIBILITY -future<typename __invoke_of<typename decay<_Fp>::type, typename decay<_Args>::type...>::type> +future<typename __invoke_of<__decay_t<_Fp>, __decay_t<_Args>...>::type> async(_Fp&& __f, _Args&&... __args) { return _VSTD::async(launch::any, _VSTD::forward<_Fp>(__f), @@ -2243,8 +2254,8 @@ public: _LIBCPP_INLINE_VISIBILITY shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} - ~shared_future(); - shared_future& operator=(const shared_future& __rhs) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI ~shared_future(); + _LIBCPP_HIDE_FROM_ABI shared_future& operator=(const shared_future& __rhs) _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY shared_future& operator=(shared_future&& __rhs) _NOEXCEPT { @@ -2313,8 +2324,8 @@ public: _LIBCPP_INLINE_VISIBILITY shared_future(shared_future&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) {__rhs.__state_ = nullptr;} - ~shared_future(); - shared_future& operator=(const shared_future& __rhs); + _LIBCPP_HIDE_FROM_ABI ~shared_future(); + _LIBCPP_HIDE_FROM_ABI shared_future& operator=(const shared_future& __rhs); _LIBCPP_INLINE_VISIBILITY shared_future& operator=(shared_future&& __rhs) _NOEXCEPT { @@ -2367,7 +2378,7 @@ shared_future<_Rp&>::operator=(const shared_future& __rhs) } template <> -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_FUTURE shared_future<void> +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_FUTURE shared_future<void> { __assoc_sub_state* __state_; @@ -2454,4 +2465,11 @@ _LIBCPP_END_NAMESPACE_STD # include <chrono> #endif +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <atomic> +# include <cstdlib> +# include <exception> +# include <system_error> +#endif + #endif // _LIBCPP_FUTURE diff --git a/libcxx/include/iomanip b/libcxx/include/iomanip index 38c5c9b9c6b2..53445c72ba19 100644 --- a/libcxx/include/iomanip +++ b/libcxx/include/iomanip @@ -301,10 +301,10 @@ template <class _CharT, class _Traits, class _MoneyT> _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& operator>>(basic_istream<_CharT, _Traits>& __is, const __iom_t7<_MoneyT>& __x) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typename basic_istream<_CharT, _Traits>::sentry __s(__is); if (__s) { @@ -315,13 +315,13 @@ operator>>(basic_istream<_CharT, _Traits>& __is, const __iom_t7<_MoneyT>& __x) __mf.get(_Ip(__is), _Ip(), __x.__intl_, __is, __err, __x.__mon_); __is.setstate(__err); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __is.__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return __is; } @@ -361,10 +361,10 @@ template <class _CharT, class _Traits, class _MoneyT> _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const __iom_t8<_MoneyT>& __x) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typename basic_ostream<_CharT, _Traits>::sentry __s(__os); if (__s) { @@ -374,13 +374,13 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const __iom_t8<_MoneyT>& __x) if (__mf.put(_Op(__os), __x.__intl_, __os, __os.fill(), __x.__mon_).failed()) __os.setstate(ios_base::badbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __os.__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return __os; } @@ -420,10 +420,10 @@ template <class _CharT, class _Traits> _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& operator>>(basic_istream<_CharT, _Traits>& __is, const __iom_t9<_CharT>& __x) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typename basic_istream<_CharT, _Traits>::sentry __s(__is); if (__s) { @@ -435,13 +435,13 @@ operator>>(basic_istream<_CharT, _Traits>& __is, const __iom_t9<_CharT>& __x) __x.__fmt_, __x.__fmt_ + _Traits::length(__x.__fmt_)); __is.setstate(__err); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __is.__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return __is; } @@ -481,10 +481,10 @@ template <class _CharT, class _Traits> _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const __iom_t10<_CharT>& __x) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typename basic_ostream<_CharT, _Traits>::sentry __s(__os); if (__s) { @@ -495,13 +495,13 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const __iom_t10<_CharT>& __x) __x.__fmt_, __x.__fmt_ + _Traits::length(__x.__fmt_)).failed()) __os.setstate(ios_base::badbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __os.__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return __os; } @@ -513,8 +513,6 @@ put_time(const tm* __tm, const _CharT* __fmt) return __iom_t10<_CharT>(__tm, __fmt); } -#if _LIBCPP_STD_VER >= 11 - template <class _CharT, class _Traits> _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& __quoted_output(basic_ostream<_CharT, _Traits>& __os, @@ -622,9 +620,7 @@ __quoted(basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT return __quoted_proxy<_CharT, _Traits, _Allocator>(__s, __delim, __escape); } -#endif // _LIBCPP_STD_VER >= 11 - -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _CharT> _LIBCPP_HIDE_FROM_ABI @@ -656,7 +652,7 @@ auto quoted(basic_string_view<_CharT, _Traits> __sv, _CharT __delim = _CharT('"' return __quoted_output_proxy<_CharT, _Traits>(__sv.data(), __sv.data() + __sv.size(), __delim, __escape); } -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/ios b/libcxx/include/ios index 9eecf4d8dd8f..156f68556427 100644 --- a/libcxx/include/ios +++ b/libcxx/include/ios @@ -217,10 +217,15 @@ storage-class-specifier const error_category& iostream_category() noexcept; #endif #include <__assert> // all public C++ headers provide the assertion handler +#include <__fwd/ios.h> #include <__ios/fpos.h> #include <__locale> +#include <__system_error/error_category.h> +#include <__system_error/error_code.h> +#include <__system_error/error_condition.h> +#include <__system_error/system_error.h> #include <__utility/swap.h> -#include <system_error> +#include <__verbose_abort> #include <version> // standard-mandated includes @@ -229,7 +234,7 @@ storage-class-specifier const error_category& iostream_category() noexcept; #include <iosfwd> #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) -#include <atomic> // for __xindex_ +# include <__atomic/atomic.h> // for __xindex_ #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -240,10 +245,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD typedef ptrdiff_t streamsize; -class _LIBCPP_TYPE_VIS ios_base +class _LIBCPP_EXPORTED_FROM_ABI ios_base { public: - class _LIBCPP_EXCEPTION_ABI failure; + class _LIBCPP_EXPORTED_FROM_ABI failure; typedef unsigned int fmtflags; static const fmtflags boolalpha = 0x0001; @@ -290,7 +295,7 @@ public: typedef _VSTD::streampos streampos; #endif - class _LIBCPP_TYPE_VIS Init; + class _LIBCPP_EXPORTED_FROM_ABI Init; // 27.5.2.2 fmtflags state: _LIBCPP_INLINE_VISIBILITY fmtflags flags() const; @@ -419,8 +424,7 @@ template <> struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<io_errc::__lx> : public true_type { }; #endif -_LIBCPP_FUNC_VIS -const error_category& iostream_category() _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI const error_category& iostream_category() _NOEXCEPT; inline _LIBCPP_INLINE_VISIBILITY error_code @@ -436,27 +440,26 @@ make_error_condition(io_errc __e) _NOEXCEPT return error_condition(static_cast<int>(__e), iostream_category()); } -class _LIBCPP_EXCEPTION_ABI ios_base::failure +class _LIBCPP_EXPORTED_FROM_ABI ios_base::failure : public system_error { public: explicit failure(const string& __msg, const error_code& __ec = io_errc::stream); explicit failure(const char* __msg, const error_code& __ec = io_errc::stream); - failure(const failure&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI failure(const failure&) _NOEXCEPT = default; ~failure() _NOEXCEPT override; }; _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_failure(char const* __msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw ios_base::failure(__msg); #else - ((void)__msg); - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("ios_base::failure was thrown in -fno-exceptions mode with message \"%s\"", __msg); #endif } -class _LIBCPP_TYPE_VIS ios_base::Init +class _LIBCPP_EXPORTED_FROM_ABI ios_base::Init { public: Init(); @@ -844,6 +847,12 @@ basic_ios<_CharT, _Traits>::set_rdbuf(basic_streambuf<char_type, traits_type>* _ ios_base::set_rdbuf(__sb); } +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ios<char>; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ios<wchar_t>; +#endif + _LIBCPP_HIDE_FROM_ABI inline ios_base& boolalpha(ios_base& __str) @@ -1039,6 +1048,7 @@ defaultfloat(ios_base& __str) _LIBCPP_END_NAMESPACE_STD #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <atomic> # include <concepts> # include <cstddef> # include <cstdlib> @@ -1047,6 +1057,7 @@ _LIBCPP_END_NAMESPACE_STD # include <limits> # include <new> # include <stdexcept> +# include <system_error> # include <type_traits> # include <typeinfo> #endif diff --git a/libcxx/include/iosfwd b/libcxx/include/iosfwd index 7948606e6453..ea1a8c0ec372 100644 --- a/libcxx/include/iosfwd +++ b/libcxx/include/iosfwd @@ -96,8 +96,14 @@ using u32streampos = fpos<char_traits<char32_t>::state_type>; #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__fwd/fstream.h> +#include <__fwd/ios.h> +#include <__fwd/istream.h> +#include <__fwd/ostream.h> +#include <__fwd/sstream.h> +#include <__fwd/streambuf.h> #include <__fwd/string.h> -#include <__mbstate_t.h> +#include <__std_mbstate_t.h> #include <version> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -106,114 +112,13 @@ using u32streampos = fpos<char_traits<char32_t>::state_type>; _LIBCPP_BEGIN_NAMESPACE_STD -class _LIBCPP_TYPE_VIS ios_base; - -template <class _CharT, class _Traits = char_traits<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_ios; - -template <class _CharT, class _Traits = char_traits<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_streambuf; -template <class _CharT, class _Traits = char_traits<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_istream; -template <class _CharT, class _Traits = char_traits<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_ostream; -template <class _CharT, class _Traits = char_traits<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_iostream; - -template <class _CharT, class _Traits = char_traits<_CharT>, - class _Allocator = allocator<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_stringbuf; -template <class _CharT, class _Traits = char_traits<_CharT>, - class _Allocator = allocator<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_istringstream; -template <class _CharT, class _Traits = char_traits<_CharT>, - class _Allocator = allocator<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_ostringstream; -template <class _CharT, class _Traits = char_traits<_CharT>, - class _Allocator = allocator<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_stringstream; - -template <class _CharT, class _Traits = char_traits<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_filebuf; -template <class _CharT, class _Traits = char_traits<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_ifstream; -template <class _CharT, class _Traits = char_traits<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_ofstream; -template <class _CharT, class _Traits = char_traits<_CharT> > - class _LIBCPP_TEMPLATE_VIS basic_fstream; +class _LIBCPP_EXPORTED_FROM_ABI ios_base; template <class _CharT, class _Traits = char_traits<_CharT> > class _LIBCPP_TEMPLATE_VIS istreambuf_iterator; template <class _CharT, class _Traits = char_traits<_CharT> > class _LIBCPP_TEMPLATE_VIS ostreambuf_iterator; -typedef basic_ios<char> ios; -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -typedef basic_ios<wchar_t> wios; -#endif - -typedef basic_streambuf<char> streambuf; -typedef basic_istream<char> istream; -typedef basic_ostream<char> ostream; -typedef basic_iostream<char> iostream; - -typedef basic_stringbuf<char> stringbuf; -typedef basic_istringstream<char> istringstream; -typedef basic_ostringstream<char> ostringstream; -typedef basic_stringstream<char> stringstream; - -typedef basic_filebuf<char> filebuf; -typedef basic_ifstream<char> ifstream; -typedef basic_ofstream<char> ofstream; -typedef basic_fstream<char> fstream; - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -typedef basic_streambuf<wchar_t> wstreambuf; -typedef basic_istream<wchar_t> wistream; -typedef basic_ostream<wchar_t> wostream; -typedef basic_iostream<wchar_t> wiostream; - -typedef basic_stringbuf<wchar_t> wstringbuf; -typedef basic_istringstream<wchar_t> wistringstream; -typedef basic_ostringstream<wchar_t> wostringstream; -typedef basic_stringstream<wchar_t> wstringstream; - -typedef basic_filebuf<wchar_t> wfilebuf; -typedef basic_ifstream<wchar_t> wifstream; -typedef basic_ofstream<wchar_t> wofstream; -typedef basic_fstream<wchar_t> wfstream; -#endif - -template <class _CharT, class _Traits> - class _LIBCPP_PREFERRED_NAME(ios) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wios)) basic_ios; - -template <class _CharT, class _Traits> - class _LIBCPP_PREFERRED_NAME(streambuf) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstreambuf)) basic_streambuf; -template <class _CharT, class _Traits> - class _LIBCPP_PREFERRED_NAME(istream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wistream)) basic_istream; -template <class _CharT, class _Traits> - class _LIBCPP_PREFERRED_NAME(ostream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wostream)) basic_ostream; -template <class _CharT, class _Traits> - class _LIBCPP_PREFERRED_NAME(iostream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wiostream)) basic_iostream; - -template <class _CharT, class _Traits, class _Allocator> - class _LIBCPP_PREFERRED_NAME(stringbuf) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstringbuf)) basic_stringbuf; -template <class _CharT, class _Traits, class _Allocator> - class _LIBCPP_PREFERRED_NAME(istringstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wistringstream)) basic_istringstream; -template <class _CharT, class _Traits, class _Allocator> - class _LIBCPP_PREFERRED_NAME(ostringstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wostringstream)) basic_ostringstream; -template <class _CharT, class _Traits, class _Allocator> - class _LIBCPP_PREFERRED_NAME(stringstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wstringstream)) basic_stringstream; - -template <class _CharT, class _Traits> - class _LIBCPP_PREFERRED_NAME(filebuf) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wfilebuf)) basic_filebuf; -template <class _CharT, class _Traits> - class _LIBCPP_PREFERRED_NAME(ifstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wifstream)) basic_ifstream; -template <class _CharT, class _Traits> - class _LIBCPP_PREFERRED_NAME(ofstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wofstream)) basic_ofstream; -template <class _CharT, class _Traits> - class _LIBCPP_PREFERRED_NAME(fstream) _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wfstream)) basic_fstream; - template <class _State> class _LIBCPP_TEMPLATE_VIS fpos; typedef fpos<mbstate_t> streampos; typedef fpos<mbstate_t> wstreampos; @@ -223,13 +128,6 @@ typedef fpos<mbstate_t> u8streampos; typedef fpos<mbstate_t> u16streampos; typedef fpos<mbstate_t> u32streampos; -#if defined(_NEWLIB_VERSION) -// On newlib, off_t is 'long int' -typedef long int streamoff; // for char_traits in <string> -#else -typedef long long streamoff; // for char_traits in <string> -#endif - // Include other forward declarations here template <class _Tp, class _Alloc = allocator<_Tp> > class _LIBCPP_TEMPLATE_VIS vector; diff --git a/libcxx/include/iostream b/libcxx/include/iostream index d679d9932d7e..568ce8caed6e 100644 --- a/libcxx/include/iostream +++ b/libcxx/include/iostream @@ -51,16 +51,16 @@ extern wostream wclog; _LIBCPP_BEGIN_NAMESPACE_STD -extern _LIBCPP_FUNC_VIS istream cin; -extern _LIBCPP_FUNC_VIS ostream cout; -extern _LIBCPP_FUNC_VIS ostream cerr; -extern _LIBCPP_FUNC_VIS ostream clog; +extern _LIBCPP_EXPORTED_FROM_ABI istream cin; +extern _LIBCPP_EXPORTED_FROM_ABI ostream cout; +extern _LIBCPP_EXPORTED_FROM_ABI ostream cerr; +extern _LIBCPP_EXPORTED_FROM_ABI ostream clog; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -extern _LIBCPP_FUNC_VIS wistream wcin; -extern _LIBCPP_FUNC_VIS wostream wcout; -extern _LIBCPP_FUNC_VIS wostream wcerr; -extern _LIBCPP_FUNC_VIS wostream wclog; +extern _LIBCPP_EXPORTED_FROM_ABI wistream wcin; +extern _LIBCPP_EXPORTED_FROM_ABI wostream wcout; +extern _LIBCPP_EXPORTED_FROM_ABI wostream wcerr; +extern _LIBCPP_EXPORTED_FROM_ABI wostream wclog; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/istream b/libcxx/include/istream index 6e67d61de2af..8b440c036ddb 100644 --- a/libcxx/include/istream +++ b/libcxx/include/istream @@ -160,7 +160,12 @@ template <class Stream, class T> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__fwd/istream.h> #include <__iterator/istreambuf_iterator.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_base_of.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <ostream> #include <version> @@ -360,14 +365,14 @@ __input_arithmetic(basic_istream<_CharT, _Traits>& __is, _Tp& __n) { typename basic_istream<_CharT, _Traits>::sentry __s(__is); if (__s) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef istreambuf_iterator<_CharT, _Traits> _Ip; typedef num_get<_CharT, _Ip> _Fp; std::use_facet<_Fp>(__is.getloc()).get(_Ip(__is), _Ip(), __is, __state, __n); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -469,10 +474,10 @@ __input_arithmetic_with_numeric_limits(basic_istream<_CharT, _Traits>& __is, _Tp typename basic_istream<_CharT, _Traits>::sentry __s(__is); if (__s) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef istreambuf_iterator<_CharT, _Traits> _Ip; typedef num_get<_CharT, _Ip> _Fp; long __temp; @@ -491,7 +496,7 @@ __input_arithmetic_with_numeric_limits(basic_istream<_CharT, _Traits>& __is, _Tp { __n = static_cast<_Tp>(__temp); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -502,7 +507,7 @@ __input_arithmetic_with_numeric_limits(basic_istream<_CharT, _Traits>& __is, _Tp throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __is.setstate(__state); } return __is; @@ -531,7 +536,7 @@ __input_c_string(basic_istream<_CharT, _Traits>& __is, _CharT* __p, size_t __n) typename basic_istream<_CharT, _Traits>::sentry __sen(__is); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif @@ -555,7 +560,7 @@ __input_c_string(basic_istream<_CharT, _Traits>& __is, _CharT* __p, size_t __n) __is.width(0); if (__s == __p) __state |= ios_base::failbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -572,7 +577,7 @@ __input_c_string(basic_istream<_CharT, _Traits>& __is, _CharT* __p, size_t __n) return __is; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class _CharT, class _Traits, size_t _Np> inline _LIBCPP_INLINE_VISIBILITY @@ -630,7 +635,7 @@ operator>>(basic_istream<char, _Traits>& __is, signed char* __s) return __is >> (char*)__s; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template<class _CharT, class _Traits> _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& @@ -640,7 +645,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, _CharT& __c) typename basic_istream<_CharT, _Traits>::sentry __sen(__is); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif @@ -649,7 +654,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, _CharT& __c) __state |= ios_base::eofbit | ios_base::failbit; else __c = _Traits::to_char_type(__i); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -693,10 +698,10 @@ basic_istream<_CharT, _Traits>::operator>>(basic_streambuf<char_type, traits_typ { if (__sb) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS while (true) { typename traits_type::int_type __i = this->rdbuf()->sgetc(); @@ -714,7 +719,7 @@ basic_istream<_CharT, _Traits>::operator>>(basic_streambuf<char_type, traits_typ } if (__gc_ == 0) __state |= ios_base::failbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -728,7 +733,7 @@ basic_istream<_CharT, _Traits>::operator>>(basic_streambuf<char_type, traits_typ throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } else { @@ -749,7 +754,7 @@ basic_istream<_CharT, _Traits>::get() sentry __s(*this, true); if (__s) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif @@ -758,7 +763,7 @@ basic_istream<_CharT, _Traits>::get() __state |= ios_base::failbit | ios_base::eofbit; else __gc_ = 1; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -785,7 +790,7 @@ basic_istream<_CharT, _Traits>::get(char_type* __s, streamsize __n, char_type __ { if (__n > 0) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif @@ -806,7 +811,7 @@ basic_istream<_CharT, _Traits>::get(char_type* __s, streamsize __n, char_type __ } if (__gc_ == 0) __state |= ios_base::failbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -845,10 +850,10 @@ basic_istream<_CharT, _Traits>::get(basic_streambuf<char_type, traits_type>& __s sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS while (true) { typename traits_type::int_type __i = this->rdbuf()->sgetc(); @@ -865,14 +870,14 @@ basic_istream<_CharT, _Traits>::get(basic_streambuf<char_type, traits_type>& __s ++__gc_; this->rdbuf()->sbumpc(); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __state |= ios_base::badbit; // according to the spec, exceptions here are caught but not rethrown } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (__gc_ == 0) __state |= ios_base::failbit; this->setstate(__state); @@ -889,10 +894,10 @@ basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n, char_typ sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS while (true) { typename traits_type::int_type __i = this->rdbuf()->sgetc(); @@ -917,7 +922,7 @@ basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n, char_typ this->rdbuf()->sbumpc(); ++__gc_; } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -932,7 +937,7 @@ basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n, char_typ throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } if (__n > 0) *__s = char_type(); @@ -951,10 +956,10 @@ basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __dlm) sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (__n == numeric_limits<streamsize>::max()) { while (true) @@ -985,7 +990,7 @@ basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __dlm) break; } } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -996,7 +1001,7 @@ basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __dlm) throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS this->setstate(__state); } return *this; @@ -1012,14 +1017,14 @@ basic_istream<_CharT, _Traits>::peek() sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __r = this->rdbuf()->sgetc(); if (traits_type::eq_int_type(__r, traits_type::eof())) __state |= ios_base::eofbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1030,7 +1035,7 @@ basic_istream<_CharT, _Traits>::peek() throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS this->setstate(__state); } return __r; @@ -1045,14 +1050,14 @@ basic_istream<_CharT, _Traits>::read(char_type* __s, streamsize __n) sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __gc_ = this->rdbuf()->sgetn(__s, __n); if (__gc_ != __n) __state |= ios_base::failbit | ios_base::eofbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1063,7 +1068,7 @@ basic_istream<_CharT, _Traits>::read(char_type* __s, streamsize __n) throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } else { @@ -1082,10 +1087,10 @@ basic_istream<_CharT, _Traits>::readsome(char_type* __s, streamsize __n) sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS streamsize __c = this->rdbuf()->in_avail(); switch (__c) { @@ -1101,7 +1106,7 @@ basic_istream<_CharT, _Traits>::readsome(char_type* __s, streamsize __n) __state |= ios_base::failbit | ios_base::eofbit; break; } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1112,7 +1117,7 @@ basic_istream<_CharT, _Traits>::readsome(char_type* __s, streamsize __n) throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } else { @@ -1132,13 +1137,13 @@ basic_istream<_CharT, _Traits>::putback(char_type __c) sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (this->rdbuf() == nullptr || this->rdbuf()->sputbackc(__c) == traits_type::eof()) __state |= ios_base::badbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1149,7 +1154,7 @@ basic_istream<_CharT, _Traits>::putback(char_type __c) throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } else { @@ -1169,13 +1174,13 @@ basic_istream<_CharT, _Traits>::unget() sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (this->rdbuf() == nullptr || this->rdbuf()->sungetc() == traits_type::eof()) __state |= ios_base::badbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1186,7 +1191,7 @@ basic_istream<_CharT, _Traits>::unget() throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } else { @@ -1205,10 +1210,10 @@ basic_istream<_CharT, _Traits>::sync() sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (this->rdbuf() == nullptr) return -1; if (this->rdbuf()->pubsync() == -1) @@ -1216,7 +1221,7 @@ basic_istream<_CharT, _Traits>::sync() __state |= ios_base::badbit; return -1; } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1227,7 +1232,7 @@ basic_istream<_CharT, _Traits>::sync() throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS this->setstate(__state); } return __r; @@ -1242,12 +1247,12 @@ basic_istream<_CharT, _Traits>::tellg() sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __r = this->rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1258,7 +1263,7 @@ basic_istream<_CharT, _Traits>::tellg() throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS this->setstate(__state); } return __r; @@ -1273,13 +1278,13 @@ basic_istream<_CharT, _Traits>::seekg(pos_type __pos) sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (this->rdbuf()->pubseekpos(__pos, ios_base::in) == pos_type(-1)) __state |= ios_base::failbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1290,7 +1295,7 @@ basic_istream<_CharT, _Traits>::seekg(pos_type __pos) throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS this->setstate(__state); } return *this; @@ -1305,13 +1310,13 @@ basic_istream<_CharT, _Traits>::seekg(off_type __off, ios_base::seekdir __dir) sentry __sen(*this, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (this->rdbuf()->pubseekoff(__off, __dir, ios_base::in) == pos_type(-1)) __state |= ios_base::failbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1322,7 +1327,7 @@ basic_istream<_CharT, _Traits>::seekg(off_type __off, ios_base::seekdir __dir) throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS this->setstate(__state); } return *this; @@ -1336,10 +1341,10 @@ ws(basic_istream<_CharT, _Traits>& __is) typename basic_istream<_CharT, _Traits>::sentry __sen(__is, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__is.getloc()); while (true) { @@ -1353,7 +1358,7 @@ ws(basic_istream<_CharT, _Traits>& __is) break; __is.rdbuf()->sbumpc(); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1364,7 +1369,7 @@ ws(basic_istream<_CharT, _Traits>& __is) throw; } } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __is.setstate(__state); } return __is; @@ -1450,7 +1455,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, typename basic_istream<_CharT, _Traits>::sentry __sen(__is); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif @@ -1480,7 +1485,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, __is.width(0); if (__c == 0) __state |= ios_base::failbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1506,7 +1511,7 @@ getline(basic_istream<_CharT, _Traits>& __is, typename basic_istream<_CharT, _Traits>::sentry __sen(__is, true); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif @@ -1533,7 +1538,7 @@ getline(basic_istream<_CharT, _Traits>& __is, } if (__extr == 0) __state |= ios_base::failbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1585,7 +1590,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, bitset<_Size>& __x) typename basic_istream<_CharT, _Traits>::sentry __sen(__is); if (__sen) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { #endif @@ -1612,7 +1617,7 @@ operator>>(basic_istream<_CharT, _Traits>& __is, bitset<_Size>& __x) __x = bitset<_Size>(__str); if (_Size > 0 && __c == 0) __state |= ios_base::failbit; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { diff --git a/libcxx/include/iterator b/libcxx/include/iterator index 35eca67b4a5e..42843781ebbf 100644 --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -387,7 +387,7 @@ template <class Iterator> class move_iterator { public: using iterator_type = Iterator; - using iterator_concept = input_iterator_tag; // From C++20 + using iterator_concept = see below; // From C++20 using iterator_category = see below; // not always present starting from C++20 using value_type = iter_value_t<Iterator>; // Until C++20, iterator_traits<Iterator>::value_type using difference_type = iter_difference_t<Iterator>; // Until C++20, iterator_traits<Iterator>::difference_type; @@ -676,7 +676,6 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept; #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include <__debug> #include <__iterator/access.h> #include <__iterator/advance.h> #include <__iterator/back_insert_iterator.h> @@ -732,6 +731,7 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept; #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstdlib> # include <exception> # include <new> # include <type_traits> diff --git a/libcxx/include/latch b/libcxx/include/latch index ff17f8453ea5..47538060eeca 100644 --- a/libcxx/include/latch +++ b/libcxx/include/latch @@ -41,9 +41,12 @@ namespace std */ #include <__assert> // all public C++ headers provide the assertion handler +#include <__atomic/atomic_base.h> +#include <__atomic/atomic_sync.h> +#include <__atomic/memory_order.h> #include <__availability> #include <__config> -#include <atomic> +#include <cstddef> #include <limits> #include <version> @@ -67,22 +70,35 @@ class latch __atomic_base<ptrdiff_t> __a_; public: - static constexpr ptrdiff_t max() noexcept { + static _LIBCPP_HIDE_FROM_ABI constexpr ptrdiff_t max() noexcept { return numeric_limits<ptrdiff_t>::max(); } inline _LIBCPP_INLINE_VISIBILITY - constexpr explicit latch(ptrdiff_t __expected) : __a_(__expected) { } + constexpr explicit latch(ptrdiff_t __expected) : __a_(__expected) + { + _LIBCPP_ASSERT_UNCATEGORIZED(__expected >= 0, + "latch::latch(ptrdiff_t): latch cannot be " + "initialized with a negative value"); + _LIBCPP_ASSERT_UNCATEGORIZED(__expected <= max(), + "latch::latch(ptrdiff_t): latch cannot be " + "initialized with a value greater than max()"); + } - ~latch() = default; + _LIBCPP_HIDE_FROM_ABI ~latch() = default; latch(const latch&) = delete; latch& operator=(const latch&) = delete; inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void count_down(ptrdiff_t __update = 1) { + _LIBCPP_ASSERT_UNCATEGORIZED( + __update >= 0, "latch::count_down called with a negative value"); auto const __old = __a_.fetch_sub(__update, memory_order_release); - if(__old == __update) + _LIBCPP_ASSERT_UNCATEGORIZED( + __update <= __old, "latch::count_down called with a value greater " + "than the internal counter"); + if (__old == __update) __a_.notify_all(); } inline _LIBCPP_INLINE_VISIBILITY @@ -93,13 +109,17 @@ public: inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void wait() const { - __cxx_atomic_wait(&__a_.__a_, [&]() -> bool { + __cxx_atomic_wait(&__a_.__a_, [this]() -> bool { return try_wait(); }); } inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void arrive_and_wait(ptrdiff_t __update = 1) { + _LIBCPP_ASSERT_UNCATEGORIZED( + __update >= 0, "latch::arrive_and_wait called with a negative value"); + // other preconditions on __update are checked in count_down() + count_down(__update); wait(); } @@ -111,4 +131,8 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <atomic> +#endif + #endif //_LIBCPP_LATCH diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp index 575ce0f79d47..f7decae8e386 100644 --- a/libcxx/include/libcxx.imp +++ b/libcxx/include/libcxx.imp @@ -8,7 +8,6 @@ { include: [ "<__node_handle>", "private", "<unordered_set>", "public" ] }, { include: [ "<__split_buffer>", "private", "<deque>", "public" ] }, { include: [ "<__split_buffer>", "private", "<vector>", "public" ] }, - { include: [ "<__std_stream>", "private", "<iostream>", "public" ] }, { include: [ "<__threading_support>", "private", "<atomic>", "public" ] }, { include: [ "<__threading_support>", "private", "<mutex>", "public" ] }, { include: [ "<__threading_support>", "private", "<semaphore>", "public" ] }, @@ -16,13 +15,16 @@ { include: [ "<__tree>", "private", "<map>", "public" ] }, { include: [ "<__tree>", "private", "<set>", "public" ] }, { include: [ "@<__algorithm/.*>", "private", "<algorithm>", "public" ] }, + { include: [ "@<__atomic/.*>", "private", "<atomic>", "public" ] }, { include: [ "@<__bit/.*>", "private", "<bit>", "public" ] }, { include: [ "@<__charconv/.*>", "private", "<charconv>", "public" ] }, { include: [ "@<__chrono/.*>", "private", "<chrono>", "public" ] }, { include: [ "@<__compare/.*>", "private", "<compare>", "public" ] }, { include: [ "@<__concepts/.*>", "private", "<concepts>", "public" ] }, + { include: [ "@<__condition_variable/.*>", "private", "<condition_variable>", "public" ] }, { include: [ "@<__coroutine/.*>", "private", "<coroutine>", "public" ] }, { include: [ "@<__debug_utils/.*>", "private", "<debug_utils>", "public" ] }, + { include: [ "@<__exception/.*>", "private", "<exception>", "public" ] }, { include: [ "@<__expected/.*>", "private", "<expected>", "public" ] }, { include: [ "@<__filesystem/.*>", "private", "<filesystem>", "public" ] }, { include: [ "@<__format/.*>", "private", "<format>", "public" ] }, @@ -30,15 +32,21 @@ { include: [ "@<__fwd/.*>", "private", "<fwd>", "public" ] }, { include: [ "@<__ios/.*>", "private", "<ios>", "public" ] }, { include: [ "@<__iterator/.*>", "private", "<iterator>", "public" ] }, + { include: [ "@<__locale_dir/.*>", "private", "<locale>", "public" ] }, + { include: [ "@<__mdspan/.*>", "private", "<mdspan>", "public" ] }, { include: [ "@<__memory/.*>", "private", "<memory>", "public" ] }, { include: [ "@<__memory_resource/.*>", "private", "<memory_resource>", "public" ] }, + { include: [ "@<__mutex/.*>", "private", "<mutex>", "public" ] }, { include: [ "@<__numeric/.*>", "private", "<numeric>", "public" ] }, + { include: [ "@<__pstl/.*>", "private", "<pstl>", "public" ] }, { include: [ "@<__random/.*>", "private", "<random>", "public" ] }, { include: [ "@<__ranges/.*>", "private", "<ranges>", "public" ] }, + { include: [ "@<__stop_token/.*>", "private", "<stop_token>", "public" ] }, { include: [ "@<__string/.*>", "private", "<string>", "public" ] }, { include: [ "@<__support/.*>", "private", "<support>", "public" ] }, + { include: [ "@<__system_error/.*>", "private", "<system_error>", "public" ] }, { include: [ "@<__thread/.*>", "private", "<thread>", "public" ] }, - { include: [ "@<__tuple_dir/.*>", "private", "<tuple>", "public" ] }, + { include: [ "@<__tuple/.*>", "private", "<tuple>", "public" ] }, { include: [ "@<__type_traits/.*>", "private", "<type_traits>", "public" ] }, { include: [ "@<__utility/.*>", "private", "<utility>", "public" ] }, { include: [ "@<__variant/.*>", "private", "<variant>", "public" ] }, diff --git a/libcxx/include/list b/libcxx/include/list index a0c732739ca2..37bed3cd89fc 100644 --- a/libcxx/include/list +++ b/libcxx/include/list @@ -46,6 +46,8 @@ public: list(Iter first, Iter last); template <class Iter> list(Iter first, Iter last, const allocator_type& a); + template<container-compatible-range<T> R> + list(from_range_t, R&& rg, const Allocator& = Allocator()); // C++23 list(const list& x); list(const list&, const allocator_type& a); list(list&& x) @@ -64,6 +66,8 @@ public: list& operator=(initializer_list<value_type>); template <class Iter> void assign(Iter first, Iter last); + template<container-compatible-range<T> R> + void assign_range(R&& rg); // C++23 void assign(size_type n, const value_type& t); void assign(initializer_list<value_type>); @@ -99,8 +103,12 @@ public: void pop_back(); void push_front(const value_type& x); void push_front(value_type&& x); + template<container-compatible-range<T> R> + void prepend_range(R&& rg); // C++23 void push_back(const value_type& x); void push_back(value_type&& x); + template<container-compatible-range<T> R> + void append_range(R&& rg); // C++23 template <class... Args> iterator emplace(const_iterator position, Args&&... args); iterator insert(const_iterator position, const value_type& x); @@ -108,6 +116,8 @@ public: iterator insert(const_iterator position, size_type n, const value_type& x); template <class Iter> iterator insert(const_iterator position, Iter first, Iter last); + template<container-compatible-range<T> R> + iterator insert_range(const_iterator position, R&& rg); // C++23 iterator insert(const_iterator position, initializer_list<value_type> il); iterator erase(const_iterator position); @@ -152,18 +162,25 @@ template <class InputIterator, class Allocator = allocator<typename iterator_tra list(InputIterator, InputIterator, Allocator = Allocator()) -> list<typename iterator_traits<InputIterator>::value_type, Allocator>; // C++17 +template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> + list(from_range_t, R&&, Allocator = Allocator()) + -> list<ranges::range_value_t<R>, Allocator>; // C++23 + template <class T, class Alloc> bool operator==(const list<T,Alloc>& x, const list<T,Alloc>& y); template <class T, class Alloc> - bool operator< (const list<T,Alloc>& x, const list<T,Alloc>& y); + bool operator< (const list<T,Alloc>& x, const list<T,Alloc>& y); // removed in C++20 template <class T, class Alloc> - bool operator!=(const list<T,Alloc>& x, const list<T,Alloc>& y); + bool operator!=(const list<T,Alloc>& x, const list<T,Alloc>& y); // removed in C++20 template <class T, class Alloc> - bool operator> (const list<T,Alloc>& x, const list<T,Alloc>& y); + bool operator> (const list<T,Alloc>& x, const list<T,Alloc>& y); // removed in C++20 template <class T, class Alloc> - bool operator>=(const list<T,Alloc>& x, const list<T,Alloc>& y); + bool operator>=(const list<T,Alloc>& x, const list<T,Alloc>& y); // removed in C++20 template <class T, class Alloc> - bool operator<=(const list<T,Alloc>& x, const list<T,Alloc>& y); + bool operator<=(const list<T,Alloc>& x, const list<T,Alloc>& y); // removed in C++20 +template<class T, class Allocator> + synth-three-way-result<T> operator<=>(const list<T, Allocator>& x, + const list<T, Allocator>& y); // since C++20 template <class T, class Alloc> void swap(list<T,Alloc>& x, list<T,Alloc>& y) @@ -171,10 +188,10 @@ template <class T, class Alloc> template <class T, class Allocator, class U> typename list<T, Allocator>::size_type - erase(list<T, Allocator>& c, const U& value); // C++20 + erase(list<T, Allocator>& c, const U& value); // since C++20 template <class T, class Allocator, class Predicate> typename list<T, Allocator>::size_type - erase_if(list<T, Allocator>& c, Predicate pred); // C++20 + erase_if(list<T, Allocator>& c, Predicate pred); // since C++20 } // std @@ -183,10 +200,11 @@ template <class T, class Allocator, class Predicate> #include <__algorithm/comp.h> #include <__algorithm/equal.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/min.h> #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> #include <__config> -#include <__debug> #include <__format/enable_insertable.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> @@ -203,13 +221,23 @@ template <class T, class Allocator, class Predicate> #include <__memory/swap_allocator.h> #include <__memory/unique_ptr.h> #include <__memory_resource/polymorphic_allocator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> +#include <__type_traits/conditional.h> #include <__type_traits/is_allocator.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_pointer.h> +#include <__type_traits/is_same.h> +#include <__type_traits/type_identity.h> #include <__utility/forward.h> #include <__utility/move.h> #include <__utility/swap.h> #include <cstring> #include <limits> -#include <type_traits> #include <version> // standard-mandated includes @@ -320,13 +348,9 @@ class _LIBCPP_TEMPLATE_VIS __list_iterator __link_pointer __ptr_; _LIBCPP_INLINE_VISIBILITY - explicit __list_iterator(__link_pointer __p, const void* __c) _NOEXCEPT + explicit __list_iterator(__link_pointer __p) _NOEXCEPT : __ptr_(__p) { - (void)__c; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__insert_ic(this, __c); -#endif } template<class, class> friend class list; @@ -342,57 +366,22 @@ public: _LIBCPP_INLINE_VISIBILITY __list_iterator() _NOEXCEPT : __ptr_(nullptr) { - _VSTD::__debug_db_insert_i(this); - } - -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - _LIBCPP_INLINE_VISIBILITY - __list_iterator(const __list_iterator& __p) - : __ptr_(__p.__ptr_) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__p)); - } - - _LIBCPP_INLINE_VISIBILITY - ~__list_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __list_iterator& operator=(const __list_iterator& __p) - { - if (this != _VSTD::addressof(__p)) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__p)); - __ptr_ = __p.__ptr_; - } - return *this; } -#endif // _LIBCPP_ENABLE_DEBUG_MODE - _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable list::iterator"); return __ptr_->__as_node()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable list::iterator"); return pointer_traits<pointer>::pointer_to(__ptr_->__as_node()->__value_); } _LIBCPP_INLINE_VISIBILITY __list_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable list::iterator"); __ptr_ = __ptr_->__next_; return *this; } @@ -402,8 +391,6 @@ public: _LIBCPP_INLINE_VISIBILITY __list_iterator& operator--() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__decrementable(this), - "Attempted to decrement a non-decrementable list::iterator"); __ptr_ = __ptr_->__prev_; return *this; } @@ -429,13 +416,9 @@ class _LIBCPP_TEMPLATE_VIS __list_const_iterator __link_pointer __ptr_; _LIBCPP_INLINE_VISIBILITY - explicit __list_const_iterator(__link_pointer __p, const void* __c) _NOEXCEPT + explicit __list_const_iterator(__link_pointer __p) _NOEXCEPT : __ptr_(__p) { - (void)__c; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__insert_ic(this, __c); -#endif } template<class, class> friend class list; @@ -450,64 +433,27 @@ public: _LIBCPP_INLINE_VISIBILITY __list_const_iterator() _NOEXCEPT : __ptr_(nullptr) { - _VSTD::__debug_db_insert_i(this); } _LIBCPP_INLINE_VISIBILITY __list_const_iterator(const __list_iterator<_Tp, _VoidPtr>& __p) _NOEXCEPT : __ptr_(__p.__ptr_) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __get_db()->__iterator_copy(this, _VSTD::addressof(__p)); -#endif - } - -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - _LIBCPP_INLINE_VISIBILITY - __list_const_iterator(const __list_const_iterator& __p) - : __ptr_(__p.__ptr_) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__p)); - } - - _LIBCPP_INLINE_VISIBILITY - ~__list_const_iterator() - { - __get_db()->__erase_i(this); - } - - _LIBCPP_INLINE_VISIBILITY - __list_const_iterator& operator=(const __list_const_iterator& __p) - { - if (this != _VSTD::addressof(__p)) - { - __get_db()->__iterator_copy(this, _VSTD::addressof(__p)); - __ptr_ = __p.__ptr_; - } - return *this; } -#endif // _LIBCPP_ENABLE_DEBUG_MODE _LIBCPP_INLINE_VISIBILITY reference operator*() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable list::const_iterator"); return __ptr_->__as_node()->__value_; } _LIBCPP_INLINE_VISIBILITY pointer operator->() const { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to dereference a non-dereferenceable list::const_iterator"); return pointer_traits<pointer>::pointer_to(__ptr_->__as_node()->__value_); } _LIBCPP_INLINE_VISIBILITY __list_const_iterator& operator++() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this), - "Attempted to increment a non-incrementable list::const_iterator"); __ptr_ = __ptr_->__next_; return *this; } @@ -517,8 +463,6 @@ public: _LIBCPP_INLINE_VISIBILITY __list_const_iterator& operator--() { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__decrementable(this), - "Attempted to decrement a non-decrementable list::const_iterator"); __ptr_ = __ptr_->__prev_; return *this; } @@ -604,35 +548,35 @@ protected: _LIBCPP_INLINE_VISIBILITY __list_imp(const __node_allocator& __a); #ifndef _LIBCPP_CXX03_LANG - __list_imp(__node_allocator&& __a) _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI __list_imp(__node_allocator&& __a) _NOEXCEPT; #endif - ~__list_imp(); - void clear() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI ~__list_imp(); + _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT {return __sz() == 0;} _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT { - return iterator(__end_.__next_, this); + return iterator(__end_.__next_); } _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT { - return const_iterator(__end_.__next_, this); + return const_iterator(__end_.__next_); } _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT { - return iterator(__end_as_link(), this); + return iterator(__end_as_link()); } _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT { - return const_iterator(__end_as_link(), this); + return const_iterator(__end_as_link()); } - void swap(__list_imp& __c) + _LIBCPP_HIDE_FROM_ABI void swap(__list_imp& __c) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else @@ -718,7 +662,6 @@ inline __list_imp<_Tp, _Alloc>::__list_imp(__node_allocator&& __a) _NOEXCEPT template <class _Tp, class _Alloc> __list_imp<_Tp, _Alloc>::~__list_imp() { clear(); - std::__debug_db_erase_c(this); } template <class _Tp, class _Alloc> @@ -739,7 +682,6 @@ __list_imp<_Tp, _Alloc>::clear() _NOEXCEPT __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_)); __node_alloc_traits::deallocate(__na, __np, 1); } - std::__debug_db_invalidate_all(this); } } @@ -753,10 +695,10 @@ __list_imp<_Tp, _Alloc>::swap(__list_imp& __c) __is_nothrow_swappable<allocator_type>::value) #endif { - _LIBCPP_ASSERT(__alloc_traits::propagate_on_container_swap::value || - this->__node_alloc() == __c.__node_alloc(), - "list::swap: Either propagate_on_container_swap must be true" - " or the allocators must compare equal"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__alloc_traits::propagate_on_container_swap::value || + this->__node_alloc() == __c.__node_alloc(), + "list::swap: Either propagate_on_container_swap must be true" + " or the allocators must compare equal"); using _VSTD::swap; _VSTD::__swap_allocator(__node_alloc(), __c.__node_alloc()); swap(__sz(), __c.__sz()); @@ -769,42 +711,6 @@ __list_imp<_Tp, _Alloc>::swap(__list_imp& __c) __c.__end_.__next_ = __c.__end_.__prev_ = __c.__end_as_link(); else __c.__end_.__prev_->__next_ = __c.__end_.__next_->__prev_ = __c.__end_as_link(); - -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __libcpp_db* __db = __get_db(); - __c_node* __cn1 = __db->__find_c_and_lock(this); - __c_node* __cn2 = __db->__find_c(_VSTD::addressof(__c)); - _VSTD::swap(__cn1->beg_, __cn2->beg_); - _VSTD::swap(__cn1->end_, __cn2->end_); - _VSTD::swap(__cn1->cap_, __cn2->cap_); - for (__i_node** __p = __cn1->end_; __p != __cn1->beg_;) - { - --__p; - const_iterator* __i = static_cast<const_iterator*>((*__p)->__i_); - if (__i->__ptr_ == __c.__end_as_link()) - { - __cn2->__add(*__p); - if (--__cn1->end_ != __p) - _VSTD::memmove(__p, __p+1, (__cn1->end_ - __p)*sizeof(__i_node*)); - } - else - (*__p)->__c_ = __cn1; - } - for (__i_node** __p = __cn2->end_; __p != __cn2->beg_;) - { - --__p; - const_iterator* __i = static_cast<const_iterator*>((*__p)->__i_); - if (__i->__ptr_ == __end_as_link()) - { - __cn1->__add(*__p); - if (--__cn2->end_ != __p) - _VSTD::memmove(__p, __p+1, (__cn2->end_ - __p)*sizeof(__i_node*)); - } - else - (*__p)->__c_ = __cn2; - } - __db->unlock(); -#endif } template <class _Tp, class _Alloc /*= allocator<_Tp>*/> @@ -824,7 +730,7 @@ public: typedef _Tp value_type; typedef _Alloc allocator_type; static_assert((is_same<value_type, typename allocator_type::value_type>::value), - "Invalid allocator::value_type"); + "Allocator::value_type must be same type as value_type"); typedef value_type& reference; typedef const value_type& const_reference; typedef typename base::pointer pointer; @@ -835,7 +741,7 @@ public: typedef typename base::const_iterator const_iterator; typedef _VSTD::reverse_iterator<iterator> reverse_iterator; typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 typedef size_type __remove_return_type; #else typedef void __remove_return_type; @@ -849,40 +755,45 @@ public: list() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value) { - _VSTD::__debug_db_insert_c(this); } _LIBCPP_INLINE_VISIBILITY explicit list(const allocator_type& __a) : base(__a) { - _VSTD::__debug_db_insert_c(this); } - explicit list(size_type __n); -#if _LIBCPP_STD_VER > 11 - explicit list(size_type __n, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI explicit list(size_type __n); +#if _LIBCPP_STD_VER >= 14 + _LIBCPP_HIDE_FROM_ABI explicit list(size_type __n, const allocator_type& __a); #endif - list(size_type __n, const value_type& __x); + _LIBCPP_HIDE_FROM_ABI list(size_type __n, const value_type& __x); template <class = __enable_if_t<__is_allocator<_Alloc>::value> > - list(size_type __n, const value_type& __x, const allocator_type& __a) : base(__a) + _LIBCPP_HIDE_FROM_ABI list(size_type __n, const value_type& __x, const allocator_type& __a) : base(__a) { - _VSTD::__debug_db_insert_c(this); for (; __n > 0; --__n) push_back(__x); } template <class _InpIter> - list(_InpIter __f, _InpIter __l, - __enable_if_t<__is_cpp17_input_iterator<_InpIter>::value>* = 0); + _LIBCPP_HIDE_FROM_ABI list(_InpIter __f, _InpIter __l, + __enable_if_t<__has_input_iterator_category<_InpIter>::value>* = 0); template <class _InpIter> - list(_InpIter __f, _InpIter __l, const allocator_type& __a, - __enable_if_t<__is_cpp17_input_iterator<_InpIter>::value>* = 0); + _LIBCPP_HIDE_FROM_ABI list(_InpIter __f, _InpIter __l, const allocator_type& __a, + __enable_if_t<__has_input_iterator_category<_InpIter>::value>* = 0); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI list(from_range_t, _Range&& __range, + const allocator_type& __a = allocator_type()) : base(__a) { + prepend_range(std::forward<_Range>(__range)); + } +#endif - list(const list& __c); - list(const list& __c, const __type_identity_t<allocator_type>& __a); + _LIBCPP_HIDE_FROM_ABI list(const list& __c); + _LIBCPP_HIDE_FROM_ABI list(const list& __c, const __type_identity_t<allocator_type>& __a); _LIBCPP_INLINE_VISIBILITY list& operator=(const list& __c); #ifndef _LIBCPP_CXX03_LANG - list(initializer_list<value_type> __il); - list(initializer_list<value_type> __il, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI list(initializer_list<value_type> __il); + _LIBCPP_HIDE_FROM_ABI list(initializer_list<value_type> __il, const allocator_type& __a); _LIBCPP_INLINE_VISIBILITY list(list&& __c) @@ -905,9 +816,18 @@ public: #endif // _LIBCPP_CXX03_LANG template <class _InpIter> - void assign(_InpIter __f, _InpIter __l, - __enable_if_t<__is_cpp17_input_iterator<_InpIter>::value>* = 0); - void assign(size_type __n, const value_type& __x); + _LIBCPP_HIDE_FROM_ABI void assign(_InpIter __f, _InpIter __l, + __enable_if_t<__has_input_iterator_category<_InpIter>::value>* = 0); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void assign_range(_Range&& __range) { + __assign_with_sentinel(ranges::begin(__range), ranges::end(__range)); + } +#endif + + _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const value_type& __x); _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT; @@ -959,56 +879,70 @@ public: _LIBCPP_INLINE_VISIBILITY reference front() { - _LIBCPP_ASSERT(!empty(), "list::front called on empty list"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::front called on empty list"); return base::__end_.__next_->__as_node()->__value_; } _LIBCPP_INLINE_VISIBILITY const_reference front() const { - _LIBCPP_ASSERT(!empty(), "list::front called on empty list"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::front called on empty list"); return base::__end_.__next_->__as_node()->__value_; } _LIBCPP_INLINE_VISIBILITY reference back() { - _LIBCPP_ASSERT(!empty(), "list::back called on empty list"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::back called on empty list"); return base::__end_.__prev_->__as_node()->__value_; } _LIBCPP_INLINE_VISIBILITY const_reference back() const { - _LIBCPP_ASSERT(!empty(), "list::back called on empty list"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::back called on empty list"); return base::__end_.__prev_->__as_node()->__value_; } #ifndef _LIBCPP_CXX03_LANG - void push_front(value_type&& __x); - void push_back(value_type&& __x); + _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x); + _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void prepend_range(_Range&& __range) { + insert_range(begin(), std::forward<_Range>(__range)); + } + + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void append_range(_Range&& __range) { + insert_range(end(), std::forward<_Range>(__range)); + } +#endif template <class... _Args> -#if _LIBCPP_STD_VER > 14 - reference emplace_front(_Args&&... __args); +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_HIDE_FROM_ABI reference emplace_front(_Args&&... __args); #else - void emplace_front(_Args&&... __args); + _LIBCPP_HIDE_FROM_ABI void emplace_front(_Args&&... __args); #endif template <class... _Args> -#if _LIBCPP_STD_VER > 14 - reference emplace_back(_Args&&... __args); +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_HIDE_FROM_ABI reference emplace_back(_Args&&... __args); #else - void emplace_back(_Args&&... __args); + _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args); #endif template <class... _Args> - iterator emplace(const_iterator __p, _Args&&... __args); + _LIBCPP_HIDE_FROM_ABI iterator emplace(const_iterator __p, _Args&&... __args); - iterator insert(const_iterator __p, value_type&& __x); + _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, value_type&& __x); _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __p, initializer_list<value_type> __il) {return insert(__p, __il.begin(), __il.end());} #endif // _LIBCPP_CXX03_LANG - void push_front(const value_type& __x); - void push_back(const value_type& __x); + _LIBCPP_HIDE_FROM_ABI void push_front(const value_type& __x); + _LIBCPP_HIDE_FROM_ABI void push_back(const value_type& __x); #ifndef _LIBCPP_CXX03_LANG template <class _Arg> @@ -1019,11 +953,19 @@ public: void __emplace_back(value_type const& __arg) { push_back(__arg); } #endif - iterator insert(const_iterator __p, const value_type& __x); - iterator insert(const_iterator __p, size_type __n, const value_type& __x); + _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, const value_type& __x); + _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, size_type __n, const value_type& __x); template <class _InpIter> - iterator insert(const_iterator __p, _InpIter __f, _InpIter __l, - __enable_if_t<__is_cpp17_input_iterator<_InpIter>::value>* = 0); + _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __p, _InpIter __f, _InpIter __l, + __enable_if_t<__has_input_iterator_category<_InpIter>::value>* = 0); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + iterator insert_range(const_iterator __position, _Range&& __range) { + return __insert_with_sentinel(__position, ranges::begin(__range), ranges::end(__range)); + } +#endif _LIBCPP_INLINE_VISIBILITY void swap(list& __c) @@ -1037,16 +979,16 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {base::clear();} - void pop_front(); - void pop_back(); + _LIBCPP_HIDE_FROM_ABI void pop_front(); + _LIBCPP_HIDE_FROM_ABI void pop_back(); - iterator erase(const_iterator __p); - iterator erase(const_iterator __f, const_iterator __l); + _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p); + _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __f, const_iterator __l); - void resize(size_type __n); - void resize(size_type __n, const value_type& __x); + _LIBCPP_HIDE_FROM_ABI void resize(size_type __n); + _LIBCPP_HIDE_FROM_ABI void resize(size_type __n, const value_type& __x); - void splice(const_iterator __p, list& __c); + _LIBCPP_HIDE_FROM_ABI void splice(const_iterator __p, list& __c); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void splice(const_iterator __p, list&& __c) {splice(__p, __c);} @@ -1057,15 +999,16 @@ public: void splice(const_iterator __p, list&& __c, const_iterator __f, const_iterator __l) {splice(__p, __c, __f, __l);} #endif - void splice(const_iterator __p, list& __c, const_iterator __i); - void splice(const_iterator __p, list& __c, const_iterator __f, const_iterator __l); + _LIBCPP_HIDE_FROM_ABI void splice(const_iterator __p, list& __c, const_iterator __i); + _LIBCPP_HIDE_FROM_ABI void splice(const_iterator __p, list& __c, const_iterator __f, const_iterator __l); - __remove_return_type remove(const value_type& __x); - template <class _Pred> __remove_return_type remove_if(_Pred __pred); + _LIBCPP_HIDE_FROM_ABI __remove_return_type remove(const value_type& __x); + template <class _Pred> + _LIBCPP_HIDE_FROM_ABI __remove_return_type remove_if(_Pred __pred); _LIBCPP_INLINE_VISIBILITY __remove_return_type unique() { return unique(__equal_to()); } template <class _BinaryPred> - __remove_return_type unique(_BinaryPred __binary_pred); + _LIBCPP_HIDE_FROM_ABI __remove_return_type unique(_BinaryPred __binary_pred); _LIBCPP_INLINE_VISIBILITY void merge(list& __c); #ifndef _LIBCPP_CXX03_LANG @@ -1077,7 +1020,7 @@ public: void merge(list&& __c, _Comp __comp) {merge(__c, __comp);} #endif template <class _Comp> - void merge(list& __c, _Comp __comp); + _LIBCPP_HIDE_FROM_ABI void merge(list& __c, _Comp __comp); _LIBCPP_INLINE_VISIBILITY void sort(); @@ -1085,9 +1028,9 @@ public: _LIBCPP_INLINE_VISIBILITY void sort(_Comp __comp); - void reverse() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI void reverse() _NOEXCEPT; - bool __invariants() const; + _LIBCPP_HIDE_FROM_ABI bool __invariants() const; typedef __allocator_destructor<__node_allocator> __node_destructor; typedef unique_ptr<__node, __node_destructor> __hold_pointer; @@ -1099,35 +1042,35 @@ public: return __hold_pointer(__p, __node_destructor(__na, 1)); } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - bool __dereferenceable(const const_iterator* __i) const; - bool __decrementable(const const_iterator* __i) const; - bool __addable(const const_iterator* __i, ptrdiff_t __n) const; - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; +private: + template <class _Iterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI + void __assign_with_sentinel(_Iterator __f, _Sentinel __l); -#endif // _LIBCPP_ENABLE_DEBUG_MODE + template <class _Iterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI + iterator __insert_with_sentinel(const_iterator __p, _Iterator __f, _Sentinel __l); -private: _LIBCPP_INLINE_VISIBILITY static void __link_nodes (__link_pointer __p, __link_pointer __f, __link_pointer __l); _LIBCPP_INLINE_VISIBILITY void __link_nodes_at_front(__link_pointer __f, __link_pointer __l); _LIBCPP_INLINE_VISIBILITY void __link_nodes_at_back (__link_pointer __f, __link_pointer __l); - iterator __iterator(size_type __n); + _LIBCPP_HIDE_FROM_ABI iterator __iterator(size_type __n); + // TODO: Make this _LIBCPP_HIDE_FROM_ABI template <class _Comp> - static iterator __sort(iterator __f1, iterator __e2, size_type __n, _Comp& __comp); + _LIBCPP_HIDDEN static iterator __sort(iterator __f1, iterator __e2, size_type __n, _Comp& __comp); - void __move_assign(list& __c, true_type) + _LIBCPP_HIDE_FROM_ABI void __move_assign(list& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value); - void __move_assign(list& __c, false_type); + _LIBCPP_HIDE_FROM_ABI void __move_assign(list& __c, false_type); }; #if _LIBCPP_STD_VER >= 17 template<class _InputIterator, class _Alloc = allocator<__iter_value_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Alloc>::value> > list(_InputIterator, _InputIterator) @@ -1135,13 +1078,22 @@ list(_InputIterator, _InputIterator) template<class _InputIterator, class _Alloc, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Alloc>::value> > list(_InputIterator, _InputIterator, _Alloc) -> list<__iter_value_type<_InputIterator>, _Alloc>; #endif +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, + class _Alloc = allocator<ranges::range_value_t<_Range>>, + class = enable_if_t<__is_allocator<_Alloc>::value> + > +list(from_range_t, _Range&&, _Alloc = _Alloc()) + -> list<ranges::range_value_t<_Range>, _Alloc>; +#endif + // Link in nodes [__f, __l] just prior to __p template <class _Tp, class _Alloc> inline @@ -1191,7 +1143,6 @@ list<_Tp, _Alloc>::__iterator(size_type __n) template <class _Tp, class _Alloc> list<_Tp, _Alloc>::list(size_type __n) { - _VSTD::__debug_db_insert_c(this); for (; __n > 0; --__n) #ifndef _LIBCPP_CXX03_LANG emplace_back(); @@ -1200,11 +1151,10 @@ list<_Tp, _Alloc>::list(size_type __n) #endif } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp, class _Alloc> list<_Tp, _Alloc>::list(size_type __n, const allocator_type& __a) : base(__a) { - _VSTD::__debug_db_insert_c(this); for (; __n > 0; --__n) emplace_back(); } @@ -1213,7 +1163,6 @@ list<_Tp, _Alloc>::list(size_type __n, const allocator_type& __a) : base(__a) template <class _Tp, class _Alloc> list<_Tp, _Alloc>::list(size_type __n, const value_type& __x) { - _VSTD::__debug_db_insert_c(this); for (; __n > 0; --__n) push_back(__x); } @@ -1221,9 +1170,8 @@ list<_Tp, _Alloc>::list(size_type __n, const value_type& __x) template <class _Tp, class _Alloc> template <class _InpIter> list<_Tp, _Alloc>::list(_InpIter __f, _InpIter __l, - __enable_if_t<__is_cpp17_input_iterator<_InpIter>::value>*) + __enable_if_t<__has_input_iterator_category<_InpIter>::value>*) { - _VSTD::__debug_db_insert_c(this); for (; __f != __l; ++__f) __emplace_back(*__f); } @@ -1231,10 +1179,9 @@ list<_Tp, _Alloc>::list(_InpIter __f, _InpIter __l, template <class _Tp, class _Alloc> template <class _InpIter> list<_Tp, _Alloc>::list(_InpIter __f, _InpIter __l, const allocator_type& __a, - __enable_if_t<__is_cpp17_input_iterator<_InpIter>::value>*) + __enable_if_t<__has_input_iterator_category<_InpIter>::value>*) : base(__a) { - _VSTD::__debug_db_insert_c(this); for (; __f != __l; ++__f) __emplace_back(*__f); } @@ -1243,7 +1190,6 @@ template <class _Tp, class _Alloc> list<_Tp, _Alloc>::list(const list& __c) : base(__node_alloc_traits::select_on_container_copy_construction( __c.__node_alloc())) { - _VSTD::__debug_db_insert_c(this); for (const_iterator __i = __c.begin(), __e = __c.end(); __i != __e; ++__i) push_back(*__i); } @@ -1252,7 +1198,6 @@ template <class _Tp, class _Alloc> list<_Tp, _Alloc>::list(const list& __c, const __type_identity_t<allocator_type>& __a) : base(__a) { - _VSTD::__debug_db_insert_c(this); for (const_iterator __i = __c.begin(), __e = __c.end(); __i != __e; ++__i) push_back(*__i); } @@ -1263,7 +1208,6 @@ template <class _Tp, class _Alloc> list<_Tp, _Alloc>::list(initializer_list<value_type> __il, const allocator_type& __a) : base(__a) { - _VSTD::__debug_db_insert_c(this); for (typename initializer_list<value_type>::const_iterator __i = __il.begin(), __e = __il.end(); __i != __e; ++__i) push_back(*__i); @@ -1272,7 +1216,6 @@ list<_Tp, _Alloc>::list(initializer_list<value_type> __il, const allocator_type& template <class _Tp, class _Alloc> list<_Tp, _Alloc>::list(initializer_list<value_type> __il) { - _VSTD::__debug_db_insert_c(this); for (typename initializer_list<value_type>::const_iterator __i = __il.begin(), __e = __il.end(); __i != __e; ++__i) push_back(*__i); @@ -1282,7 +1225,6 @@ template <class _Tp, class _Alloc> inline list<_Tp, _Alloc>::list(list&& __c) _NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value) : base(_VSTD::move(__c.__node_alloc())) { - _VSTD::__debug_db_insert_c(this); splice(end(), __c); } @@ -1291,7 +1233,6 @@ inline list<_Tp, _Alloc>::list(list&& __c, const __type_identity_t<allocator_type>& __a) : base(__a) { - _VSTD::__debug_db_insert_c(this); if (__a == __c.get_allocator()) splice(end(), __c); else @@ -1356,17 +1297,23 @@ template <class _Tp, class _Alloc> template <class _InpIter> void list<_Tp, _Alloc>::assign(_InpIter __f, _InpIter __l, - __enable_if_t<__is_cpp17_input_iterator<_InpIter>::value>*) + __enable_if_t<__has_input_iterator_category<_InpIter>::value>*) { + __assign_with_sentinel(__f, __l); +} + +template <class _Tp, class _Alloc> +template <class _Iterator, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI +void list<_Tp, _Alloc>::__assign_with_sentinel(_Iterator __f, _Sentinel __l) { iterator __i = begin(); iterator __e = end(); for (; __f != __l && __i != __e; ++__f, (void) ++__i) *__i = *__f; if (__i == __e) - insert(__e, __f, __l); + __insert_with_sentinel(__e, std::move(__f), std::move(__l)); else erase(__i, __e); - std::__debug_db_invalidate_all(this); } template <class _Tp, class _Alloc> @@ -1381,7 +1328,6 @@ list<_Tp, _Alloc>::assign(size_type __n, const value_type& __x) insert(__e, __n, __x); else erase(__i, __e); - std::__debug_db_invalidate_all(this); } template <class _Tp, class _Alloc> @@ -1396,23 +1342,19 @@ template <class _Tp, class _Alloc> typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, const value_type& __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "list::insert(iterator, x) called with an iterator not referring to this list"); __node_allocator& __na = base::__node_alloc(); __hold_pointer __hold = __allocate_node(__na); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x); __link_nodes(__p.__ptr_, __hold->__as_link(), __hold->__as_link()); ++base::__sz(); - return iterator(__hold.release()->__as_link(), this); + return iterator(__hold.release()->__as_link()); } template <class _Tp, class _Alloc> typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "list::insert(iterator, n, x) called with an iterator not referring to this list"); - iterator __r(__p.__ptr_, this); + iterator __r(__p.__ptr_); if (__n > 0) { size_type __ds = 0; @@ -1420,13 +1362,13 @@ list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& _ __hold_pointer __hold = __allocate_node(__na); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x); ++__ds; - __r = iterator(__hold->__as_link(), this); + __r = iterator(__hold->__as_link()); __hold.release(); iterator __e = __r; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (--__n; __n != 0; --__n, (void) ++__e, ++__ds) { __hold.reset(__node_alloc_traits::allocate(__na, 1)); @@ -1435,7 +1377,7 @@ list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& _ __hold->__prev_ = __e.__ptr_; __hold.release(); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1446,11 +1388,11 @@ list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& _ __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1); if (__prev == 0) break; - __e = iterator(__prev, this); + __e = iterator(__prev); } throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __link_nodes(__p.__ptr_, __r.__ptr_, __e.__ptr_); base::__sz() += __ds; } @@ -1461,11 +1403,17 @@ template <class _Tp, class _Alloc> template <class _InpIter> typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, _InpIter __f, _InpIter __l, - __enable_if_t<__is_cpp17_input_iterator<_InpIter>::value>*) + __enable_if_t<__has_input_iterator_category<_InpIter>::value>*) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "list::insert(iterator, range) called with an iterator not referring to this list"); - iterator __r(__p.__ptr_, this); + return __insert_with_sentinel(__p, __f, __l); +} + +template <class _Tp, class _Alloc> +template <class _Iterator, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI +typename list<_Tp, _Alloc>::iterator +list<_Tp, _Alloc>::__insert_with_sentinel(const_iterator __p, _Iterator __f, _Sentinel __l) { + iterator __r(__p.__ptr_); if (__f != __l) { size_type __ds = 0; @@ -1473,13 +1421,13 @@ list<_Tp, _Alloc>::insert(const_iterator __p, _InpIter __f, _InpIter __l, __hold_pointer __hold = __allocate_node(__na); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), *__f); ++__ds; - __r = iterator(__hold.get()->__as_link(), this); + __r = iterator(__hold.get()->__as_link()); __hold.release(); iterator __e = __r; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (++__f; __f != __l; ++__f, (void) ++__e, ++__ds) { __hold.reset(__node_alloc_traits::allocate(__na, 1)); @@ -1488,7 +1436,7 @@ list<_Tp, _Alloc>::insert(const_iterator __p, _InpIter __f, _InpIter __l, __hold->__prev_ = __e.__ptr_; __hold.release(); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1499,11 +1447,11 @@ list<_Tp, _Alloc>::insert(const_iterator __p, _InpIter __f, _InpIter __l, __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1); if (__prev == 0) break; - __e = iterator(__prev, this); + __e = iterator(__prev); } throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __link_nodes(__p.__ptr_, __r.__ptr_, __e.__ptr_); base::__sz() += __ds; } @@ -1563,7 +1511,7 @@ list<_Tp, _Alloc>::push_back(value_type&& __x) template <class _Tp, class _Alloc> template <class... _Args> -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typename list<_Tp, _Alloc>::reference #else void @@ -1575,7 +1523,7 @@ list<_Tp, _Alloc>::emplace_front(_Args&&... __args) __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::forward<_Args>(__args)...); __link_nodes_at_front(__hold.get()->__as_link(), __hold.get()->__as_link()); ++base::__sz(); -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return __hold.release()->__value_; #else __hold.release(); @@ -1584,7 +1532,7 @@ list<_Tp, _Alloc>::emplace_front(_Args&&... __args) template <class _Tp, class _Alloc> template <class... _Args> -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typename list<_Tp, _Alloc>::reference #else void @@ -1597,7 +1545,7 @@ list<_Tp, _Alloc>::emplace_back(_Args&&... __args) __link_pointer __nl = __hold->__as_link(); __link_nodes_at_back(__nl, __nl); ++base::__sz(); -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return __hold.release()->__value_; #else __hold.release(); @@ -1609,8 +1557,6 @@ template <class... _Args> typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::emplace(const_iterator __p, _Args&&... __args) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "list::emplace(iterator, args...) called with an iterator not referring to this list"); __node_allocator& __na = base::__node_alloc(); __hold_pointer __hold = __allocate_node(__na); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::forward<_Args>(__args)...); @@ -1618,15 +1564,13 @@ list<_Tp, _Alloc>::emplace(const_iterator __p, _Args&&... __args) __link_nodes(__p.__ptr_, __nl, __nl); ++base::__sz(); __hold.release(); - return iterator(__nl, this); + return iterator(__nl); } template <class _Tp, class _Alloc> typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, value_type&& __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "list::insert(iterator, x) called with an iterator not referring to this list"); __node_allocator& __na = base::__node_alloc(); __hold_pointer __hold = __allocate_node(__na); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), _VSTD::move(__x)); @@ -1634,7 +1578,7 @@ list<_Tp, _Alloc>::insert(const_iterator __p, value_type&& __x) __link_nodes(__p.__ptr_, __nl, __nl); ++base::__sz(); __hold.release(); - return iterator(__nl, this); + return iterator(__nl); } #endif // _LIBCPP_CXX03_LANG @@ -1643,26 +1587,11 @@ template <class _Tp, class _Alloc> void list<_Tp, _Alloc>::pop_front() { - _LIBCPP_ASSERT(!empty(), "list::pop_front() called with empty list"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::pop_front() called with empty list"); __node_allocator& __na = base::__node_alloc(); __link_pointer __n = base::__end_.__next_; base::__unlink_nodes(__n, __n); --base::__sz(); -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __p = __c->end_; __p != __c->beg_; ) - { - --__p; - iterator* __i = static_cast<iterator*>((*__p)->__i_); - if (__i->__ptr_ == __n) - { - (*__p)->__c_ = nullptr; - if (--__c->end_ != __p) - _VSTD::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#endif __node_pointer __np = __n->__as_node(); __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_)); __node_alloc_traits::deallocate(__na, __np, 1); @@ -1672,26 +1601,11 @@ template <class _Tp, class _Alloc> void list<_Tp, _Alloc>::pop_back() { - _LIBCPP_ASSERT(!empty(), "list::pop_back() called on an empty list"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::pop_back() called on an empty list"); __node_allocator& __na = base::__node_alloc(); __link_pointer __n = base::__end_.__prev_; base::__unlink_nodes(__n, __n); --base::__sz(); -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __p = __c->end_; __p != __c->beg_; ) - { - --__p; - iterator* __i = static_cast<iterator*>((*__p)->__i_); - if (__i->__ptr_ == __n) - { - (*__p)->__c_ = nullptr; - if (--__c->end_ != __p) - _VSTD::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#endif __node_pointer __np = __n->__as_node(); __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_)); __node_alloc_traits::deallocate(__na, __np, 1); @@ -1701,44 +1615,23 @@ template <class _Tp, class _Alloc> typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::erase(const_iterator __p) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "list::erase(iterator) called with an iterator not referring to this list"); - _LIBCPP_ASSERT(__p != end(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p != end(), "list::erase(iterator) called with a non-dereferenceable iterator"); __node_allocator& __na = base::__node_alloc(); __link_pointer __n = __p.__ptr_; __link_pointer __r = __n->__next_; base::__unlink_nodes(__n, __n); --base::__sz(); -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __ip = __c->end_; __ip != __c->beg_; ) - { - --__ip; - iterator* __i = static_cast<iterator*>((*__ip)->__i_); - if (__i->__ptr_ == __n) - { - (*__ip)->__c_ = nullptr; - if (--__c->end_ != __ip) - _VSTD::memmove(__ip, __ip+1, (__c->end_ - __ip)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#endif __node_pointer __np = __n->__as_node(); __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_)); __node_alloc_traits::deallocate(__na, __np, 1); - return iterator(__r, this); + return iterator(__r); } template <class _Tp, class _Alloc> typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::erase(const_iterator __f, const_iterator __l) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__f)) == this, - "list::erase(iterator, iterator) called with an iterator not referring to this list"); - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__l)) == this, - "list::erase(iterator, iterator) called with an iterator not referring to this list"); if (__f != __l) { __node_allocator& __na = base::__node_alloc(); @@ -1748,27 +1641,12 @@ list<_Tp, _Alloc>::erase(const_iterator __f, const_iterator __l) __link_pointer __n = __f.__ptr_; ++__f; --base::__sz(); -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __p = __c->end_; __p != __c->beg_; ) - { - --__p; - iterator* __i = static_cast<iterator*>((*__p)->__i_); - if (__i->__ptr_ == __n) - { - (*__p)->__c_ = nullptr; - if (--__c->end_ != __p) - _VSTD::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#endif __node_pointer __np = __n->__as_node(); __node_alloc_traits::destroy(__na, _VSTD::addressof(__np->__value_)); __node_alloc_traits::deallocate(__na, __np, 1); } } - return iterator(__l.__ptr_, this); + return iterator(__l.__ptr_); } template <class _Tp, class _Alloc> @@ -1785,12 +1663,12 @@ list<_Tp, _Alloc>::resize(size_type __n) __hold_pointer __hold = __allocate_node(__na); __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_)); ++__ds; - iterator __r = iterator(__hold.release()->__as_link(), this); + iterator __r = iterator(__hold.release()->__as_link()); iterator __e = __r; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (--__n; __n != 0; --__n, (void) ++__e, ++__ds) { __hold.reset(__node_alloc_traits::allocate(__na, 1)); @@ -1799,7 +1677,7 @@ list<_Tp, _Alloc>::resize(size_type __n) __hold->__prev_ = __e.__ptr_; __hold.release(); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1810,11 +1688,11 @@ list<_Tp, _Alloc>::resize(size_type __n) __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1); if (__prev == 0) break; - __e = iterator(__prev, this); + __e = iterator(__prev); } throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __link_nodes_at_back(__r.__ptr_, __e.__ptr_); base::__sz() += __ds; } @@ -1835,12 +1713,12 @@ list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x) __node_alloc_traits::construct(__na, _VSTD::addressof(__hold->__value_), __x); ++__ds; __link_pointer __nl = __hold.release()->__as_link(); - iterator __r = iterator(__nl, this); + iterator __r = iterator(__nl); iterator __e = __r; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (--__n; __n != 0; --__n, (void) ++__e, ++__ds) { __hold.reset(__node_alloc_traits::allocate(__na, 1)); @@ -1849,7 +1727,7 @@ list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x) __hold->__prev_ = __e.__ptr_; __hold.release(); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -1860,11 +1738,11 @@ list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x) __node_alloc_traits::deallocate(__na, __e.__ptr_->__as_node(), 1); if (__prev == 0) break; - __e = iterator(__prev, this); + __e = iterator(__prev); } throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS __link_nodes(base::__end_as_link(), __r.__ptr_, __e.__ptr_); base::__sz() += __ds; } @@ -1874,10 +1752,8 @@ template <class _Tp, class _Alloc> void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c) { - _LIBCPP_ASSERT(this != _VSTD::addressof(__c), - "list::splice(iterator, list) called with this == &list"); - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "list::splice(iterator, list) called with an iterator not referring to this list"); + _LIBCPP_ASSERT_VALID_INPUT_RANGE(this != _VSTD::addressof(__c), + "list::splice(iterator, list) called with this == &list"); if (!__c.empty()) { __link_pointer __f = __c.__end_.__next_; @@ -1886,26 +1762,6 @@ list<_Tp, _Alloc>::splice(const_iterator __p, list& __c) __link_nodes(__p.__ptr_, __f, __l); base::__sz() += __c.__sz(); __c.__sz() = 0; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (_VSTD::addressof(__c) != this) { - __libcpp_db* __db = __get_db(); - __c_node* __cn1 = __db->__find_c_and_lock(this); - __c_node* __cn2 = __db->__find_c(_VSTD::addressof(__c)); - for (__i_node** __ip = __cn2->end_; __ip != __cn2->beg_;) - { - --__ip; - iterator* __i = static_cast<iterator*>((*__ip)->__i_); - if (__i->__ptr_ != __c.__end_as_link()) - { - __cn1->__add(*__ip); - (*__ip)->__c_ = __cn1; - if (--__cn2->end_ != __ip) - _VSTD::memmove(__ip, __ip+1, (__cn2->end_ - __ip)*sizeof(__i_node*)); - } - } - __db->unlock(); - } -#endif } } @@ -1913,13 +1769,6 @@ template <class _Tp, class _Alloc> void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __i) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "list::splice(iterator, list, iterator) called with the first iterator not referring to this list"); - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__i)) == _VSTD::addressof(__c), - "list::splice(iterator, list, iterator) called with the second iterator not referring to the list argument"); - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(_VSTD::addressof(__i)), - "list::splice(iterator, list, iterator) called with the second iterator not dereferenceable"); - if (__p.__ptr_ != __i.__ptr_ && __p.__ptr_ != __i.__ptr_->__next_) { __link_pointer __f = __i.__ptr_; @@ -1927,26 +1776,6 @@ list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __i) __link_nodes(__p.__ptr_, __f, __f); --__c.__sz(); ++base::__sz(); -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (_VSTD::addressof(__c) != this) { - __libcpp_db* __db = __get_db(); - __c_node* __cn1 = __db->__find_c_and_lock(this); - __c_node* __cn2 = __db->__find_c(_VSTD::addressof(__c)); - for (__i_node** __ip = __cn2->end_; __ip != __cn2->beg_;) - { - --__ip; - iterator* __j = static_cast<iterator*>((*__ip)->__i_); - if (__j->__ptr_ == __f) - { - __cn1->__add(*__ip); - (*__ip)->__c_ = __cn1; - if (--__cn2->end_ != __ip) - _VSTD::memmove(__ip, __ip+1, (__cn2->end_ - __ip)*sizeof(__i_node*)); - } - } - __db->unlock(); - } -#endif } } @@ -1965,16 +1794,6 @@ template <class _Tp, class _Alloc> void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __f, const_iterator __l) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "list::splice(iterator, list, iterator, iterator) called with first iterator not referring to this list"); - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__f)) == _VSTD::addressof(__c), - "list::splice(iterator, list, iterator, iterator) called with second iterator not referring to the list argument"); - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__l)) == _VSTD::addressof(__c), - "list::splice(iterator, list, iterator, iterator) called with third iterator not referring to the list argument"); - _LIBCPP_DEBUG_ASSERT(this != std::addressof(__c) || !std::__iterator_in_range(__f, __l, __p), - "list::splice(iterator, list, iterator, iterator)" - " called with the first iterator within the range of the second and third iterators"); - if (__f != __l) { __link_pointer __first = __f.__ptr_; @@ -1988,30 +1807,6 @@ list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __f, con } base::__unlink_nodes(__first, __last); __link_nodes(__p.__ptr_, __first, __last); -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (_VSTD::addressof(__c) != this) { - __libcpp_db* __db = __get_db(); - __c_node* __cn1 = __db->__find_c_and_lock(this); - __c_node* __cn2 = __db->__find_c(_VSTD::addressof(__c)); - for (__i_node** __ip = __cn2->end_; __ip != __cn2->beg_;) - { - --__ip; - iterator* __j = static_cast<iterator*>((*__ip)->__i_); - for (__link_pointer __k = __f.__ptr_; - __k != __l.__ptr_; __k = __k->__next_) - { - if (__j->__ptr_ == __k) - { - __cn1->__add(*__ip); - (*__ip)->__c_ = __cn1; - if (--__cn2->end_ != __ip) - _VSTD::memmove(__ip, __ip+1, (__cn2->end_ - __ip)*sizeof(__i_node*)); - } - } - } - __db->unlock(); - } -#endif } } @@ -2089,7 +1884,7 @@ inline void list<_Tp, _Alloc>::merge(list& __c) { - merge(__c, __less<value_type>()); + merge(__c, __less<>()); } template <class _Tp, class _Alloc> @@ -2125,24 +1920,6 @@ list<_Tp, _Alloc>::merge(list& __c, _Comp __comp) ++__f1; } splice(__e1, __c); -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __libcpp_db* __db = __get_db(); - __c_node* __cn1 = __db->__find_c_and_lock(this); - __c_node* __cn2 = __db->__find_c(_VSTD::addressof(__c)); - for (__i_node** __p = __cn2->end_; __p != __cn2->beg_;) - { - --__p; - iterator* __i = static_cast<iterator*>((*__p)->__i_); - if (__i->__ptr_ != __c.__end_as_link()) - { - __cn1->__add(*__p); - (*__p)->__c_ = __cn1; - if (--__cn2->end_ != __p) - _VSTD::memmove(__p, __p+1, (__cn2->end_ - __p)*sizeof(__i_node*)); - } - } - __db->unlock(); -#endif } } @@ -2151,7 +1928,7 @@ inline void list<_Tp, _Alloc>::sort() { - sort(__less<value_type>()); + sort(__less<>()); } template <class _Tp, class _Alloc> @@ -2249,38 +2026,6 @@ list<_Tp, _Alloc>::__invariants() const return size() == _VSTD::distance(begin(), end()); } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - -template <class _Tp, class _Alloc> -bool -list<_Tp, _Alloc>::__dereferenceable(const const_iterator* __i) const -{ - return __i->__ptr_ != this->__end_as_link(); -} - -template <class _Tp, class _Alloc> -bool -list<_Tp, _Alloc>::__decrementable(const const_iterator* __i) const -{ - return !empty() && __i->__ptr_ != base::__end_.__next_; -} - -template <class _Tp, class _Alloc> -bool -list<_Tp, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const -{ - return false; -} - -template <class _Tp, class _Alloc> -bool -list<_Tp, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const -{ - return false; -} - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - template <class _Tp, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY bool @@ -2289,6 +2034,8 @@ operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) return __x.size() == __y.size() && _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template <class _Tp, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY bool @@ -2329,6 +2076,17 @@ operator<=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) return !(__y < __x); } +#else // _LIBCPP_STD_VER <= 17 + +template <class _Tp, class _Allocator> +_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Tp> +operator<=>(const list<_Tp, _Allocator>& __x, const list<_Tp, _Allocator>& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>); +} + +#endif // _LIBCPP_STD_VER <= 17 + template <class _Tp, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY void @@ -2338,7 +2096,7 @@ swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Allocator, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY typename list<_Tp, _Allocator>::size_type erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred) { @@ -2358,15 +2116,15 @@ template <> inline constexpr bool __format::__enable_insertable<std::list<wchar_t>> = true; #endif -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template <class _ValueT> -using list = std::list<_ValueT, polymorphic_allocator<_ValueT>>; +using list _LIBCPP_AVAILABILITY_PMR = std::list<_ValueT, polymorphic_allocator<_ValueT>>; } // namespace pmr _LIBCPP_END_NAMESPACE_STD #endif @@ -2377,9 +2135,11 @@ _LIBCPP_POP_MACROS # include <algorithm> # include <atomic> # include <concepts> +# include <cstdlib> # include <functional> # include <iosfwd> # include <iterator> +# include <type_traits> # include <typeinfo> #endif diff --git a/libcxx/include/locale b/libcxx/include/locale index 874866f69822..e8ce28234402 100644 --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -53,7 +53,7 @@ public: // locale operations: basic_string<char> name() const; bool operator==(const locale& other) const; - bool operator!=(const locale& other) const; + bool operator!=(const locale& other) const; // removed C++20 template <class charT, class Traits, class Allocator> bool operator()(const basic_string<charT,Traits,Allocator>& s1, const basic_string<charT,Traits,Allocator>& s2) const; @@ -195,13 +195,14 @@ template <class charT> class messages_byname; #include <__algorithm/unwrap_iter.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include <__debug> #include <__iterator/access.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/istreambuf_iterator.h> #include <__iterator/ostreambuf_iterator.h> #include <__locale> #include <__memory/unique_ptr.h> +#include <__type_traits/make_unsigned.h> +#include <cerrno> #include <cstdio> #include <cstdlib> #include <ctime> @@ -223,9 +224,9 @@ template <class charT> class messages_byname; #endif #ifdef _LIBCPP_LOCALE__L_EXTENSIONS -#include <__bsd_locale_defaults.h> +# include <__locale_dir/locale_base_api/bsd_locale_defaults.h> #else -#include <__bsd_locale_fallbacks.h> +# include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h> #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -245,7 +246,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #else # define _LIBCPP_GET_C_LOCALE __cloc() // Get the C locale object - _LIBCPP_FUNC_VIS locale_t __cloc(); + _LIBCPP_EXPORTED_FROM_ABI locale_t __cloc(); #define __cloc_defined #endif @@ -377,7 +378,7 @@ __scan_keyword(_InputIterator& __b, _InputIterator __e, return __kb; } -struct _LIBCPP_TYPE_VIS __num_get_base +struct _LIBCPP_EXPORTED_FROM_ABI __num_get_base { static const int __num_get_buf_sz = 40; @@ -385,8 +386,7 @@ struct _LIBCPP_TYPE_VIS __num_get_base static const char __src[33]; }; -_LIBCPP_FUNC_VIS -void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, +_LIBCPP_EXPORTED_FROM_ABI void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, ios_base::iostate& __err); template <class _CharT> @@ -1126,7 +1126,7 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<char>; extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<wchar_t>; #endif -struct _LIBCPP_TYPE_VIS __num_put_base +struct _LIBCPP_EXPORTED_FROM_ABI __num_put_base { protected: static void __format_int(char* __fmt, const char* __len, bool __signd, @@ -1464,12 +1464,7 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, return do_put(__s, __iob, __fl, (unsigned long)__v); const numpunct<char_type>& __np = std::use_facet<numpunct<char_type> >(__iob.getloc()); typedef typename numpunct<char_type>::string_type string_type; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - string_type __tmp(__v ? __np.truename() : __np.falsename()); - string_type __nm = _VSTD::move(__tmp); -#else string_type __nm = __v ? __np.truename() : __np.falsename(); -#endif for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s) *__s = *__i; return __s; @@ -1681,7 +1676,7 @@ __get_up_to_n_digits(_InputIterator& __b, _InputIterator __e, return __r; } -class _LIBCPP_TYPE_VIS time_base +class _LIBCPP_EXPORTED_FROM_ABI time_base { public: enum dateorder {no_order, dmy, mdy, ymd, ydm}; @@ -1705,22 +1700,22 @@ protected: ~__time_get_c_storage() {} }; -template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__weeks() const; -template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__months() const; -template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__am_pm() const; -template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__c() const; -template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__r() const; -template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__x() const; -template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__X() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__weeks() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__months() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage<char>::__am_pm() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__c() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__r() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__x() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage<char>::__X() const; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__weeks() const; -template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__months() const; -template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__am_pm() const; -template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__c() const; -template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__r() const; -template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__x() const; -template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__X() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__weeks() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__months() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage<wchar_t>::__am_pm() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__c() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__r() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__x() const; +template <> _LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage<wchar_t>::__X() const; #endif template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> > @@ -2337,7 +2332,7 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<char>; extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>; #endif -class _LIBCPP_TYPE_VIS __time_get +class _LIBCPP_EXPORTED_FROM_ABI __time_get { protected: locale_t __loc_; @@ -2375,16 +2370,16 @@ private: }; #define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \ -template <> _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \ -template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \ -template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \ -template <> _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ -template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \ -extern template _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \ -extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \ -extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \ -extern template _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ -extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \ +template <> _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \ +template <> _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \ +template <> _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \ +template <> _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ +template <> _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \ +extern template _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \ +extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \ +extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \ +extern template _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ +extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \ /**/ _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char) @@ -2432,7 +2427,7 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>; extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>; #endif -class _LIBCPP_TYPE_VIS __time_put +class _LIBCPP_EXPORTED_FROM_ABI __time_put { locale_t __loc_; protected: @@ -2572,7 +2567,7 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<wchar_t>; // money_base -class _LIBCPP_TYPE_VIS money_base +class _LIBCPP_EXPORTED_FROM_ABI money_base { public: enum part {none, space, symbol, sign, value}; @@ -2686,14 +2681,14 @@ private: void init(const char*); }; -template<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, false>::init(const char*); -template<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, true>::init(const char*); +template<> _LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, false>::init(const char*); +template<> _LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, true>::init(const char*); extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>; extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, false>::init(const char*); -template<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, true>::init(const char*); +template<> _LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, false>::init(const char*); +template<> _LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, true>::init(const char*); extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>; extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>; #endif @@ -2810,7 +2805,7 @@ template <class _CharT, class _InputIterator> locale::id money_get<_CharT, _InputIterator>::id; -_LIBCPP_FUNC_VIS void __do_nothing(void*); +_LIBCPP_EXPORTED_FROM_ABI void __do_nothing(void*); template <class _Tp> _LIBCPP_HIDE_FROM_ABI @@ -3457,7 +3452,7 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>; // messages -class _LIBCPP_TYPE_VIS messages_base +class _LIBCPP_EXPORTED_FROM_ABI messages_base { public: typedef ptrdiff_t catalog; @@ -3598,15 +3593,15 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<wchar_t>; #endif template<class _Codecvt, class _Elem = wchar_t, - class _Wide_alloc = allocator<_Elem>, - class _Byte_alloc = allocator<char> > + class _WideAlloc = allocator<_Elem>, + class _ByteAlloc = allocator<char> > class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX17 wstring_convert { public: - typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string; - typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string; - typedef typename _Codecvt::state_type state_type; - typedef typename wide_string::traits_type::int_type int_type; + typedef basic_string<char, char_traits<char>, _ByteAlloc> byte_string; + typedef basic_string<_Elem, char_traits<_Elem>, _WideAlloc> wide_string; + typedef typename _Codecvt::state_type state_type; + typedef typename wide_string::traits_type::int_type int_type; private: byte_string __byte_err_string_; @@ -3625,19 +3620,19 @@ public: explicit wstring_convert(_Codecvt* __pcvt); #else _LIBCPP_INLINE_VISIBILITY - _LIBCPP_EXPLICIT_AFTER_CXX11 + _LIBCPP_EXPLICIT_SINCE_CXX14 wstring_convert(_Codecvt* __pcvt = new _Codecvt); #endif _LIBCPP_INLINE_VISIBILITY wstring_convert(_Codecvt* __pcvt, state_type __state); - _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err, + _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err = wide_string()); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY wstring_convert(wstring_convert&& __wc); #endif - ~wstring_convert(); + _LIBCPP_HIDE_FROM_ABI ~wstring_convert(); _LIBCPP_INLINE_VISIBILITY wide_string from_bytes(char __byte) @@ -3648,7 +3643,7 @@ public: _LIBCPP_INLINE_VISIBILITY wide_string from_bytes(const byte_string& __str) {return from_bytes(__str.data(), __str.data() + __str.size());} - wide_string from_bytes(const char* __first, const char* __last); + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __first, const char* __last); _LIBCPP_INLINE_VISIBILITY byte_string to_bytes(_Elem __wchar) @@ -3659,7 +3654,7 @@ public: _LIBCPP_INLINE_VISIBILITY byte_string to_bytes(const wide_string& __wstr) {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());} - byte_string to_bytes(const _Elem* __first, const _Elem* __last); + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __first, const _Elem* __last); _LIBCPP_INLINE_VISIBILITY size_t converted() const _NOEXCEPT {return __cvtcount_;} @@ -3668,25 +3663,25 @@ public: }; _LIBCPP_SUPPRESS_DEPRECATED_PUSH -template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> +template<class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc> inline -wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>:: wstring_convert(_Codecvt* __pcvt) : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0) { } _LIBCPP_SUPPRESS_DEPRECATED_POP -template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> +template<class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc> inline -wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>:: wstring_convert(_Codecvt* __pcvt, state_type __state) : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0) { } -template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> -wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: +template<class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc> +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>:: wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err) : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err), __cvtstate_(), __cvtcount_(0) @@ -3696,9 +3691,9 @@ wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: #ifndef _LIBCPP_CXX03_LANG -template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> +template<class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc> inline -wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>:: wstring_convert(wstring_convert&& __wc) : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)), __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)), @@ -3711,15 +3706,15 @@ wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: #endif // _LIBCPP_CXX03_LANG _LIBCPP_SUPPRESS_DEPRECATED_PUSH -template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> -wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert() +template<class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc> +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::~wstring_convert() { delete __cvtptr_; } -template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> -typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string -wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: +template<class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc> +typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wide_string +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>:: from_bytes(const char* __frm, const char* __frm_end) { _LIBCPP_SUPPRESS_DEPRECATED_POP @@ -3779,9 +3774,9 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP return __wide_err_string_; } -template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc> -typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string -wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>:: +template<class _Codecvt, class _Elem, class _WideAlloc, class _ByteAlloc> +typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::byte_string +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>:: to_bytes(const _Elem* __frm, const _Elem* __frm_end) { __cvtcount_ = 0; @@ -3902,18 +3897,18 @@ private: public: #ifndef _LIBCPP_CXX03_LANG - wbuffer_convert() : wbuffer_convert(nullptr) {} - explicit wbuffer_convert(streambuf* __bytebuf, + _LIBCPP_HIDE_FROM_ABI wbuffer_convert() : wbuffer_convert(nullptr) {} + explicit _LIBCPP_HIDE_FROM_ABI wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); #else - _LIBCPP_EXPLICIT_AFTER_CXX11 + _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI wbuffer_convert(streambuf* __bytebuf = nullptr, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); #endif - ~wbuffer_convert(); + _LIBCPP_HIDE_FROM_ABI ~wbuffer_convert(); _LIBCPP_INLINE_VISIBILITY streambuf* rdbuf() const {return __bufptr_;} @@ -3929,21 +3924,21 @@ public: state_type state() const {return __st_;} protected: - virtual int_type underflow(); - virtual int_type pbackfail(int_type __c = traits_type::eof()); - virtual int_type overflow (int_type __c = traits_type::eof()); - virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s, + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type underflow(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type pbackfail(int_type __c = traits_type::eof()); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type overflow (int_type __c = traits_type::eof()); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s, streamsize __n); - virtual pos_type seekoff(off_type __off, ios_base::seekdir __way, + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __wch = ios_base::in | ios_base::out); - virtual pos_type seekpos(pos_type __sp, + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type seekpos(pos_type __sp, ios_base::openmode __wch = ios_base::in | ios_base::out); - virtual int sync(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int sync(); private: - bool __read_mode(); - void __write_mode(); - wbuffer_convert* __close(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL bool __read_mode(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __write_mode(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL wbuffer_convert* __close(); }; _LIBCPP_SUPPRESS_DEPRECATED_PUSH @@ -4009,8 +4004,8 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP else { if (__extbufend_ != __extbufnext_) { - _LIBCPP_ASSERT(__extbufnext_ != nullptr, "underflow moving from nullptr"); - _LIBCPP_ASSERT(__extbuf_ != nullptr, "underflow moving into nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__extbufnext_ != nullptr, "underflow moving from nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__extbuf_ != nullptr, "underflow moving into nullptr"); _VSTD::memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_); } __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_); diff --git a/libcxx/include/map b/libcxx/include/map index 9cf47b245a02..4152d58a2f88 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -70,6 +70,8 @@ public: template <class InputIterator> map(InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& a); + template<container-compatible-range<value_type> R> + map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); // C++23 map(const map& m); map(map&& m) noexcept( @@ -83,6 +85,9 @@ public: template <class InputIterator> map(InputIterator first, InputIterator last, const allocator_type& a) : map(first, last, Compare(), a) {} // C++14 + template<container-compatible-range<value_type> R> + map(from_range_t, R&& rg, const Allocator& a)) + : map(from_range, std::forward<R>(rg), Compare(), a) { } // C++23 map(initializer_list<value_type> il, const allocator_type& a) : map(il, Compare(), a) {} // C++14 ~map(); @@ -138,6 +143,8 @@ public: iterator insert(const_iterator position, P&& p); template <class InputIterator> void insert(InputIterator first, InputIterator last); + template<container-compatible-range<value_type> R> + void insert_range(R&& rg); // C++23 void insert(initializer_list<value_type> il); node_type extract(const_iterator position); // C++17 @@ -229,6 +236,11 @@ template <class InputIterator, map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>; // C++17 +template<ranges::input_range R, class Compare = less<range-key-type<R>, + class Allocator = allocator<range-to-alloc-type<R>>> + map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> map<range-key-type<R>, range-mapped-type<R>, Compare, Allocator>; // C++23 + template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> map(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator()) @@ -239,6 +251,10 @@ map(InputIterator, InputIterator, Allocator) -> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, less<iter_key_t<InputIterator>>, Allocator>; // C++17 +template<ranges::input_range R, class Allocator> + map(from_range_t, R&&, Allocator) + -> map<range-key-type<R>, range-mapped-type<R>, less<range-key-type<R>>, Allocator>; // C++23 + template<class Key, class T, class Allocator> map(initializer_list<pair<const Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>; // C++17 @@ -250,27 +266,32 @@ operator==(const map<Key, T, Compare, Allocator>& x, template <class Key, class T, class Compare, class Allocator> bool operator< (const map<Key, T, Compare, Allocator>& x, - const map<Key, T, Compare, Allocator>& y); + const map<Key, T, Compare, Allocator>& y); // removed in C++20 template <class Key, class T, class Compare, class Allocator> bool operator!=(const map<Key, T, Compare, Allocator>& x, - const map<Key, T, Compare, Allocator>& y); + const map<Key, T, Compare, Allocator>& y); // removed in C++20 template <class Key, class T, class Compare, class Allocator> bool operator> (const map<Key, T, Compare, Allocator>& x, - const map<Key, T, Compare, Allocator>& y); + const map<Key, T, Compare, Allocator>& y); // removed in C++20 template <class Key, class T, class Compare, class Allocator> bool operator>=(const map<Key, T, Compare, Allocator>& x, - const map<Key, T, Compare, Allocator>& y); + const map<Key, T, Compare, Allocator>& y); // removed in C++20 template <class Key, class T, class Compare, class Allocator> bool operator<=(const map<Key, T, Compare, Allocator>& x, - const map<Key, T, Compare, Allocator>& y); + const map<Key, T, Compare, Allocator>& y); // removed in C++20 + +template<class Key, class T, class Compare, class Allocator> + synth-three-way-result<pair<const Key, T>> + operator<=>(const map<Key, T, Compare, Allocator>& x, + const map<Key, T, Compare, Allocator>& y); // since C++20 // specialized algorithms: template <class Key, class T, class Compare, class Allocator> @@ -333,6 +354,9 @@ public: template <class InputIterator> multimap(InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& a); + template<container-compatible-range<value_type> R> + multimap(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); // C++23 multimap(const multimap& m); multimap(multimap&& m) noexcept( @@ -347,6 +371,9 @@ public: template <class InputIterator> multimap(InputIterator first, InputIterator last, const allocator_type& a) : multimap(first, last, Compare(), a) {} // C++14 + template<container-compatible-range<value_type> R> + multimap(from_range_t, R&& rg, const Allocator& a)) + : multimap(from_range, std::forward<R>(rg), Compare(), a) { } // C++23 multimap(initializer_list<value_type> il, const allocator_type& a) : multimap(il, Compare(), a) {} // C++14 ~multimap(); @@ -395,6 +422,8 @@ public: iterator insert(const_iterator position, P&& p); template <class InputIterator> void insert(InputIterator first, InputIterator last); + template<container-compatible-range<value_type> R> + void insert_range(R&& rg); // C++23 void insert(initializer_list<value_type> il); node_type extract(const_iterator position); // C++17 @@ -469,6 +498,11 @@ template <class InputIterator, multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>; // C++17 +template<ranges::input_range R, class Compare = less<range-key-type<R>>, + class Allocator = allocator<range-to-alloc-type<R>>> + multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> multimap<range-key-type<R>, range-mapped-type<R>, Compare, Allocator>; // C++23 + template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> multimap(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator()) @@ -479,6 +513,10 @@ multimap(InputIterator, InputIterator, Allocator) -> multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, less<iter_key_t<InputIterator>>, Allocator>; // C++17 +template<ranges::input_range R, class Allocator> + multimap(from_range_t, R&&, Allocator) + -> multimap<range-key-type<R>, range-mapped-type<R>, less<range-key-type<R>>, Allocator>; // C++23 + template<class Key, class T, class Allocator> multimap(initializer_list<pair<const Key, T>>, Allocator) -> multimap<Key, T, less<Key>, Allocator>; // C++17 @@ -491,27 +529,32 @@ operator==(const multimap<Key, T, Compare, Allocator>& x, template <class Key, class T, class Compare, class Allocator> bool operator< (const multimap<Key, T, Compare, Allocator>& x, - const multimap<Key, T, Compare, Allocator>& y); + const multimap<Key, T, Compare, Allocator>& y); // removed in C++20 template <class Key, class T, class Compare, class Allocator> bool operator!=(const multimap<Key, T, Compare, Allocator>& x, - const multimap<Key, T, Compare, Allocator>& y); + const multimap<Key, T, Compare, Allocator>& y); // removed in C++20 template <class Key, class T, class Compare, class Allocator> bool operator> (const multimap<Key, T, Compare, Allocator>& x, - const multimap<Key, T, Compare, Allocator>& y); + const multimap<Key, T, Compare, Allocator>& y); // removed in C++20 template <class Key, class T, class Compare, class Allocator> bool operator>=(const multimap<Key, T, Compare, Allocator>& x, - const multimap<Key, T, Compare, Allocator>& y); + const multimap<Key, T, Compare, Allocator>& y); // removed in C++20 template <class Key, class T, class Compare, class Allocator> bool operator<=(const multimap<Key, T, Compare, Allocator>& x, - const multimap<Key, T, Compare, Allocator>& y); + const multimap<Key, T, Compare, Allocator>& y); // removed in C++20 + +template<class Key, class T, class Compare, class Allocator> + synth-three-way-result<pair<const Key, T>> + operator<=>(const multimap<Key, T, Compare, Allocator>& x, + const multimap<Key, T, Compare, Allocator>& y); // since c++20 // specialized algorithms: template <class Key, class T, class Compare, class Allocator> @@ -530,24 +573,30 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20 #include <__algorithm/equal.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> #include <__config> #include <__functional/binary_function.h> #include <__functional/is_transparent.h> #include <__functional/operations.h> #include <__iterator/erase_if_container.h> #include <__iterator/iterator_traits.h> +#include <__iterator/ranges_iterator_traits.h> #include <__iterator/reverse_iterator.h> +#include <__memory/addressof.h> #include <__memory/allocator.h> #include <__memory_resource/polymorphic_allocator.h> #include <__node_handle> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> #include <__tree> #include <__type_traits/is_allocator.h> #include <__utility/forward.h> #include <__utility/piecewise_construct.h> #include <__utility/swap.h> #include <tuple> -#include <type_traits> #include <version> // standard-mandated includes @@ -594,14 +643,14 @@ public: _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _CP& __y) const {return static_cast<const _Compare&>(*this)(__x, __y.__get_value().first);} - void swap(__map_value_compare& __y) + _LIBCPP_HIDE_FROM_ABI void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable<_Compare>::value) { using _VSTD::swap; swap(static_cast<_Compare&>(*this), static_cast<_Compare&>(__y)); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY bool operator()(const _K2& __x, const _CP& __y) const @@ -647,7 +696,7 @@ public: swap(__comp_, __y.__comp_); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY bool operator()(const _K2& __x, const _CP& __y) const @@ -742,7 +791,7 @@ public: _LIBCPP_INLINE_VISIBILITY value_type& __get_value() { -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return *_VSTD::launder(_VSTD::addressof(__cc_)); #else return __cc_; @@ -752,7 +801,7 @@ public: _LIBCPP_INLINE_VISIBILITY const value_type& __get_value() const { -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return *_VSTD::launder(_VSTD::addressof(__cc_)); #else return __cc_; @@ -1020,7 +1069,7 @@ public: typedef _VSTD::reverse_iterator<iterator> reverse_iterator; typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef __map_node_handle<typename __base::__node, allocator_type> node_type; typedef __insert_return_type<iterator, node_type> insert_return_type; #endif @@ -1067,13 +1116,30 @@ public: insert(__f, __l); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + map(from_range_t, _Range&& __range, const key_compare& __comp = key_compare(), + const allocator_type& __a = allocator_type()) + : __tree_(__vc(__comp), typename __base::allocator_type(__a)) { + insert_range(std::forward<_Range>(__range)); + } +#endif + +#if _LIBCPP_STD_VER >= 14 template <class _InputIterator> _LIBCPP_INLINE_VISIBILITY map(_InputIterator __f, _InputIterator __l, const allocator_type& __a) : map(__f, __l, key_compare(), __a) {} #endif +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + map(from_range_t, _Range&& __range, const allocator_type& __a) + : map(from_range, std::forward<_Range>(__range), key_compare(), __a) {} +#endif + _LIBCPP_INLINE_VISIBILITY map(const map& __m) : __tree_(__m.__tree_) @@ -1106,7 +1172,7 @@ public: { } - map(map&& __m, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI map(map&& __m, const allocator_type& __a); _LIBCPP_INLINE_VISIBILITY map& operator=(map&& __m) @@ -1130,7 +1196,7 @@ public: insert(__il.begin(), __il.end()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _LIBCPP_INLINE_VISIBILITY map(initializer_list<value_type> __il, const allocator_type& __a) : map(__il, key_compare(), __a) {} @@ -1200,13 +1266,13 @@ public: _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT {return __tree_.max_size();} - mapped_type& operator[](const key_type& __k); + _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __k); #ifndef _LIBCPP_CXX03_LANG - mapped_type& operator[](key_type&& __k); + _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __k); #endif - mapped_type& at(const key_type& __k); - const mapped_type& at(const key_type& __k) const; + _LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __k); + _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __k) const; _LIBCPP_INLINE_VISIBILITY allocator_type get_allocator() const _NOEXCEPT {return allocator_type(__tree_.__alloc());} @@ -1273,7 +1339,18 @@ public: insert(__e.__i_, *__f); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + void insert_range(_Range&& __range) { + const_iterator __end = cend(); + for (auto&& __element : __range) { + insert(__end.__i_, std::forward<decltype(__element)>(__element)); + } + } +#endif + +#if _LIBCPP_STD_VER >= 17 template <class... _Args> _LIBCPP_INLINE_VISIBILITY @@ -1367,7 +1444,7 @@ public: return __r; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __p) {return __tree_.erase(__p.__i_);} @@ -1382,11 +1459,11 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__tree_.clear();} -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY insert_return_type insert(node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to map::insert()"); return __tree_.template __node_handle_insert_unique< node_type, insert_return_type>(_VSTD::move(__nh)); @@ -1394,7 +1471,7 @@ public: _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __hint, node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to map::insert()"); return __tree_.template __node_handle_insert_unique<node_type>( __hint.__i_, _VSTD::move(__nh)); @@ -1413,32 +1490,32 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(map<key_type, mapped_type, _Compare2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); } template <class _Compare2> _LIBCPP_INLINE_VISIBILITY void merge(map<key_type, mapped_type, _Compare2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); } template <class _Compare2> _LIBCPP_INLINE_VISIBILITY void merge(multimap<key_type, mapped_type, _Compare2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); } template <class _Compare2> _LIBCPP_INLINE_VISIBILITY void merge(multimap<key_type, mapped_type, _Compare2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); } #endif @@ -1452,7 +1529,7 @@ public: iterator find(const key_type& __k) {return __tree_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __tree_.find(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, iterator> @@ -1466,21 +1543,21 @@ public: _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __tree_.__count_unique(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, size_type> count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, bool> contains(const _K2& __k) const { return find(__k) != end(); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) @@ -1488,7 +1565,7 @@ public: _LIBCPP_INLINE_VISIBILITY const_iterator lower_bound(const key_type& __k) const {return __tree_.lower_bound(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, iterator> @@ -1506,7 +1583,7 @@ public: _LIBCPP_INLINE_VISIBILITY const_iterator upper_bound(const key_type& __k) const {return __tree_.upper_bound(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, iterator> @@ -1523,7 +1600,7 @@ public: _LIBCPP_INLINE_VISIBILITY pair<const_iterator,const_iterator> equal_range(const key_type& __k) const {return __tree_.__equal_range_unique(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, pair<iterator,iterator>> @@ -1545,19 +1622,28 @@ private: typedef unique_ptr<__node, _Dp> __node_holder; #ifdef _LIBCPP_CXX03_LANG - __node_holder __construct_node_with_key(const key_type& __k); + _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_with_key(const key_type& __k); #endif }; #if _LIBCPP_STD_VER >= 17 template<class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>, class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value, void>, class = enable_if_t<!__is_allocator<_Compare>::value, void>, class = enable_if_t<__is_allocator<_Allocator>::value, void>> map(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) -> map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, class _Compare = less<__range_key_type<_Range>>, + class _Allocator = allocator<__range_to_alloc_type<_Range>>, + class = enable_if_t<!__is_allocator<_Compare>::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) + -> map<__range_key_type<_Range>, __range_mapped_type<_Range>, _Compare, _Allocator>; +#endif + template<class _Key, class _Tp, class _Compare = less<remove_const_t<_Key>>, class _Allocator = allocator<pair<const _Key, _Tp>>, class = enable_if_t<!__is_allocator<_Compare>::value, void>, @@ -1566,12 +1652,19 @@ map(initializer_list<pair<_Key, _Tp>>, _Compare = _Compare(), _Allocator = _Allo -> map<remove_const_t<_Key>, _Tp, _Compare, _Allocator>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value, void>, class = enable_if_t<__is_allocator<_Allocator>::value, void>> map(_InputIterator, _InputIterator, _Allocator) -> map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, less<__iter_key_type<_InputIterator>>, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +map(from_range_t, _Range&&, _Allocator) + -> map<__range_key_type<_Range>, __range_mapped_type<_Range>, less<__range_key_type<_Range>>, _Allocator>; +#endif + template<class _Key, class _Tp, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value, void>> map(initializer_list<pair<_Key, _Tp>>, _Allocator) @@ -1677,6 +1770,8 @@ operator==(const map<_Key, _Tp, _Compare, _Allocator>& __x, return __x.size() == __y.size() && _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template <class _Key, class _Tp, class _Compare, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY bool @@ -1722,6 +1817,21 @@ operator<=(const map<_Key, _Tp, _Compare, _Allocator>& __x, return !(__y < __x); } +#else // #if _LIBCPP_STD_VER <= 17 + +template <class _Key, class _Tp, class _Compare, class _Allocator> +_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<pair<const _Key, _Tp>> +operator<=>(const map<_Key, _Tp, _Compare, _Allocator>& __x, const map<_Key, _Tp, _Compare, _Allocator>& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), + __x.end(), + __y.begin(), + __y.end(), + std::__synth_three_way<pair<const _Key, _Tp>, pair<const _Key, _Tp>>); +} + +#endif // #if _LIBCPP_STD_VER <= 17 + template <class _Key, class _Tp, class _Compare, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY void @@ -1732,7 +1842,7 @@ swap(map<_Key, _Tp, _Compare, _Allocator>& __x, __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Key, class _Tp, class _Compare, class _Allocator, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY @@ -1800,7 +1910,7 @@ public: typedef _VSTD::reverse_iterator<iterator> reverse_iterator; typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef __map_node_handle<typename __base::__node, allocator_type> node_type; #endif @@ -1846,13 +1956,30 @@ public: insert(__f, __l); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + multimap(from_range_t, _Range&& __range, const key_compare& __comp = key_compare(), + const allocator_type& __a = allocator_type()) + : __tree_(__vc(__comp), typename __base::allocator_type(__a)) { + insert_range(std::forward<_Range>(__range)); + } +#endif + +#if _LIBCPP_STD_VER >= 14 template <class _InputIterator> _LIBCPP_INLINE_VISIBILITY multimap(_InputIterator __f, _InputIterator __l, const allocator_type& __a) : multimap(__f, __l, key_compare(), __a) {} #endif +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + multimap(from_range_t, _Range&& __range, const allocator_type& __a) + : multimap(from_range, std::forward<_Range>(__range), key_compare(), __a) {} +#endif + _LIBCPP_INLINE_VISIBILITY multimap(const multimap& __m) : __tree_(__m.__tree_.value_comp(), @@ -1886,7 +2013,7 @@ public: { } - multimap(multimap&& __m, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI multimap(multimap&& __m, const allocator_type& __a); _LIBCPP_INLINE_VISIBILITY multimap& operator=(multimap&& __m) @@ -1910,7 +2037,7 @@ public: insert(__il.begin(), __il.end()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _LIBCPP_INLINE_VISIBILITY multimap(initializer_list<value_type> __il, const allocator_type& __a) : multimap(__il, key_compare(), __a) {} @@ -2043,6 +2170,17 @@ public: __tree_.__insert_multi(__e.__i_, *__f); } +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + void insert_range(_Range&& __range) { + const_iterator __end = cend(); + for (auto&& __element : __range) { + __tree_.__insert_multi(__end.__i_, std::forward<decltype(__element)>(__element)); + } + } +#endif + _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __p) {return __tree_.erase(__p.__i_);} _LIBCPP_INLINE_VISIBILITY @@ -2053,11 +2191,11 @@ public: iterator erase(const_iterator __f, const_iterator __l) {return __tree_.erase(__f.__i_, __l.__i_);} -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY iterator insert(node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to multimap::insert()"); return __tree_.template __node_handle_insert_multi<node_type>( _VSTD::move(__nh)); @@ -2065,7 +2203,7 @@ public: _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __hint, node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to multimap::insert()"); return __tree_.template __node_handle_insert_multi<node_type>( __hint.__i_, _VSTD::move(__nh)); @@ -2085,32 +2223,32 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(multimap<key_type, mapped_type, _Compare2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __tree_.__node_handle_merge_multi(__source.__tree_); } template <class _Compare2> _LIBCPP_INLINE_VISIBILITY void merge(multimap<key_type, mapped_type, _Compare2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __tree_.__node_handle_merge_multi(__source.__tree_); } template <class _Compare2> _LIBCPP_INLINE_VISIBILITY void merge(map<key_type, mapped_type, _Compare2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __tree_.__node_handle_merge_multi(__source.__tree_); } template <class _Compare2> _LIBCPP_INLINE_VISIBILITY void merge(map<key_type, mapped_type, _Compare2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __tree_.__node_handle_merge_multi(__source.__tree_); } #endif @@ -2127,7 +2265,7 @@ public: iterator find(const key_type& __k) {return __tree_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __tree_.find(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, iterator> @@ -2141,21 +2279,21 @@ public: _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __tree_.__count_multi(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, size_type> count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, bool> contains(const _K2& __k) const { return find(__k) != end(); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) @@ -2163,7 +2301,7 @@ public: _LIBCPP_INLINE_VISIBILITY const_iterator lower_bound(const key_type& __k) const {return __tree_.lower_bound(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, iterator> @@ -2181,7 +2319,7 @@ public: _LIBCPP_INLINE_VISIBILITY const_iterator upper_bound(const key_type& __k) const {return __tree_.upper_bound(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, iterator> @@ -2198,7 +2336,7 @@ public: _LIBCPP_INLINE_VISIBILITY pair<const_iterator,const_iterator> equal_range(const key_type& __k) const {return __tree_.__equal_range_multi(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_transparent<_Compare, _K2>::value, pair<iterator,iterator>> @@ -2221,12 +2359,21 @@ private: #if _LIBCPP_STD_VER >= 17 template<class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>, class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value, void>, class = enable_if_t<!__is_allocator<_Compare>::value, void>, class = enable_if_t<__is_allocator<_Allocator>::value, void>> multimap(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) -> multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, class _Compare = less<__range_key_type<_Range>>, + class _Allocator = allocator<__range_to_alloc_type<_Range>>, + class = enable_if_t<!__is_allocator<_Compare>::value, void>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +multimap(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<__range_key_type<_Range>, __range_mapped_type<_Range>, _Compare, _Allocator>; +#endif + template<class _Key, class _Tp, class _Compare = less<remove_const_t<_Key>>, class _Allocator = allocator<pair<const _Key, _Tp>>, class = enable_if_t<!__is_allocator<_Compare>::value, void>, @@ -2235,12 +2382,19 @@ multimap(initializer_list<pair<_Key, _Tp>>, _Compare = _Compare(), _Allocator = -> multimap<remove_const_t<_Key>, _Tp, _Compare, _Allocator>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value, void>, class = enable_if_t<__is_allocator<_Allocator>::value, void>> multimap(_InputIterator, _InputIterator, _Allocator) -> multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, less<__iter_key_type<_InputIterator>>, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +multimap(from_range_t, _Range&&, _Allocator) + -> multimap<__range_key_type<_Range>, __range_mapped_type<_Range>, less<__range_key_type<_Range>>, _Allocator>; +#endif + template<class _Key, class _Tp, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value, void>> multimap(initializer_list<pair<_Key, _Tp>>, _Allocator) @@ -2271,6 +2425,8 @@ operator==(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, return __x.size() == __y.size() && _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template <class _Key, class _Tp, class _Compare, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY bool @@ -2316,6 +2472,22 @@ operator<=(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, return !(__y < __x); } +#else // #if _LIBCPP_STD_VER <= 17 + +template <class _Key, class _Tp, class _Compare, class _Allocator> +_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<pair<const _Key, _Tp>> +operator<=>(const multimap<_Key, _Tp, _Compare, _Allocator>& __x, + const multimap<_Key, _Tp, _Compare, _Allocator>& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), + __x.end(), + __y.begin(), + __y.end(), + std::__synth_three_way<pair<const _Key, _Tp>, pair<const _Key, _Tp>>); +} + +#endif // #if _LIBCPP_STD_VER <= 17 + template <class _Key, class _Tp, class _Compare, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY void @@ -2326,7 +2498,7 @@ swap(multimap<_Key, _Tp, _Compare, _Allocator>& __x, __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Key, class _Tp, class _Compare, class _Allocator, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY @@ -2339,22 +2511,24 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template <class _KeyT, class _ValueT, class _CompareT = std::less<_KeyT>> -using map = std::map<_KeyT, _ValueT, _CompareT, polymorphic_allocator<std::pair<const _KeyT, _ValueT>>>; +using map _LIBCPP_AVAILABILITY_PMR = std::map<_KeyT, _ValueT, _CompareT, polymorphic_allocator<std::pair<const _KeyT, _ValueT>>>; template <class _KeyT, class _ValueT, class _CompareT = std::less<_KeyT>> -using multimap = std::multimap<_KeyT, _ValueT, _CompareT, polymorphic_allocator<std::pair<const _KeyT, _ValueT>>>; +using multimap _LIBCPP_AVAILABILITY_PMR = std::multimap<_KeyT, _ValueT, _CompareT, polymorphic_allocator<std::pair<const _KeyT, _ValueT>>>; } // namespace pmr _LIBCPP_END_NAMESPACE_STD #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> +# include <cstdlib> # include <functional> # include <iterator> +# include <type_traits> # include <utility> #endif diff --git a/libcxx/include/math.h b/libcxx/include/math.h index a23d1ff3ed37..5820151c4135 100644 --- a/libcxx/include/math.h +++ b/libcxx/include/math.h @@ -554,7 +554,6 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 // acos -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float acos(float __x) _NOEXCEPT {return __builtin_acosf(__x);} template <class = int> @@ -563,7 +562,6 @@ _LIBCPP_HIDE_FROM_ABI double acos(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double acos(long double __x) _NOEXCEPT {return __builtin_acosl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -572,7 +570,6 @@ acos(_A1 __x) _NOEXCEPT {return __builtin_acos((double)__x);} // asin -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float asin(float __x) _NOEXCEPT {return __builtin_asinf(__x);} template <class = int> @@ -581,7 +578,6 @@ _LIBCPP_HIDE_FROM_ABI double asin(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double asin(long double __x) _NOEXCEPT {return __builtin_asinl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -590,7 +586,6 @@ asin(_A1 __x) _NOEXCEPT {return __builtin_asin((double)__x);} // atan -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float atan(float __x) _NOEXCEPT {return __builtin_atanf(__x);} template <class = int> @@ -599,7 +594,6 @@ _LIBCPP_HIDE_FROM_ABI double atan(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double atan(long double __x) _NOEXCEPT {return __builtin_atanl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -608,7 +602,6 @@ atan(_A1 __x) _NOEXCEPT {return __builtin_atan((double)__x);} // atan2 -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float atan2(float __y, float __x) _NOEXCEPT {return __builtin_atan2f(__y, __x);} template <class = int> @@ -617,7 +610,6 @@ _LIBCPP_HIDE_FROM_ABI double atan2(double __x, double __y) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double atan2(long double __y, long double __x) _NOEXCEPT {return __builtin_atan2l(__y, __x);} -# endif template <class _A1, class _A2> inline _LIBCPP_HIDE_FROM_ABI @@ -637,7 +629,6 @@ atan2(_A1 __y, _A2 __x) _NOEXCEPT // ceil -# if !defined(__sun__) _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float ceil(float __x) _NOEXCEPT {return __builtin_ceilf(__x);} template <class = int> @@ -646,7 +637,6 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double ceil(double __x) _NOEXCEPT { } _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double ceil(long double __x) _NOEXCEPT {return __builtin_ceill(__x);} -# endif template <class _A1> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI @@ -655,7 +645,6 @@ ceil(_A1 __x) _NOEXCEPT {return __builtin_ceil((double)__x);} // cos -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float cos(float __x) _NOEXCEPT {return __builtin_cosf(__x);} template <class = int> @@ -664,7 +653,6 @@ _LIBCPP_HIDE_FROM_ABI double cos(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double cos(long double __x) _NOEXCEPT {return __builtin_cosl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -673,7 +661,6 @@ cos(_A1 __x) _NOEXCEPT {return __builtin_cos((double)__x);} // cosh -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float cosh(float __x) _NOEXCEPT {return __builtin_coshf(__x);} template <class = int> @@ -682,7 +669,6 @@ _LIBCPP_HIDE_FROM_ABI double cosh(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double cosh(long double __x) _NOEXCEPT {return __builtin_coshl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -691,7 +677,6 @@ cosh(_A1 __x) _NOEXCEPT {return __builtin_cosh((double)__x);} // exp -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float exp(float __x) _NOEXCEPT {return __builtin_expf(__x);} template <class = int> @@ -700,7 +685,6 @@ _LIBCPP_HIDE_FROM_ABI double exp(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double exp(long double __x) _NOEXCEPT {return __builtin_expl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -709,7 +693,6 @@ exp(_A1 __x) _NOEXCEPT {return __builtin_exp((double)__x);} // fabs -# if !defined(__sun__) _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float fabs(float __x) _NOEXCEPT {return __builtin_fabsf(__x);} template <class = int> @@ -718,7 +701,6 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double fabs(double __x) _NOEXCEPT { } _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double fabs(long double __x) _NOEXCEPT {return __builtin_fabsl(__x);} -# endif template <class _A1> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI @@ -727,7 +709,6 @@ fabs(_A1 __x) _NOEXCEPT {return __builtin_fabs((double)__x);} // floor -# if !defined(__sun__) _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI float floor(float __x) _NOEXCEPT {return __builtin_floorf(__x);} template <class = int> @@ -736,7 +717,6 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI double floor(double __x) _NOEXCEPT { } _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double floor(long double __x) _NOEXCEPT {return __builtin_floorl(__x);} -# endif template <class _A1> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI @@ -745,7 +725,6 @@ floor(_A1 __x) _NOEXCEPT {return __builtin_floor((double)__x);} // fmod -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float fmod(float __x, float __y) _NOEXCEPT {return __builtin_fmodf(__x, __y);} template <class = int> @@ -754,7 +733,6 @@ _LIBCPP_HIDE_FROM_ABI double fmod(double __x, double __y) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double fmod(long double __x, long double __y) _NOEXCEPT {return __builtin_fmodl(__x, __y);} -# endif template <class _A1, class _A2> inline _LIBCPP_HIDE_FROM_ABI @@ -774,7 +752,6 @@ fmod(_A1 __x, _A2 __y) _NOEXCEPT // frexp -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float frexp(float __x, int* __e) _NOEXCEPT {return __builtin_frexpf(__x, __e);} template <class = int> @@ -783,7 +760,6 @@ _LIBCPP_HIDE_FROM_ABI double frexp(double __x, int* __e) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double frexp(long double __x, int* __e) _NOEXCEPT {return __builtin_frexpl(__x, __e);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -792,7 +768,6 @@ frexp(_A1 __x, int* __e) _NOEXCEPT {return __builtin_frexp((double)__x, __e);} // ldexp -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float ldexp(float __x, int __e) _NOEXCEPT {return __builtin_ldexpf(__x, __e);} template <class = int> @@ -801,7 +776,6 @@ _LIBCPP_HIDE_FROM_ABI double ldexp(double __x, int __e) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double ldexp(long double __x, int __e) _NOEXCEPT {return __builtin_ldexpl(__x, __e);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -810,7 +784,6 @@ ldexp(_A1 __x, int __e) _NOEXCEPT {return __builtin_ldexp((double)__x, __e);} // log -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float log(float __x) _NOEXCEPT {return __builtin_logf(__x);} template <class = int> @@ -819,7 +792,6 @@ _LIBCPP_HIDE_FROM_ABI double log(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double log(long double __x) _NOEXCEPT {return __builtin_logl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -828,7 +800,6 @@ log(_A1 __x) _NOEXCEPT {return __builtin_log((double)__x);} // log10 -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float log10(float __x) _NOEXCEPT {return __builtin_log10f(__x);} @@ -838,7 +809,6 @@ _LIBCPP_HIDE_FROM_ABI double log10(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double log10(long double __x) _NOEXCEPT {return __builtin_log10l(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -847,7 +817,6 @@ log10(_A1 __x) _NOEXCEPT {return __builtin_log10((double)__x);} // modf -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float modf(float __x, float* __y) _NOEXCEPT {return __builtin_modff(__x, __y);} template <class = int> @@ -856,11 +825,9 @@ _LIBCPP_HIDE_FROM_ABI double modf(double __x, double* __y) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double modf(long double __x, long double* __y) _NOEXCEPT {return __builtin_modfl(__x, __y);} -# endif // pow -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float pow(float __x, float __y) _NOEXCEPT {return __builtin_powf(__x, __y);} template <class = int> @@ -869,7 +836,6 @@ _LIBCPP_HIDE_FROM_ABI double pow(double __x, double __y) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double pow(long double __x, long double __y) _NOEXCEPT {return __builtin_powl(__x, __y);} -# endif template <class _A1, class _A2> inline _LIBCPP_HIDE_FROM_ABI @@ -889,7 +855,6 @@ pow(_A1 __x, _A2 __y) _NOEXCEPT // sin -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float sin(float __x) _NOEXCEPT {return __builtin_sinf(__x);} template <class = int> @@ -898,7 +863,6 @@ _LIBCPP_HIDE_FROM_ABI double sin(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double sin(long double __x) _NOEXCEPT {return __builtin_sinl(__x);} -#endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -907,7 +871,6 @@ sin(_A1 __x) _NOEXCEPT {return __builtin_sin((double)__x);} // sinh -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float sinh(float __x) _NOEXCEPT {return __builtin_sinhf(__x);} template <class = int> @@ -916,7 +879,6 @@ _LIBCPP_HIDE_FROM_ABI double sinh(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double sinh(long double __x) _NOEXCEPT {return __builtin_sinhl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -925,7 +887,6 @@ sinh(_A1 __x) _NOEXCEPT {return __builtin_sinh((double)__x);} // sqrt -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float sqrt(float __x) _NOEXCEPT {return __builtin_sqrtf(__x);} template <class = int> @@ -934,7 +895,6 @@ _LIBCPP_HIDE_FROM_ABI double sqrt(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double sqrt(long double __x) _NOEXCEPT {return __builtin_sqrtl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -943,7 +903,6 @@ sqrt(_A1 __x) _NOEXCEPT {return __builtin_sqrt((double)__x);} // tan -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float tan(float __x) _NOEXCEPT {return __builtin_tanf(__x);} template <class = int> @@ -952,7 +911,6 @@ _LIBCPP_HIDE_FROM_ABI double tan(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double tan(long double __x) _NOEXCEPT {return __builtin_tanl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI @@ -961,7 +919,6 @@ tan(_A1 __x) _NOEXCEPT {return __builtin_tan((double)__x);} // tanh -# if !defined(__sun__) inline _LIBCPP_HIDE_FROM_ABI float tanh(float __x) _NOEXCEPT {return __builtin_tanhf(__x);} template <class = int> @@ -970,7 +927,6 @@ _LIBCPP_HIDE_FROM_ABI double tanh(double __x) _NOEXCEPT { } inline _LIBCPP_HIDE_FROM_ABI long double tanh(long double __x) _NOEXCEPT {return __builtin_tanhl(__x);} -# endif template <class _A1> inline _LIBCPP_HIDE_FROM_ABI diff --git a/libcxx/include/mdspan b/libcxx/include/mdspan new file mode 100644 index 000000000000..701def50b40a --- /dev/null +++ b/libcxx/include/mdspan @@ -0,0 +1,227 @@ +// -*-C++ - *- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +/* + +// Overall mdspan synopsis + +namespace std { + // [mdspan.extents], class template extents + template<class IndexType, size_t... Extents> + class extents; + + // [mdspan.extents.dextents], alias template dextents + template<class IndexType, size_t Rank> + using dextents = see below; + + // [mdspan.layout], layout mapping + struct layout_left; + struct layout_right; + struct layout_stride; // not implemented yet + + // [mdspan.accessor.default], class template default_accessor + template<class ElementType> + class default_accessor; + + // [mdspan.mdspan], class template mdspan + template<class ElementType, class Extents, class LayoutPolicy = layout_right, + class AccessorPolicy = default_accessor<ElementType>> + class mdspan; // not implemented yet +} + +// extents synopsis + +namespace std { + template<class _IndexType, size_t... _Extents> + class extents { + public: + using index_type = _IndexType; + using size_type = make_unsigned_t<index_type>; + using rank_type = size_t; + + // [mdspan.extents.obs], observers of the multidimensional index space + static constexpr rank_type rank() noexcept { return sizeof...(_Extents); } + static constexpr rank_type rank_dynamic() noexcept { return dynamic-index(rank()); } + static constexpr size_t static_extent(rank_type) noexcept; + constexpr index_type extent(rank_type) const noexcept; + + // [mdspan.extents.cons], constructors + constexpr extents() noexcept = default; + + template<class _OtherIndexType, size_t... _OtherExtents> + constexpr explicit(see below) + extents(const extents<_OtherIndexType, _OtherExtents...>&) noexcept; + template<class... _OtherIndexTypes> + constexpr explicit extents(_OtherIndexTypes...) noexcept; + template<class _OtherIndexType, size_t N> + constexpr explicit(N != rank_dynamic()) + extents(span<_OtherIndexType, N>) noexcept; + template<class _OtherIndexType, size_t N> + constexpr explicit(N != rank_dynamic()) + extents(const array<_OtherIndexType, N>&) noexcept; + + // [mdspan.extents.cmp], comparison operators + template<class _OtherIndexType, size_t... _OtherExtents> + friend constexpr bool operator==(const extents&, + const extents<_OtherIndexType, _OtherExtents...>&) noexcept; + + private: + // libcxx note: we do not use an array here, but we need to preserve the as-if behavior + // for example the default constructor must zero initialize dynamic extents + array<index_type, rank_dynamic()> dynamic-extents{}; // exposition only + }; + + template<class... Integrals> + explicit extents(Integrals...) + -> see below; +} + +// layout_left synopsis + +namespace std { + template<class Extents> + class layout_left::mapping { + public: + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_left; + + // [mdspan.layout.right.cons], constructors + constexpr mapping() noexcept = default; + constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&) noexcept; + template<class OtherExtents> + constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) + mapping(const mapping<OtherExtents>&) noexcept; + template<class OtherExtents> + constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) + mapping(const layout_right::mapping<OtherExtents>&) noexcept; + template<class OtherExtents> + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping<OtherExtents>&) noexcept; + + constexpr mapping& operator=(const mapping&) noexcept = default; + + // [mdspan.layout.right.obs], observers + constexpr const extents_type& extents() const noexcept { return extents_; } + + constexpr index_type required_span_size() const noexcept; + + template<class... Indices> + constexpr index_type operator()(Indices...) const noexcept; + + static constexpr bool is_always_unique() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept { return true; } + static constexpr bool is_always_strided() noexcept { return true; } + + static constexpr bool is_unique() noexcept { return true; } + static constexpr bool is_exhaustive() noexcept { return true; } + static constexpr bool is_strided() noexcept { return true; } + + constexpr index_type stride(rank_type) const noexcept; + + template<class OtherExtents> + friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept; + + private: + extents_type extents_{}; // exposition only + }; +} + +// layout_right synopsis + +namespace std { + template<class Extents> + class layout_right::mapping { + public: + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_right; + + // [mdspan.layout.right.cons], constructors + constexpr mapping() noexcept = default; + constexpr mapping(const mapping&) noexcept = default; + constexpr mapping(const extents_type&) noexcept; + template<class OtherExtents> + constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) + mapping(const mapping<OtherExtents>&) noexcept; + template<class OtherExtents> + constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) + mapping(const layout_left::mapping<OtherExtents>&) noexcept; + template<class OtherExtents> + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping<OtherExtents>&) noexcept; + + constexpr mapping& operator=(const mapping&) noexcept = default; + + // [mdspan.layout.right.obs], observers + constexpr const extents_type& extents() const noexcept { return extents_; } + + constexpr index_type required_span_size() const noexcept; + + template<class... Indices> + constexpr index_type operator()(Indices...) const noexcept; + + static constexpr bool is_always_unique() noexcept { return true; } + static constexpr bool is_always_exhaustive() noexcept { return true; } + static constexpr bool is_always_strided() noexcept { return true; } + + static constexpr bool is_unique() noexcept { return true; } + static constexpr bool is_exhaustive() noexcept { return true; } + static constexpr bool is_strided() noexcept { return true; } + + constexpr index_type stride(rank_type) const noexcept; + + template<class OtherExtents> + friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept; + + private: + extents_type extents_{}; // exposition only + }; +} + +// default_accessor synopsis + +namespace std { + template<class ElementType> + struct default_accessor { + using offset_policy = default_accessor; + using element_type = ElementType; + using reference = ElementType&; + using data_handle_type = ElementType*; + + constexpr default_accessor() noexcept = default; + template<class OtherElementType> + constexpr default_accessor(default_accessor<OtherElementType>) noexcept; + constexpr reference access(data_handle_type p, size_t i) const noexcept; + constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept; + }; +} + +*/ + +#ifndef _LIBCPP_MDSPAN +#define _LIBCPP_MDSPAN + +#include <__config> +#include <__fwd/mdspan.h> +#include <__mdspan/default_accessor.h> +#include <__mdspan/extents.h> +#include <__mdspan/layout_left.h> +#include <__mdspan/layout_right.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#endif // _LIBCPP_MDSPAN diff --git a/libcxx/include/memory b/libcxx/include/memory index 0a7787acf1a8..cd6bcc7eaa35 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -160,7 +160,7 @@ template <class T, class U> bool operator==(const allocator<T>&, const allocator<U>&) noexcept; // constexpr in C++20 template <class T, class U> -bool operator!=(const allocator<T>&, const allocator<U>&) noexcept; // constexpr in C++20 +bool operator!=(const allocator<T>&, const allocator<U>&) noexcept; // removed in C++20 template <class OutputIterator, class T> class raw_storage_iterator // deprecated in C++17, removed in C++20 @@ -912,14 +912,12 @@ template<size_t N, class T> # pragma GCC system_header #endif -#if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17 -# include <__pstl_memory> -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <atomic> # include <concepts> # include <cstddef> # include <cstdint> +# include <cstdlib> # include <cstring> # include <iosfwd> # include <iterator> diff --git a/libcxx/include/memory_resource b/libcxx/include/memory_resource index 4b393433696f..276e08f23fa1 100644 --- a/libcxx/include/memory_resource +++ b/libcxx/include/memory_resource @@ -22,7 +22,7 @@ namespace std::pmr { bool operator==(const memory_resource& a, const memory_resource& b) noexcept; bool operator!=(const memory_resource& a, - const memory_resource& b) noexcept; + const memory_resource& b) noexcept; // removed in C++20 template <class Tp> class polymorphic_allocator; @@ -31,7 +31,7 @@ namespace std::pmr { const polymorphic_allocator<T2>& b) noexcept; template <class T1, class T2> bool operator!=(const polymorphic_allocator<T1>& a, - const polymorphic_allocator<T2>& b) noexcept; + const polymorphic_allocator<T2>& b) noexcept; // removed in C++20 // Global memory resources memory_resource* set_default_resource(memory_resource* r) noexcept; diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 1f1d67dbb7fc..9ff8b67a6a20 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1,1724 +1,2076 @@ -// define the module for __config outside of the top level 'std' module -// since __config may be included from C headers which may create an -// include cycle. -module std_config [system] [extern_c] { - header "__config" +// Main C++ standard library interfaces +module std_algorithm [system] { + header "algorithm" + export * +} +module std_any [system] { + header "any" + export * +} +module std_array [system] { + header "array" + export * +} +module std_atomic [system] { + header "atomic" + export * +} +module std_barrier [system] { + @requires_LIBCXX_ENABLE_THREADS@ + header "barrier" + export * +} +module std_bit [system] { + header "bit" + export * +} +module std_bitset [system] { + header "bitset" + export * +} +module std_charconv [system] { + header "charconv" + export * +} +module std_chrono [system] { + header "chrono" + export * +} +module std_codecvt [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "codecvt" + export * +} +module std_compare [system] { + header "compare" + export * +} +module std_complex [system] { + header "complex" + export * +} +module std_concepts [system] { + header "concepts" + export * +} +module std_condition_variable [system] { + header "condition_variable" + export * +} +module std_coroutine [system] { + header "coroutine" + export * +} +module std_deque [system] { + header "deque" + export * +} +module std_exception [system] { + header "exception" + export * +} +module std_execution [system] { + header "execution" + export * +} +module std_expected [system] { + header "expected" + export * +} +module std_filesystem [system] { + @requires_LIBCXX_ENABLE_FILESYSTEM@ + header "filesystem" + export * +} +module std_format [system] { + header "format" + export * +} +module std_forward_list [system] { + header "forward_list" + export * +} +module std_fstream [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + @requires_LIBCXX_ENABLE_FILESYSTEM@ + header "fstream" + export * +} +module std_functional [system] { + header "functional" + export * +} +module std_future [system] { + @requires_LIBCXX_ENABLE_THREADS@ + header "future" + export * +} +module std_initializer_list [system] { + header "initializer_list" + export * +} +module std_iomanip [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "iomanip" + export * +} +module std_ios [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "ios" + export * +} +module std_iosfwd [system] { + header "iosfwd" + export * +} +module std_iostream [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "iostream" + export * +} +module std_istream [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "istream" + export * +} +module std_iterator [system] { + header "iterator" + export * +} +module std_latch [system] { + @requires_LIBCXX_ENABLE_THREADS@ + header "latch" + export * +} +module std_limits [system] { + header "limits" + export * +} +module std_list [system] { + header "list" + export * +} +module std_locale [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "locale" + export * +} +module std_map [system] { + header "map" + export * +} +module std_mdspan [system] { + header "mdspan" + export * +} +module std_memory [system] { + header "memory" + export * +} +module std_memory_resource [system] { + header "memory_resource" + export * +} +module std_mutex [system] { + header "mutex" + export * +} +module std_new [system] { + header "new" + export * +} +module std_numbers [system] { + header "numbers" + export * +} +module std_numeric [system] { + header "numeric" + export * +} +module std_optional [system] { + header "optional" + export * +} +module std_ostream [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "ostream" + export * +} +module std_print [system] { + header "print" + export * +} +module std_queue [system] { + header "queue" + export * +} +module std_random [system] { + header "random" + export * +} +module std_ranges [system] { + header "ranges" + export * +} +module std_ratio [system] { + header "ratio" + export * +} +module std_regex [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "regex" + export * +} +module std_scoped_allocator [system] { + header "scoped_allocator" + export * +} +module std_semaphore [system] { + @requires_LIBCXX_ENABLE_THREADS@ + header "semaphore" + export * +} +module std_set [system] { + header "set" + export * +} +module std_shared_mutex [system] { + @requires_LIBCXX_ENABLE_THREADS@ + header "shared_mutex" + export std_version +} +module std_source_location [system] { + header "source_location" + export * +} +module std_span [system] { + header "span" + export std_private_ranges_enable_borrowed_range + export std_version + export std_private_span_span_fwd +} +module std_sstream [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "sstream" + export * +} +module std_stack [system] { + header "stack" + export * +} +module std_stdexcept [system] { + header "stdexcept" + export * +} +module std_stop_token { + @requires_LIBCXX_ENABLE_THREADS@ + header "stop_token" + export * +} +module std_streambuf [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "streambuf" + export * +} +module std_string [system] { + header "string" + export * +} +module std_string_view [system] { + header "string_view" + export * +} +module std_strstream [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "strstream" + export * +} +module std_system_error [system] { + header "system_error" + export * +} +module std_thread [system] { + @requires_LIBCXX_ENABLE_THREADS@ + header "thread" + export * +} +module std_tuple [system] { + header "tuple" + export * +} +module std_type_traits [system] { + header "type_traits" + export * +} +module std_typeindex [system] { + header "typeindex" + export * +} +module std_typeinfo [system] { + header "typeinfo" + export * +} +module std_unordered_map [system] { + header "unordered_map" + export * +} +module std_unordered_set [system] { + header "unordered_set" + export * +} +module std_utility [system] { + header "utility" + export * +} +module std_valarray [system] { + header "valarray" + export * +} +module std_variant [system] { + header "variant" + export * +} +module std_vector [system] { + header "vector" + export * +} +module std_version [system] { + header "version" export * } -module std [system] { - export std_config - // FIXME: The standard does not require that each of these submodules - // re-exports its imported modules. We should provide an alternative form of - // export that issues a warning if a name from the submodule is used, and - // use that to provide a 'strict mode' for libc++. - - // Deprecated C-compatibility headers. These can all be included from within - // an 'extern "C"' context. - module depr [extern_c] { - // <assert.h> provided by C library. - module ctype_h { - header "ctype.h" - export * - } - module errno_h { - header "errno.h" - export * - } - module fenv_h { - header "fenv.h" - export * - } - // <float.h> provided by compiler or C library. - module inttypes_h { - header "inttypes.h" - export stdint_h - export * - } - // <iso646.h> provided by compiler. - // <limits.h> provided by compiler or C library. - module locale_h { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "locale.h" - export * - } - module math_h { - header "math.h" - export * - } - module setjmp_h { - header "setjmp.h" - export * - } - module stdatomic_h { - @requires_LIBCXX_ENABLE_THREADS@ - requires cplusplus23 - header "stdatomic.h" - export * - } - // FIXME: <stdalign.h> is missing. - // <signal.h> provided by C library. - // <stdarg.h> provided by compiler. - module stdbool_h { - // <stdbool.h>'s __bool_true_false_are_defined macro requires textual inclusion. - textual header "stdbool.h" - } - module stddef_h { - // <stddef.h>'s __need_* macros require textual inclusion. - textual header "stddef.h" - } - module stdint_h { - header "stdint.h" - export * - // FIXME: This module only exists on OS X and for some reason the - // wildcard above doesn't export it. - export Darwin.C.stdint - } - module stdio_h { - // <stdio.h>'s __need_* macros require textual inclusion. - textual header "stdio.h" - export * - export Darwin.C.stdio - } - module stdlib_h { - // <stdlib.h>'s __need_* macros require textual inclusion. - textual header "stdlib.h" - export * - } - module string_h { - header "string.h" - export * - } - module uchar_h { - header "uchar.h" - export * - } - // <time.h> provided by C library. - module wchar_h { - @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ - // <wchar.h>'s __need_* macros require textual inclusion. - textual header "wchar.h" - export * - } - module wctype_h { - @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ - header "wctype.h" - export * - } - } +// C standard library interface wrappers +module std_cassert [system] { + // <cassert>'s use of NDEBUG requires textual inclusion. + textual header "cassert" +} +module std_ccomplex [system] { + header "ccomplex" + export * +} +module std_cctype [system] { + header "cctype" + export * +} +module std_cerrno [system] { + header "cerrno" + export * +} +module std_cfenv [system] { + header "cfenv" + export * +} +module std_cfloat [system] { + header "cfloat" + export * +} +module std_cinttypes [system] { + header "cinttypes" + export * +} +module std_ciso646 [system] { + header "ciso646" + export * +} +module std_climits [system] { + header "climits" + export * +} +module std_clocale [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "clocale" + export * +} +module std_cmath [system] { + header "cmath" + export * +} +module std_csetjmp [system] { + header "csetjmp" + export * +} +module std_csignal [system] { + header "csignal" + export * +} +// FIXME: <cstdalign> is missing. +module std_cstdarg [system] { + header "cstdarg" + export * +} +module std_cstdbool [system] { + header "cstdbool" + export * +} +module std_cstddef [system] { + header "cstddef" + export * +} +module std_cstdint [system] { + header "cstdint" + export * +} +module std_cstdio [system] { + header "cstdio" + export * +} +module std_cstdlib [system] { + header "cstdlib" + export * +} +module std_cstring [system] { + header "cstring" + export * +} +module std_ctgmath [system] { + header "ctgmath" + export * +} +module std_ctime [system] { + header "ctime" + export * +} +module std_cuchar [system] { + header "cuchar" + export * +} +module std_cwchar [system] { + @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ + header "cwchar" + export * +} +module std_cwctype [system] { + @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ + header "cwctype" + export * +} - // <complex.h> and <tgmath.h> are not C headers in any real sense, do not - // allow their use in extern "C" contexts. - module complex_h { - header "complex.h" - export ccomplex - export * - } - module tgmath_h { - header "tgmath.h" - export ccomplex - export cmath - export * - } +// C standard library interfaces augmented/replaced in C++ +// <assert.h> provided by C library. +module std_complex_h [system] { + header "complex.h" + export * +} +module std_ctype_h [system] { + header "ctype.h" + export * +} +module std_errno_h [system] { + header "errno.h" + export * +} +module std_fenv_h [system] { + header "fenv.h" + export * +} +module std_float_h [system] { + header "float.h" + export * +} +module std_inttypes_h [system] { + header "inttypes.h" + export * +} +// <iso646.h> provided by compiler. +module std_limits_h [system] { + header "limits.h" + export * +} +module std_locale_h [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "locale.h" + export * +} +module std_math_h [system] { + header "math.h" + export * +} +module std_setjmp_h [system] { + header "setjmp.h" + export * +} +// <signal.h> provided by C library. +// FIXME: <stdalign.h> is missing. +// <stdarg.h> provided by compiler. +module std_stdatomic_h [system] { + @requires_LIBCXX_ENABLE_THREADS@ + requires cplusplus23 + header "stdatomic.h" + export * +} +module std_stdbool_h [system] { + // <stdbool.h>'s __bool_true_false_are_defined macro requires textual inclusion. + textual header "stdbool.h" + export * +} +module std_stddef_h [system] { + // <stddef.h>'s __need_* macros require textual inclusion. + textual header "stddef.h" + export * +} +module std_stdint_h [system] { + header "stdint.h" + export * +} +module std_stdio_h [system] { + // <stdio.h>'s __need_* macros require textual inclusion. + textual header "stdio.h" + export * +} +module std_stdlib_h [system] { + // <stdlib.h>'s __need_* macros require textual inclusion. + textual header "stdlib.h" + export * +} +module std_string_h [system] { + header "string.h" + export * +} +module std_tgmath_h [system] { + header "tgmath.h" + export * +} +module std_uchar_h [system] { + header "uchar.h" + export * +} +// <time.h> provided by C library. +module std_wchar_h [system] { + @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ + // <wchar.h>'s __need_* macros require textual inclusion. + textual header "wchar.h" + export * +} +module std_wctype_h [system] { + @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ + header "wctype.h" + export * +} - // C compatibility headers. - module compat { - module cassert { - // <cassert>'s use of NDEBUG requires textual inclusion. - textual header "cassert" - } - module ccomplex { - header "ccomplex" - export complex - export * - } - module cctype { - header "cctype" - export * - } - module cerrno { - header "cerrno" - export * - } - module cfenv { - header "cfenv" - export * - } - module cfloat { - header "cfloat" - export * - } - module cinttypes { - header "cinttypes" - export cstdint - export * - } - module ciso646 { - header "ciso646" - export * - } - module climits { - header "climits" - export * - } - module clocale { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "clocale" - export * - } - module cmath { - header "cmath" - export * - } - module csetjmp { - header "csetjmp" - export * - } - module csignal { - header "csignal" - export * - } - // FIXME: <cstdalign> is missing. - module cstdarg { - header "cstdarg" - export * - } - module cstdbool { - header "cstdbool" - export * - } - module cstddef { - header "cstddef" - export * - } - module cstdint { - header "cstdint" - export depr.stdint_h - export * - } - module cstdio { - header "cstdio" - export * - } - module cstdlib { - header "cstdlib" - export * - } - module cstring { - header "cstring" - export * - } - module ctgmath { - header "ctgmath" - export ccomplex - export cmath - export * - } - module ctime { - header "ctime" - export * - } - module cuchar { - header "cuchar" - export * - } - module cwchar { - @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ - header "cwchar" - export depr.stdio_h - export * - } - module cwctype { - @requires_LIBCXX_ENABLE_WIDE_CHARACTERS@ - header "cwctype" - export * - } - } +// Experimental C++ standard library interfaces +module std_experimental [system] { + requires cplusplus11 - module algorithm { - header "algorithm" - export initializer_list + module deque { + header "experimental/deque" export * - - module __algorithm { - module adjacent_find { private header "__algorithm/adjacent_find.h" } - module all_of { private header "__algorithm/all_of.h" } - module any_of { private header "__algorithm/any_of.h" } - module binary_search { private header "__algorithm/binary_search.h" } - module clamp { private header "__algorithm/clamp.h" } - module comp { private header "__algorithm/comp.h" } - module comp_ref_type { private header "__algorithm/comp_ref_type.h" } - module copy { private header "__algorithm/copy.h" } - module copy_backward { private header "__algorithm/copy_backward.h" } - module copy_if { private header "__algorithm/copy_if.h" } - module copy_move_common { private header "__algorithm/copy_move_common.h" } - module copy_n { private header "__algorithm/copy_n.h" } - module count { private header "__algorithm/count.h" } - module count_if { private header "__algorithm/count_if.h" } - module equal { private header "__algorithm/equal.h" } - module equal_range { private header "__algorithm/equal_range.h" } - module fill { private header "__algorithm/fill.h" } - module fill_n { private header "__algorithm/fill_n.h" } - module find { private header "__algorithm/find.h" } - module find_end { private header "__algorithm/find_end.h" } - module find_first_of { private header "__algorithm/find_first_of.h" } - module find_if { private header "__algorithm/find_if.h" } - module find_if_not { private header "__algorithm/find_if_not.h" } - module for_each { private header "__algorithm/for_each.h" } - module for_each_n { private header "__algorithm/for_each_n.h" } - module generate { private header "__algorithm/generate.h" } - module generate_n { private header "__algorithm/generate_n.h" } - module half_positive { private header "__algorithm/half_positive.h" } - module in_found_result { private header "__algorithm/in_found_result.h" } - module in_fun_result { private header "__algorithm/in_fun_result.h" } - module in_in_out_result { private header "__algorithm/in_in_out_result.h" } - module in_in_result { private header "__algorithm/in_in_result.h" } - module in_out_out_result { private header "__algorithm/in_out_out_result.h" } - module in_out_result { private header "__algorithm/in_out_result.h" } - module includes { private header "__algorithm/includes.h" } - module inplace_merge { private header "__algorithm/inplace_merge.h" } - module is_heap { private header "__algorithm/is_heap.h" } - module is_heap_until { private header "__algorithm/is_heap_until.h" } - module is_partitioned { private header "__algorithm/is_partitioned.h" } - module is_permutation { private header "__algorithm/is_permutation.h" } - module is_sorted { private header "__algorithm/is_sorted.h" } - module is_sorted_until { private header "__algorithm/is_sorted_until.h" } - module iter_swap { private header "__algorithm/iter_swap.h" } - module iterator_operations { - private header "__algorithm/iterator_operations.h" - export * - } - module lexicographical_compare { private header "__algorithm/lexicographical_compare.h" } - module lower_bound { private header "__algorithm/lower_bound.h" } - module make_heap { private header "__algorithm/make_heap.h" } - module make_projected { private header "__algorithm/make_projected.h" } - module max { private header "__algorithm/max.h" } - module max_element { private header "__algorithm/max_element.h" } - module merge { private header "__algorithm/merge.h" } - module min { private header "__algorithm/min.h" } - module min_element { private header "__algorithm/min_element.h" } - module min_max_result { private header "__algorithm/min_max_result.h" } - module minmax { private header "__algorithm/minmax.h" } - module minmax_element { private header "__algorithm/minmax_element.h" } - module mismatch { private header "__algorithm/mismatch.h" } - module move { private header "__algorithm/move.h" } - module move_backward { private header "__algorithm/move_backward.h" } - module next_permutation { private header "__algorithm/next_permutation.h" } - module none_of { private header "__algorithm/none_of.h" } - module nth_element { private header "__algorithm/nth_element.h" } - module partial_sort { private header "__algorithm/partial_sort.h" } - module partial_sort_copy { private header "__algorithm/partial_sort_copy.h" } - module partition { private header "__algorithm/partition.h" } - module partition_copy { private header "__algorithm/partition_copy.h" } - module partition_point { private header "__algorithm/partition_point.h" } - module pop_heap { private header "__algorithm/pop_heap.h" } - module prev_permutation { private header "__algorithm/prev_permutation.h" } - module push_heap { private header "__algorithm/push_heap.h" } - module ranges_adjacent_find { private header "__algorithm/ranges_adjacent_find.h" } - module ranges_all_of { private header "__algorithm/ranges_all_of.h" } - module ranges_any_of { private header "__algorithm/ranges_any_of.h" } - module ranges_binary_search { - private header "__algorithm/ranges_binary_search.h" - export functional.__functional.ranges_operations - } - module ranges_clamp { - private header "__algorithm/ranges_clamp.h" - export functional.__functional.ranges_operations - } - module ranges_copy { - private header "__algorithm/ranges_copy.h" - export algorithm.__algorithm.in_out_result - } - module ranges_copy_backward { - private header "__algorithm/ranges_copy_backward.h" - export algorithm.__algorithm.in_out_result - } - module ranges_copy_if { - private header "__algorithm/ranges_copy_if.h" - export algorithm.__algorithm.in_out_result - } - module ranges_copy_n { - private header "__algorithm/ranges_copy_n.h" - export algorithm.__algorithm.in_out_result - } - module ranges_count { private header "__algorithm/ranges_count.h" } - module ranges_count_if { private header "__algorithm/ranges_count_if.h" } - module ranges_equal { private header "__algorithm/ranges_equal.h" } - module ranges_equal_range { - private header "__algorithm/ranges_equal_range.h" - export functional.__functional.ranges_operations - } - module ranges_fill { private header "__algorithm/ranges_fill.h" } - module ranges_fill_n { private header "__algorithm/ranges_fill_n.h" } - module ranges_find { private header "__algorithm/ranges_find.h" } - module ranges_find_end { private header "__algorithm/ranges_find_end.h" } - module ranges_find_first_of { private header "__algorithm/ranges_find_first_of.h" } - module ranges_find_if { private header "__algorithm/ranges_find_if.h" } - module ranges_find_if_not { private header "__algorithm/ranges_find_if_not.h" } - module ranges_for_each { - private header "__algorithm/ranges_for_each.h" - export algorithm.__algorithm.in_fun_result - } - module ranges_for_each_n { - private header "__algorithm/ranges_for_each_n.h" - export algorithm.__algorithm.in_fun_result - } - module ranges_generate { private header "__algorithm/ranges_generate.h" } - module ranges_generate_n { private header "__algorithm/ranges_generate_n.h" } - module ranges_includes { - private header "__algorithm/ranges_includes.h" - export functional.__functional.ranges_operations - } - module ranges_inplace_merge { - private header "__algorithm/ranges_inplace_merge.h" - export functional.__functional.ranges_operations - } - module ranges_is_heap { - private header "__algorithm/ranges_is_heap.h" - export functional.__functional.ranges_operations - } - module ranges_is_heap_until { - private header "__algorithm/ranges_is_heap_until.h" - export functional.__functional.ranges_operations - } - module ranges_is_partitioned { private header "__algorithm/ranges_is_partitioned.h" } - module ranges_is_permutation { private header "__algorithm/ranges_is_permutation.h" } - module ranges_is_sorted { - private header "__algorithm/ranges_is_sorted.h" - export functional.__functional.ranges_operations - } - module ranges_is_sorted_until { - private header "__algorithm/ranges_is_sorted_until.h" - export functional.__functional.ranges_operations - } - module ranges_iterator_concept { private header "__algorithm/ranges_iterator_concept.h" } - module ranges_lexicographical_compare { - private header "__algorithm/ranges_lexicographical_compare.h" - export functional.__functional.ranges_operations - } - module ranges_lower_bound { - private header "__algorithm/ranges_lower_bound.h" - export functional.__functional.ranges_operations - } - module ranges_make_heap { - private header "__algorithm/ranges_make_heap.h" - export functional.__functional.ranges_operations - } - module ranges_max { - private header "__algorithm/ranges_max.h" - export functional.__functional.ranges_operations - } - module ranges_max_element { - private header "__algorithm/ranges_max_element.h" - export functional.__functional.ranges_operations - } - module ranges_merge { - private header "__algorithm/ranges_merge.h" - export algorithm.__algorithm.in_in_out_result - } - module ranges_min { - private header "__algorithm/ranges_min.h" - export functional.__functional.ranges_operations - } - module ranges_min_element { - private header "__algorithm/ranges_min_element.h" - export functional.__functional.ranges_operations - } - module ranges_minmax { - private header "__algorithm/ranges_minmax.h" - export functional.__functional.ranges_operations - export algorithm.__algorithm.min_max_result - } - module ranges_minmax_element { - private header "__algorithm/ranges_minmax_element.h" - export functional.__functional.ranges_operations - export algorithm.__algorithm.min_max_result - } - module ranges_mismatch { - private header "__algorithm/ranges_mismatch.h" - export algorithm.__algorithm.in_in_result - } - module ranges_move { - private header "__algorithm/ranges_move.h" - export algorithm.__algorithm.in_out_result - } - module ranges_move_backward { - private header "__algorithm/ranges_move_backward.h" - export algorithm.__algorithm.in_out_result - } - module ranges_next_permutation { - private header "__algorithm/ranges_next_permutation.h" - export algorithm.__algorithm.in_found_result - export functional.__functional.ranges_operations - } - module ranges_none_of { private header "__algorithm/ranges_none_of.h" } - module ranges_nth_element { - private header "__algorithm/ranges_nth_element.h" - export functional.__functional.ranges_operations - } - module ranges_partial_sort { - private header "__algorithm/ranges_partial_sort.h" - export algorithm.__algorithm.in_out_result - export functional.__functional.ranges_operations - } - module ranges_partial_sort_copy { - private header "__algorithm/ranges_partial_sort_copy.h" - export algorithm.__algorithm.in_out_out_result - export functional.__functional.ranges_operations - } - module ranges_partition { private header "__algorithm/ranges_partition.h" } - module ranges_partition_copy { private header "__algorithm/ranges_partition_copy.h" } - module ranges_partition_point { private header "__algorithm/ranges_partition_point.h" } - module ranges_pop_heap { - private header "__algorithm/ranges_pop_heap.h" - export functional.__functional.ranges_operations - } - module ranges_prev_permutation { - private header "__algorithm/ranges_prev_permutation.h" - export algorithm.__algorithm.in_found_result - export functional.__functional.ranges_operations - } - module ranges_push_heap { - private header "__algorithm/ranges_push_heap.h" - export functional.__functional.ranges_operations - } - module ranges_remove { private header "__algorithm/ranges_remove.h" } - module ranges_remove_copy { - private header "__algorithm/ranges_remove_copy.h" - export algorithm.__algorithm.in_out_result - } - module ranges_remove_copy_if { - private header "__algorithm/ranges_remove_copy_if.h" - export algorithm.__algorithm.in_out_result - } - module ranges_remove_if { private header "__algorithm/ranges_remove_if.h" } - module ranges_replace { private header "__algorithm/ranges_replace.h" } - module ranges_replace_copy { - private header "__algorithm/ranges_replace_copy.h" - export algorithm.__algorithm.in_out_result - } - module ranges_replace_copy_if { - private header "__algorithm/ranges_replace_copy_if.h" - export algorithm.__algorithm.in_out_result - } - module ranges_replace_if { private header "__algorithm/ranges_replace_if.h" } - module ranges_reverse { private header "__algorithm/ranges_reverse.h" } - module ranges_reverse_copy { - private header "__algorithm/ranges_reverse_copy.h" - export algorithm.__algorithm.in_out_result - } - module ranges_rotate { private header "__algorithm/ranges_rotate.h" } - module ranges_rotate_copy { - private header "__algorithm/ranges_rotate_copy.h" - export algorithm.__algorithm.in_out_result - } - module ranges_sample { private header "__algorithm/ranges_sample.h" } - module ranges_search { private header "__algorithm/ranges_search.h" } - module ranges_search_n { private header "__algorithm/ranges_search_n.h" } - module ranges_set_difference { - private header "__algorithm/ranges_set_difference.h" - export algorithm.__algorithm.in_out_result - } - module ranges_set_intersection { - private header "__algorithm/ranges_set_intersection.h" - export algorithm.__algorithm.in_in_out_result - } - module ranges_set_symmetric_difference { - private header "__algorithm/ranges_set_symmetric_difference.h" - export algorithm.__algorithm.in_in_out_result - export functional.__functional.ranges_operations - } - module ranges_set_union { - private header "__algorithm/ranges_set_union.h" - export algorithm.__algorithm.in_in_out_result - export functional.__functional.ranges_operations - } - module ranges_shuffle { private header "__algorithm/ranges_shuffle.h" } - module ranges_sort { - private header "__algorithm/ranges_sort.h" - export functional.__functional.ranges_operations - } - module ranges_sort_heap { - private header "__algorithm/ranges_sort_heap.h" - export functional.__functional.ranges_operations - } - module ranges_stable_partition { private header "__algorithm/ranges_stable_partition.h" } - module ranges_stable_sort { - private header "__algorithm/ranges_stable_sort.h" - export functional.__functional.ranges_operations - } - module ranges_swap_ranges { - private header "__algorithm/ranges_swap_ranges.h" - export algorithm.__algorithm.in_in_result - } - module ranges_transform { - private header "__algorithm/ranges_transform.h" - export algorithm.__algorithm.in_in_out_result - export algorithm.__algorithm.in_out_result - } - module uniform_random_bit_generator_adaptor { - private header "__algorithm/uniform_random_bit_generator_adaptor.h" - } - module ranges_unique { private header "__algorithm/ranges_unique.h" } - module ranges_unique_copy { - private header "__algorithm/ranges_unique_copy.h" - export algorithm.__algorithm.in_out_result - } - module ranges_upper_bound { - private header "__algorithm/ranges_upper_bound.h" - export functional.__functional.ranges_operations - } - module remove { private header "__algorithm/remove.h" } - module remove_copy { private header "__algorithm/remove_copy.h" } - module remove_copy_if { private header "__algorithm/remove_copy_if.h" } - module remove_if { private header "__algorithm/remove_if.h" } - module replace { private header "__algorithm/replace.h" } - module replace_copy { private header "__algorithm/replace_copy.h" } - module replace_copy_if { private header "__algorithm/replace_copy_if.h" } - module replace_if { private header "__algorithm/replace_if.h" } - module reverse { private header "__algorithm/reverse.h" } - module reverse_copy { private header "__algorithm/reverse_copy.h" } - module rotate { private header "__algorithm/rotate.h" } - module rotate_copy { private header "__algorithm/rotate_copy.h" } - module sample { private header "__algorithm/sample.h" } - module search { private header "__algorithm/search.h" } - module search_n { private header "__algorithm/search_n.h" } - module set_difference { private header "__algorithm/set_difference.h" } - module set_intersection { private header "__algorithm/set_intersection.h" } - module set_symmetric_difference { private header "__algorithm/set_symmetric_difference.h" } - module set_union { private header "__algorithm/set_union.h" } - module shift_left { private header "__algorithm/shift_left.h" } - module shift_right { private header "__algorithm/shift_right.h" } - module shuffle { private header "__algorithm/shuffle.h" } - module sift_down { private header "__algorithm/sift_down.h" } - module sort { private header "__algorithm/sort.h" } - module sort_heap { private header "__algorithm/sort_heap.h" } - module stable_partition { private header "__algorithm/stable_partition.h" } - module stable_sort { private header "__algorithm/stable_sort.h" } - module swap_ranges { private header "__algorithm/swap_ranges.h" } - module transform { private header "__algorithm/transform.h" } - module unique { private header "__algorithm/unique.h" } - module unique_copy { private header "__algorithm/unique_copy.h" } - module unwrap_iter { private header "__algorithm/unwrap_iter.h" } - module unwrap_range { private header "__algorithm/unwrap_range.h" } - module upper_bound { private header "__algorithm/upper_bound.h" } - } } - module any { - header "any" + module forward_list { + header "experimental/forward_list" export * } - module array { - header "array" - export initializer_list + module iterator { + header "experimental/iterator" export * - - module array_fwd { private header "__fwd/array.h" } } - module atomic { - header "atomic" + module list { + header "experimental/list" export * } - module barrier { - @requires_LIBCXX_ENABLE_THREADS@ - header "barrier" + module map { + header "experimental/map" export * } - module bit { - header "bit" + module memory_resource { + header "experimental/memory_resource" export * - - module __bit { - module bit_cast { private header "__bit/bit_cast.h" } - module bit_ceil { private header "__bit/bit_ceil.h" } - module bit_floor { private header "__bit/bit_floor.h" } - module bit_log2 { private header "__bit/bit_log2.h" } - module bit_width { private header "__bit/bit_width.h" } - module blsr { private header "__bit/blsr.h" } - module byteswap { private header "__bit/byteswap.h" } - module countl { private header "__bit/countl.h" } - module countr { private header "__bit/countr.h" } - module endian { private header "__bit/endian.h" } - module has_single_bit { private header "__bit/has_single_bit.h" } - module popcount { private header "__bit/popcount.h" } - module rotate { private header "__bit/rotate.h" } - } } - module bitset { - header "bitset" - export string - export iosfwd + module propagate_const { + header "experimental/propagate_const" export * } - // No submodule for cassert. It fundamentally needs repeated, textual inclusion. - module charconv { - header "charconv" + module regex { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "experimental/regex" export * - - module __charconv { - module chars_format { private header "__charconv/chars_format.h" } - module from_chars_result { private header "__charconv/from_chars_result.h" } - module tables { private header "__charconv/tables.h" } - module to_chars_base_10 { private header "__charconv/to_chars_base_10.h" } - module to_chars_result { private header "__charconv/to_chars_result.h" } - } - } - module chrono { - header "chrono" + module simd { + header "experimental/simd" export * - - module __chrono { - module calendar { private header "__chrono/calendar.h" } - module convert_to_timespec { private header "__chrono/convert_to_timespec.h" } - module convert_to_tm { private header "__chrono/convert_to_tm.h" } - module day { private header "__chrono/day.h" } - module duration { private header "__chrono/duration.h" } - module file_clock { private header "__chrono/file_clock.h" } - module formatter { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - private header "__chrono/formatter.h" - } - module hh_mm_ss { private header "__chrono/hh_mm_ss.h" } - module high_resolution_clock { - private header "__chrono/high_resolution_clock.h" - export steady_clock - export system_clock - export time_point - } - module literals { private header "__chrono/literals.h" } - module month { private header "__chrono/month.h" } - module month_weekday { private header "__chrono/month_weekday.h" } - module monthday { private header "__chrono/monthday.h" } - module ostream { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - private header "__chrono/ostream.h" - } - module parser_std_format_spec { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - private header "__chrono/parser_std_format_spec.h" - } - module statically_widen { private header "__chrono/statically_widen.h" } - module steady_clock { private header "__chrono/steady_clock.h" } - module system_clock { private header "__chrono/system_clock.h" } - module time_point { private header "__chrono/time_point.h" } - module weekday { private header "__chrono/weekday.h" } - module year { private header "__chrono/year.h" } - module year_month { private header "__chrono/year_month.h" } - module year_month_day { private header "__chrono/year_month_day.h" } - module year_month_weekday { private header "__chrono/year_month_weekday.h" } - } } - module codecvt { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "codecvt" + module set { + header "experimental/set" export * } - module compare { - header "compare" + module string { + header "experimental/string" export * - - module __compare { - module common_comparison_category { private header "__compare/common_comparison_category.h" } - module compare_partial_order_fallback { private header "__compare/compare_partial_order_fallback.h" } - module compare_strong_order_fallback { private header "__compare/compare_strong_order_fallback.h" } - module compare_three_way { private header "__compare/compare_three_way.h" } - module compare_three_way_result { private header "__compare/compare_three_way_result.h" } - module compare_weak_order_fallback { private header "__compare/compare_weak_order_fallback.h" } - module is_eq { private header "__compare/is_eq.h" } - module ordering { private header "__compare/ordering.h" } - module partial_order { private header "__compare/partial_order.h" } - module strong_order { private header "__compare/strong_order.h" } - module synth_three_way { private header "__compare/synth_three_way.h" } - module three_way_comparable { private header "__compare/three_way_comparable.h" } - module weak_order { private header "__compare/weak_order.h" } - } } - module complex { - header "complex" + module type_traits { + header "experimental/type_traits" export * } - module concepts { - header "concepts" + module unordered_map { + header "experimental/unordered_map" export * - - module __concepts { - module arithmetic { private header "__concepts/arithmetic.h" } - module assignable { private header "__concepts/assignable.h" } - module boolean_testable { private header "__concepts/boolean_testable.h" } - module class_or_enum { private header "__concepts/class_or_enum.h" } - module common_reference_with { private header "__concepts/common_reference_with.h" } - module common_with { private header "__concepts/common_with.h" } - module constructible { private header "__concepts/constructible.h" } - module convertible_to { private header "__concepts/convertible_to.h" } - module copyable { private header "__concepts/copyable.h" } - module derived_from { private header "__concepts/derived_from.h" } - module destructible { private header "__concepts/destructible.h" } - module different_from { private header "__concepts/different_from.h" } - module equality_comparable { private header "__concepts/equality_comparable.h" } - module invocable { private header "__concepts/invocable.h" } - module movable { private header "__concepts/movable.h" } - module predicate { private header "__concepts/predicate.h" } - module regular { private header "__concepts/regular.h" } - module relation { private header "__concepts/relation.h" } - module same_as { private header "__concepts/same_as.h" } - module semiregular { private header "__concepts/semiregular.h" } - module swappable { private header "__concepts/swappable.h" } - module totally_ordered { private header "__concepts/totally_ordered.h" } - } } - module condition_variable { - header "condition_variable" + module unordered_set { + header "experimental/unordered_set" export * } - module coroutine { - requires coroutines - header "coroutine" - export compare + module utility { + header "experimental/utility" export * - - module __coroutine { - module coroutine_handle { private header "__coroutine/coroutine_handle.h" } - module coroutine_traits { private header "__coroutine/coroutine_traits.h" } - module noop_coroutine_handle { private header "__coroutine/noop_coroutine_handle.h" } - module trivial_awaitables { private header "__coroutine/trivial_awaitables.h" } - } } - module deque { - header "deque" - export initializer_list + module vector { + header "experimental/vector" export * } - module exception { - header "exception" + module __config { + private textual header "experimental/__config" export * } - module execution { - header "execution" + // FIXME these should be private + module __memory { + header "experimental/__memory" export * } - module expected { - header "expected" - export * +} - module __expected { - module bad_expected_access { private header "__expected/bad_expected_access.h" } - module expected { private header "__expected/expected.h" } - module unexpect { private header "__expected/unexpect.h" } - module unexpected { private header "__expected/unexpected.h" } - } - } - module filesystem { - @requires_LIBCXX_ENABLE_FILESYSTEM@ - header "filesystem" - export * +// Implementation detail headers that are private to libc++. These modules +// must not be directly imported. +module std_private_assert [system] { + header "__assert" + export * +} +module std_private_availability [system] { + header "__availability" + export * +} +module std_private_bit_reference [system] { + header "__bit_reference" + export * +} +module std_private_config [system] { + textual header "__config" + export * +} +module std_private_hash_table [system] { + header "__hash_table" + export * +} +module std_private_locale [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "__locale" + export * +} +module std_private_mbstate_t [system] { + header "__mbstate_t.h" + export * +} +module std_private_node_handle [system] { + header "__node_handle" + export * +} +module std_private_split_buffer [system] { + header "__split_buffer" + export * +} +module std_private_std_mbstate_t [system] { + header "__std_mbstate_t.h" + export * +} +module std_private_threading_support [system] { + header "__threading_support" + export * +} +module std_private_tree [system] { + header "__tree" + export * +} +module std_private_undef_macros [system] { + textual header "__undef_macros" + export * +} +module std_private_verbose_abort [system] { + header "__verbose_abort" + export * +} - module __filesystem { - module copy_options { private header "__filesystem/copy_options.h" } - module directory_entry { private header "__filesystem/directory_entry.h" } - module directory_iterator { private header "__filesystem/directory_iterator.h" } - module directory_options { private header "__filesystem/directory_options.h" } - module file_status { private header "__filesystem/file_status.h" } - module file_time_type { private header "__filesystem/file_time_type.h" } - module file_type { private header "__filesystem/file_type.h" } - module filesystem_error { private header "__filesystem/filesystem_error.h" } - module operations { private header "__filesystem/operations.h" } - module path { private header "__filesystem/path.h" } - module path_iterator { private header "__filesystem/path_iterator.h" } - module perm_options { private header "__filesystem/perm_options.h" } - module perms { private header "__filesystem/perms.h" } - module recursive_directory_iterator { private header "__filesystem/recursive_directory_iterator.h" } - module space_info { private header "__filesystem/space_info.h" } - module u8path { private header "__filesystem/u8path.h" } - } - } - module format { - header "format" - export * +module std_private_algorithm_adjacent_find [system] { header "__algorithm/adjacent_find.h" } +module std_private_algorithm_all_of [system] { header "__algorithm/all_of.h" } +module std_private_algorithm_any_of [system] { header "__algorithm/any_of.h" } +module std_private_algorithm_binary_search [system] { header "__algorithm/binary_search.h" } +module std_private_algorithm_clamp [system] { header "__algorithm/clamp.h" } +module std_private_algorithm_comp [system] { header "__algorithm/comp.h" } +module std_private_algorithm_comp_ref_type [system] { header "__algorithm/comp_ref_type.h" } +module std_private_algorithm_copy [system] { + header "__algorithm/copy.h" + export std_private_algorithm_copy_move_common +} +module std_private_algorithm_copy_backward [system] { header "__algorithm/copy_backward.h" } +module std_private_algorithm_copy_if [system] { header "__algorithm/copy_if.h" } +module std_private_algorithm_copy_move_common [system] { + header "__algorithm/copy_move_common.h" + export std_private_type_traits_is_trivially_copyable +} +module std_private_algorithm_copy_n [system] { header "__algorithm/copy_n.h" } +module std_private_algorithm_count [system] { header "__algorithm/count.h" } +module std_private_algorithm_count_if [system] { header "__algorithm/count_if.h" } +module std_private_algorithm_equal [system] { header "__algorithm/equal.h" } +module std_private_algorithm_equal_range [system] { header "__algorithm/equal_range.h" } +module std_private_algorithm_fill [system] { header "__algorithm/fill.h" } +module std_private_algorithm_fill_n [system] { header "__algorithm/fill_n.h" } +module std_private_algorithm_find [system] { + header "__algorithm/find.h" + export std_private_algorithm_unwrap_iter +} +module std_private_algorithm_find_end [system] { header "__algorithm/find_end.h" } +module std_private_algorithm_find_first_of [system] { header "__algorithm/find_first_of.h" } +module std_private_algorithm_find_if [system] { header "__algorithm/find_if.h" } +module std_private_algorithm_find_if_not [system] { header "__algorithm/find_if_not.h" } +module std_private_algorithm_for_each [system] { header "__algorithm/for_each.h" } +module std_private_algorithm_for_each_n [system] { header "__algorithm/for_each_n.h" } +module std_private_algorithm_for_each_segment [system] { header "__algorithm/for_each_segment.h" } +module std_private_algorithm_generate [system] { header "__algorithm/generate.h" } +module std_private_algorithm_generate_n [system] { header "__algorithm/generate_n.h" } +module std_private_algorithm_half_positive [system] { header "__algorithm/half_positive.h" } +module std_private_algorithm_in_found_result [system] { header "__algorithm/in_found_result.h" } +module std_private_algorithm_in_fun_result [system] { header "__algorithm/in_fun_result.h" } +module std_private_algorithm_in_in_out_result [system] { header "__algorithm/in_in_out_result.h" } +module std_private_algorithm_in_in_result [system] { header "__algorithm/in_in_result.h" } +module std_private_algorithm_in_out_out_result [system] { header "__algorithm/in_out_out_result.h" } +module std_private_algorithm_in_out_result [system] { header "__algorithm/in_out_result.h" } +module std_private_algorithm_includes [system] { header "__algorithm/includes.h" } +module std_private_algorithm_inplace_merge [system] { header "__algorithm/inplace_merge.h" } +module std_private_algorithm_is_heap [system] { header "__algorithm/is_heap.h" } +module std_private_algorithm_is_heap_until [system] { header "__algorithm/is_heap_until.h" } +module std_private_algorithm_is_partitioned [system] { header "__algorithm/is_partitioned.h" } +module std_private_algorithm_is_permutation [system] { header "__algorithm/is_permutation.h" } +module std_private_algorithm_is_sorted [system] { header "__algorithm/is_sorted.h" } +module std_private_algorithm_is_sorted_until [system] { header "__algorithm/is_sorted_until.h" } +module std_private_algorithm_iter_swap [system] { header "__algorithm/iter_swap.h" } +module std_private_algorithm_iterator_operations [system] { + header "__algorithm/iterator_operations.h" + export * +} +module std_private_algorithm_lexicographical_compare [system] { header "__algorithm/lexicographical_compare.h" } +module std_private_algorithm_lexicographical_compare_three_way [system] { header "__algorithm/lexicographical_compare_three_way.h" } +module std_private_algorithm_lower_bound [system] { header "__algorithm/lower_bound.h" } +module std_private_algorithm_make_heap [system] { header "__algorithm/make_heap.h" } +module std_private_algorithm_make_projected [system] { header "__algorithm/make_projected.h" } +module std_private_algorithm_max [system] { header "__algorithm/max.h" } +module std_private_algorithm_max_element [system] { header "__algorithm/max_element.h" } +module std_private_algorithm_merge [system] { header "__algorithm/merge.h" } +module std_private_algorithm_min [system] { header "__algorithm/min.h" } +module std_private_algorithm_min_element [system] { header "__algorithm/min_element.h" } +module std_private_algorithm_min_max_result [system] { header "__algorithm/min_max_result.h" } +module std_private_algorithm_minmax [system] { + header "__algorithm/minmax.h" + export * +} +module std_private_algorithm_minmax_element [system] { header "__algorithm/minmax_element.h" } +module std_private_algorithm_mismatch [system] { header "__algorithm/mismatch.h" } +module std_private_algorithm_move [system] { header "__algorithm/move.h" } +module std_private_algorithm_move_backward [system] { header "__algorithm/move_backward.h" } +module std_private_algorithm_next_permutation [system] { header "__algorithm/next_permutation.h" } +module std_private_algorithm_none_of [system] { header "__algorithm/none_of.h" } +module std_private_algorithm_nth_element [system] { header "__algorithm/nth_element.h" } +module std_private_algorithm_partial_sort [system] { header "__algorithm/partial_sort.h" } +module std_private_algorithm_partial_sort_copy [system] { header "__algorithm/partial_sort_copy.h" } +module std_private_algorithm_partition [system] { header "__algorithm/partition.h" } +module std_private_algorithm_partition_copy [system] { header "__algorithm/partition_copy.h" } +module std_private_algorithm_partition_point [system] { header "__algorithm/partition_point.h" } +module std_private_algorithm_pop_heap [system] { header "__algorithm/pop_heap.h" } +module std_private_algorithm_prev_permutation [system] { header "__algorithm/prev_permutation.h" } +module std_private_algorithm_pstl_any_all_none_of [system] { header "__algorithm/pstl_any_all_none_of.h" } +module std_private_algorithm_pstl_backend [system] { + header "__algorithm/pstl_backend.h" + export * +} +module std_private_algorithm_pstl_backends_cpu_backend [system] { + header "__algorithm/pstl_backends/cpu_backend.h" + export * +} +module std_private_algorithm_pstl_backends_cpu_backends_any_of [system] { header "__algorithm/pstl_backends/cpu_backends/any_of.h" } +module std_private_algorithm_pstl_backends_cpu_backends_backend [system] { + header "__algorithm/pstl_backends/cpu_backends/backend.h" + export * +} +module std_private_algorithm_pstl_backends_cpu_backends_fill [system] { header "__algorithm/pstl_backends/cpu_backends/fill.h" } +module std_private_algorithm_pstl_backends_cpu_backends_find_if [system] { header "__algorithm/pstl_backends/cpu_backends/find_if.h" } +module std_private_algorithm_pstl_backends_cpu_backends_for_each [system] { header "__algorithm/pstl_backends/cpu_backends/for_each.h" } +module std_private_algorithm_pstl_backends_cpu_backends_libdispatch [system] { header "__algorithm/pstl_backends/cpu_backends/libdispatch.h" } +module std_private_algorithm_pstl_backends_cpu_backends_merge [system] { header "__algorithm/pstl_backends/cpu_backends/merge.h" } +module std_private_algorithm_pstl_backends_cpu_backends_serial [system] { textual header "__algorithm/pstl_backends/cpu_backends/serial.h" } +module std_private_algorithm_pstl_backends_cpu_backends_stable_sort [system] { header "__algorithm/pstl_backends/cpu_backends/stable_sort.h" } +module std_private_algorithm_pstl_backends_cpu_backends_thread [system] { textual header "__algorithm/pstl_backends/cpu_backends/thread.h" } +module std_private_algorithm_pstl_backends_cpu_backends_transform [system] { + header "__algorithm/pstl_backends/cpu_backends/transform.h" + export std_private_algorithm_transform +} +module std_private_algorithm_pstl_backends_cpu_backends_transform_reduce [system] { header "__algorithm/pstl_backends/cpu_backends/transform_reduce.h" } +module std_private_algorithm_pstl_copy [system] { header "__algorithm/pstl_copy.h" } +module std_private_algorithm_pstl_count [system] { header "__algorithm/pstl_count.h" } +module std_private_algorithm_pstl_fill [system] { header "__algorithm/pstl_fill.h" } +module std_private_algorithm_pstl_find [system] { + header "__algorithm/pstl_find.h" + export * +} +module std_private_algorithm_pstl_for_each [system] { + header "__algorithm/pstl_for_each.h" + export * +} +module std_private_algorithm_pstl_frontend_dispatch [system] { + header "__algorithm/pstl_frontend_dispatch.h" + export std_private_utility_forward +} +module std_private_algorithm_pstl_generate [system] { header "__algorithm/pstl_generate.h" } +module std_private_algorithm_pstl_is_partitioned [system] { header "__algorithm/pstl_is_partitioned.h" } +module std_private_algorithm_pstl_merge [system] { header "__algorithm/pstl_merge.h" } +module std_private_algorithm_pstl_replace [system] { header "__algorithm/pstl_replace.h" } +module std_private_algorithm_pstl_stable_sort [system] { + header "__algorithm/pstl_stable_sort.h" + export std_private_functional_operations +} +module std_private_algorithm_pstl_transform [system] { header "__algorithm/pstl_transform.h" } +module std_private_algorithm_push_heap [system] { header "__algorithm/push_heap.h" } +module std_private_algorithm_ranges_adjacent_find [system] { header "__algorithm/ranges_adjacent_find.h" } +module std_private_algorithm_ranges_all_of [system] { header "__algorithm/ranges_all_of.h" } +module std_private_algorithm_ranges_any_of [system] { header "__algorithm/ranges_any_of.h" } +module std_private_algorithm_ranges_binary_search [system] { + header "__algorithm/ranges_binary_search.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_clamp [system] { + header "__algorithm/ranges_clamp.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_copy [system] { + header "__algorithm/ranges_copy.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_copy_backward [system] { + header "__algorithm/ranges_copy_backward.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_copy_if [system] { + header "__algorithm/ranges_copy_if.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_copy_n [system] { + header "__algorithm/ranges_copy_n.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_count [system] { header "__algorithm/ranges_count.h" } +module std_private_algorithm_ranges_count_if [system] { header "__algorithm/ranges_count_if.h" } +module std_private_algorithm_ranges_equal [system] { header "__algorithm/ranges_equal.h" } +module std_private_algorithm_ranges_equal_range [system] { + header "__algorithm/ranges_equal_range.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_fill [system] { header "__algorithm/ranges_fill.h" } +module std_private_algorithm_ranges_fill_n [system] { header "__algorithm/ranges_fill_n.h" } +module std_private_algorithm_ranges_find [system] { header "__algorithm/ranges_find.h" } +module std_private_algorithm_ranges_find_end [system] { header "__algorithm/ranges_find_end.h" } +module std_private_algorithm_ranges_find_first_of [system] { header "__algorithm/ranges_find_first_of.h" } +module std_private_algorithm_ranges_find_if [system] { header "__algorithm/ranges_find_if.h" } +module std_private_algorithm_ranges_find_if_not [system] { header "__algorithm/ranges_find_if_not.h" } +module std_private_algorithm_ranges_for_each [system] { + header "__algorithm/ranges_for_each.h" + export std_private_algorithm_in_fun_result +} +module std_private_algorithm_ranges_for_each_n [system] { + header "__algorithm/ranges_for_each_n.h" + export std_private_algorithm_in_fun_result +} +module std_private_algorithm_ranges_generate [system] { header "__algorithm/ranges_generate.h" } +module std_private_algorithm_ranges_generate_n [system] { header "__algorithm/ranges_generate_n.h" } +module std_private_algorithm_ranges_includes [system] { + header "__algorithm/ranges_includes.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_inplace_merge [system] { + header "__algorithm/ranges_inplace_merge.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_is_heap [system] { + header "__algorithm/ranges_is_heap.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_is_heap_until [system] { + header "__algorithm/ranges_is_heap_until.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_is_partitioned [system] { header "__algorithm/ranges_is_partitioned.h" } +module std_private_algorithm_ranges_is_permutation [system] { header "__algorithm/ranges_is_permutation.h" } +module std_private_algorithm_ranges_is_sorted [system] { + header "__algorithm/ranges_is_sorted.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_is_sorted_until [system] { + header "__algorithm/ranges_is_sorted_until.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_iterator_concept [system] { header "__algorithm/ranges_iterator_concept.h" } +module std_private_algorithm_ranges_lexicographical_compare [system] { + header "__algorithm/ranges_lexicographical_compare.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_lower_bound [system] { + header "__algorithm/ranges_lower_bound.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_make_heap [system] { + header "__algorithm/ranges_make_heap.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_max [system] { + header "__algorithm/ranges_max.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_max_element [system] { + header "__algorithm/ranges_max_element.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_merge [system] { + header "__algorithm/ranges_merge.h" + export std_private_algorithm_in_in_out_result +} +module std_private_algorithm_ranges_min [system] { + header "__algorithm/ranges_min.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_min_element [system] { + header "__algorithm/ranges_min_element.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_minmax [system] { + header "__algorithm/ranges_minmax.h" + export std_private_functional_ranges_operations + export std_private_algorithm_min_max_result +} +module std_private_algorithm_ranges_minmax_element [system] { + header "__algorithm/ranges_minmax_element.h" + export std_private_functional_ranges_operations + export std_private_algorithm_min_max_result +} +module std_private_algorithm_ranges_mismatch [system] { + header "__algorithm/ranges_mismatch.h" + export std_private_algorithm_in_in_result +} +module std_private_algorithm_ranges_move [system] { + header "__algorithm/ranges_move.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_move_backward [system] { + header "__algorithm/ranges_move_backward.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_next_permutation [system] { + header "__algorithm/ranges_next_permutation.h" + export std_private_algorithm_in_found_result + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_none_of [system] { header "__algorithm/ranges_none_of.h" } +module std_private_algorithm_ranges_nth_element [system] { + header "__algorithm/ranges_nth_element.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_partial_sort [system] { + header "__algorithm/ranges_partial_sort.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_partial_sort_copy [system] { + header "__algorithm/ranges_partial_sort_copy.h" + export std_private_algorithm_in_out_result + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_partition [system] { header "__algorithm/ranges_partition.h" } +module std_private_algorithm_ranges_partition_copy [system] { header "__algorithm/ranges_partition_copy.h" } +module std_private_algorithm_ranges_partition_point [system] { header "__algorithm/ranges_partition_point.h" } +module std_private_algorithm_ranges_pop_heap [system] { + header "__algorithm/ranges_pop_heap.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_prev_permutation [system] { + header "__algorithm/ranges_prev_permutation.h" + export std_private_algorithm_in_found_result + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_push_heap [system] { + header "__algorithm/ranges_push_heap.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_remove [system] { header "__algorithm/ranges_remove.h" } +module std_private_algorithm_ranges_remove_copy [system] { + header "__algorithm/ranges_remove_copy.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_remove_copy_if [system] { + header "__algorithm/ranges_remove_copy_if.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_remove_if [system] { header "__algorithm/ranges_remove_if.h" } +module std_private_algorithm_ranges_replace [system] { header "__algorithm/ranges_replace.h" } +module std_private_algorithm_ranges_replace_copy [system] { + header "__algorithm/ranges_replace_copy.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_replace_copy_if [system] { + header "__algorithm/ranges_replace_copy_if.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_replace_if [system] { header "__algorithm/ranges_replace_if.h" } +module std_private_algorithm_ranges_reverse [system] { header "__algorithm/ranges_reverse.h" } +module std_private_algorithm_ranges_reverse_copy [system] { + header "__algorithm/ranges_reverse_copy.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_rotate [system] { header "__algorithm/ranges_rotate.h" } +module std_private_algorithm_ranges_rotate_copy [system] { + header "__algorithm/ranges_rotate_copy.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_sample [system] { header "__algorithm/ranges_sample.h" } +module std_private_algorithm_ranges_search [system] { header "__algorithm/ranges_search.h" } +module std_private_algorithm_ranges_search_n [system] { header "__algorithm/ranges_search_n.h" } +module std_private_algorithm_ranges_set_difference [system] { + header "__algorithm/ranges_set_difference.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_set_intersection [system] { + header "__algorithm/ranges_set_intersection.h" + export std_private_algorithm_in_in_out_result +} +module std_private_algorithm_ranges_set_symmetric_difference [system] { + header "__algorithm/ranges_set_symmetric_difference.h" + export std_private_algorithm_in_in_out_result + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_set_union [system] { + header "__algorithm/ranges_set_union.h" + export std_private_algorithm_in_in_out_result + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_shuffle [system] { header "__algorithm/ranges_shuffle.h" } +module std_private_algorithm_ranges_sort [system] { + header "__algorithm/ranges_sort.h" + export std_private_algorithm_make_projected + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_sort_heap [system] { + header "__algorithm/ranges_sort_heap.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_stable_partition [system] { header "__algorithm/ranges_stable_partition.h" } +module std_private_algorithm_ranges_stable_sort [system] { + header "__algorithm/ranges_stable_sort.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_ranges_starts_with [system] { header "__algorithm/ranges_starts_with.h" } +module std_private_algorithm_ranges_swap_ranges [system] { + header "__algorithm/ranges_swap_ranges.h" + export std_private_algorithm_in_in_result +} +module std_private_algorithm_ranges_transform [system] { + header "__algorithm/ranges_transform.h" + export std_private_algorithm_in_in_out_result + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_unique [system] { header "__algorithm/ranges_unique.h" } +module std_private_algorithm_ranges_unique_copy [system] { + header "__algorithm/ranges_unique_copy.h" + export std_private_algorithm_in_out_result +} +module std_private_algorithm_ranges_upper_bound [system] { + header "__algorithm/ranges_upper_bound.h" + export std_private_functional_ranges_operations +} +module std_private_algorithm_remove [system] { header "__algorithm/remove.h" } +module std_private_algorithm_remove_copy [system] { header "__algorithm/remove_copy.h" } +module std_private_algorithm_remove_copy_if [system] { header "__algorithm/remove_copy_if.h" } +module std_private_algorithm_remove_if [system] { header "__algorithm/remove_if.h" } +module std_private_algorithm_replace [system] { header "__algorithm/replace.h" } +module std_private_algorithm_replace_copy [system] { header "__algorithm/replace_copy.h" } +module std_private_algorithm_replace_copy_if [system] { header "__algorithm/replace_copy_if.h" } +module std_private_algorithm_replace_if [system] { header "__algorithm/replace_if.h" } +module std_private_algorithm_reverse [system] { header "__algorithm/reverse.h" } +module std_private_algorithm_reverse_copy [system] { header "__algorithm/reverse_copy.h" } +module std_private_algorithm_rotate [system] { header "__algorithm/rotate.h" } +module std_private_algorithm_rotate_copy [system] { header "__algorithm/rotate_copy.h" } +module std_private_algorithm_sample [system] { header "__algorithm/sample.h" } +module std_private_algorithm_search [system] { header "__algorithm/search.h" } +module std_private_algorithm_search_n [system] { header "__algorithm/search_n.h" } +module std_private_algorithm_set_difference [system] { header "__algorithm/set_difference.h" } +module std_private_algorithm_set_intersection [system] { header "__algorithm/set_intersection.h" } +module std_private_algorithm_set_symmetric_difference [system] { header "__algorithm/set_symmetric_difference.h" } +module std_private_algorithm_set_union [system] { header "__algorithm/set_union.h" } +module std_private_algorithm_shift_left [system] { header "__algorithm/shift_left.h" } +module std_private_algorithm_shift_right [system] { header "__algorithm/shift_right.h" } +module std_private_algorithm_shuffle [system] { header "__algorithm/shuffle.h" } +module std_private_algorithm_sift_down [system] { header "__algorithm/sift_down.h" } +module std_private_algorithm_sort [system] { + header "__algorithm/sort.h" + export std_private_debug_utils_strict_weak_ordering_check +} +module std_private_algorithm_sort_heap [system] { header "__algorithm/sort_heap.h" } +module std_private_algorithm_stable_partition [system] { header "__algorithm/stable_partition.h" } +module std_private_algorithm_stable_sort [system] { header "__algorithm/stable_sort.h" } +module std_private_algorithm_swap_ranges [system] { + header "__algorithm/swap_ranges.h" + export std_private_algorithm_iterator_operations +} +module std_private_algorithm_three_way_comp_ref_type [system] { header "__algorithm/three_way_comp_ref_type.h" } +module std_private_algorithm_transform [system] { header "__algorithm/transform.h" } +module std_private_algorithm_uniform_random_bit_generator_adaptor [system] { header "__algorithm/uniform_random_bit_generator_adaptor.h" } +module std_private_algorithm_unique [system] { header "__algorithm/unique.h" } +module std_private_algorithm_unique_copy [system] { header "__algorithm/unique_copy.h" } +module std_private_algorithm_unwrap_iter [system] { + header "__algorithm/unwrap_iter.h" + export std_private_iterator_iterator_traits +} +module std_private_algorithm_unwrap_range [system] { + header "__algorithm/unwrap_range.h" + export std_private_utility_pair +} +module std_private_algorithm_upper_bound [system] { header "__algorithm/upper_bound.h" } - module __format { - module buffer { private header "__format/buffer.h" } - module concepts { private header "__format/concepts.h" } - module container_adaptor { private header "__format/container_adaptor.h" } - module enable_insertable { private header "__format/enable_insertable.h" } - module escaped_output_table { private header "__format/escaped_output_table.h" } - module extended_grapheme_cluster_table { private header "__format/extended_grapheme_cluster_table.h" } - module format_arg { private header "__format/format_arg.h" } - module format_arg_store { private header "__format/format_arg_store.h" } - module format_args { private header "__format/format_args.h" } - module format_context { - private header "__format/format_context.h" - export optional - export locale - } - module format_error { private header "__format/format_error.h" } - module format_functions { private header "__format/format_functions.h" } - module format_fwd { private header "__format/format_fwd.h" } - module format_parse_context { private header "__format/format_parse_context.h" } - module format_string { private header "__format/format_string.h" } - module format_to_n_result { - private header "__format/format_to_n_result.h" - export iterator.__iterator.incrementable_traits - } - module formatter { private header "__format/formatter.h" } - module formatter_bool { private header "__format/formatter_bool.h" } - module formatter_char { private header "__format/formatter_char.h" } - module formatter_floating_point { private header "__format/formatter_floating_point.h" } - module formatter_integer { private header "__format/formatter_integer.h" } - module formatter_integral { private header "__format/formatter_integral.h" } - module formatter_output { private header "__format/formatter_output.h" } - module formatter_pointer { private header "__format/formatter_pointer.h" } - module formatter_string { private header "__format/formatter_string.h" } - module formatter_tuple { private header "__format/formatter_tuple.h" } - module parser_std_format_spec { private header "__format/parser_std_format_spec.h" } - module range_default_formatter { private header "__format/range_default_formatter.h" } - module range_formatter { private header "__format/range_formatter.h" } - module unicode { private header "__format/unicode.h" } - } - } - module forward_list { - header "forward_list" - export initializer_list - export * - } - module fstream { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - @requires_LIBCXX_ENABLE_FSTREAM@ - header "fstream" - export * - } - module functional { - header "functional" - export * +module std_private_array_array_fwd [system] { header "__fwd/array.h" } - module __functional { - module binary_function { private header "__functional/binary_function.h" } - module binary_negate { private header "__functional/binary_negate.h" } - module bind { private header "__functional/bind.h" } - module bind_back { private header "__functional/bind_back.h" } - module bind_front { private header "__functional/bind_front.h" } - module binder1st { private header "__functional/binder1st.h" } - module binder2nd { private header "__functional/binder2nd.h" } - module boyer_moore_searcher { private header "__functional/boyer_moore_searcher.h" } - module compose { private header "__functional/compose.h" } - module default_searcher { private header "__functional/default_searcher.h" } - module function { private header "__functional/function.h" } - module hash { private header "__functional/hash.h" } - module hash_fwd { private header "__fwd/hash.h" } - module identity { private header "__functional/identity.h" } - module invoke { - private header "__functional/invoke.h" - export type_traits - } - module is_transparent { private header "__functional/is_transparent.h" } - module mem_fn { private header "__functional/mem_fn.h" } - module mem_fun_ref { private header "__functional/mem_fun_ref.h" } - module not_fn { private header "__functional/not_fn.h" } - module operations { private header "__functional/operations.h" } - module perfect_forward { private header "__functional/perfect_forward.h" } - module pointer_to_binary_function { private header "__functional/pointer_to_binary_function.h" } - module pointer_to_unary_function { private header "__functional/pointer_to_unary_function.h" } - module ranges_operations { private header "__functional/ranges_operations.h" } - module reference_wrapper { private header "__functional/reference_wrapper.h" } - module unary_function { private header "__functional/unary_function.h" } - module unary_negate { private header "__functional/unary_negate.h" } - module unwrap_ref { private header "__functional/unwrap_ref.h" } - module weak_result_type { private header "__functional/weak_result_type.h" } - } - } - module future { - @requires_LIBCXX_ENABLE_THREADS@ - header "future" - export * - } - module initializer_list { - header "initializer_list" - export * - } - module iomanip { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "iomanip" - export * - } - module ios { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "ios" - export iosfwd - export * +module std_private_atomic_aliases [system] { + header "__atomic/aliases.h" + export std_private_atomic_atomic +} +module std_private_atomic_atomic [system] { + header "__atomic/atomic.h" + export std_private_atomic_atomic_base +} +module std_private_atomic_atomic_base [system] { header "__atomic/atomic_base.h" } +module std_private_atomic_atomic_flag [system] { + header "__atomic/atomic_flag.h" + export * +} +module std_private_atomic_atomic_init [system] { header "__atomic/atomic_init.h" } +module std_private_atomic_atomic_lock_free [system] { header "__atomic/atomic_lock_free.h" } +module std_private_atomic_atomic_sync [system] { header "__atomic/atomic_sync.h" } +module std_private_atomic_check_memory_order [system] { header "__atomic/check_memory_order.h" } +module std_private_atomic_contention_t [system] { header "__atomic/contention_t.h" } +module std_private_atomic_cxx_atomic_impl [system] { header "__atomic/cxx_atomic_impl.h" } +module std_private_atomic_fence [system] { header "__atomic/fence.h" } +module std_private_atomic_is_always_lock_free [system] { header "__atomic/is_always_lock_free.h" } +module std_private_atomic_kill_dependency [system] { header "__atomic/kill_dependency.h" } +module std_private_atomic_memory_order [system] { header "__atomic/memory_order.h" } - module __ios { - module fpos { private header "__ios/fpos.h" } - } - } - module iosfwd { - header "iosfwd" - export * - } - module iostream { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "iostream" - export ios - export streambuf - export istream - export ostream - export * - } - module istream { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "istream" - // FIXME: should re-export ios, streambuf? - export * - } - module iterator { - header "iterator" - export * +module std_private_bit_bit_cast [system] { header "__bit/bit_cast.h" } +module std_private_bit_bit_ceil [system] { header "__bit/bit_ceil.h" } +module std_private_bit_bit_floor [system] { header "__bit/bit_floor.h" } +module std_private_bit_bit_log2 [system] { header "__bit/bit_log2.h" } +module std_private_bit_bit_width [system] { header "__bit/bit_width.h" } +module std_private_bit_blsr [system] { header "__bit/blsr.h" } +module std_private_bit_byteswap [system] { header "__bit/byteswap.h" } +module std_private_bit_countl [system] { header "__bit/countl.h" } +module std_private_bit_countr [system] { header "__bit/countr.h" } +module std_private_bit_endian [system] { header "__bit/endian.h" } +module std_private_bit_has_single_bit [system] { header "__bit/has_single_bit.h" } +module std_private_bit_popcount [system] { header "__bit/popcount.h" } +module std_private_bit_rotate [system] { header "__bit/rotate.h" } - module __iterator { - module access { private header "__iterator/access.h" } - module advance { private header "__iterator/advance.h" } - module back_insert_iterator { private header "__iterator/back_insert_iterator.h" } - module bounded_iter { private header "__iterator/bounded_iter.h" } - module common_iterator { private header "__iterator/common_iterator.h" } - module concepts { private header "__iterator/concepts.h" } - module counted_iterator { private header "__iterator/counted_iterator.h" } - module data { private header "__iterator/data.h" } - module default_sentinel { private header "__iterator/default_sentinel.h" } - module distance { private header "__iterator/distance.h" } - module empty { private header "__iterator/empty.h" } - module erase_if_container { private header "__iterator/erase_if_container.h" } - module front_insert_iterator { private header "__iterator/front_insert_iterator.h" } - module incrementable_traits { private header "__iterator/incrementable_traits.h" } - module indirectly_comparable { private header "__iterator/indirectly_comparable.h" } - module insert_iterator { private header "__iterator/insert_iterator.h" } - module istream_iterator { private header "__iterator/istream_iterator.h" } - module istreambuf_iterator { private header "__iterator/istreambuf_iterator.h" } - module iter_move { private header "__iterator/iter_move.h" } - module iter_swap { private header "__iterator/iter_swap.h" } - module iterator { private header "__iterator/iterator.h" } - module iterator_traits { private header "__iterator/iterator_traits.h" } - module iterator_with_data { private header "__iterator/iterator_with_data.h" } - module mergeable { - private header "__iterator/mergeable.h" - export functional.__functional.ranges_operations - } - module move_iterator { private header "__iterator/move_iterator.h" } - module move_sentinel { private header "__iterator/move_sentinel.h" } - module next { private header "__iterator/next.h" } - module ostream_iterator { private header "__iterator/ostream_iterator.h" } - module ostreambuf_iterator { - private header "__iterator/ostreambuf_iterator.h" - export iosfwd - } - module permutable { private header "__iterator/permutable.h" } - module prev { private header "__iterator/prev.h" } - module projected { private header "__iterator/projected.h" } - module readable_traits { private header "__iterator/readable_traits.h" } - module reverse_access { private header "__iterator/reverse_access.h" } - module reverse_iterator { private header "__iterator/reverse_iterator.h" } - module segmented_iterator { private header "__iterator/segmented_iterator.h" } - module size { private header "__iterator/size.h" } - module sortable { - private header "__iterator/sortable.h" - export functional.__functional.ranges_operations - } - module unreachable_sentinel { private header "__iterator/unreachable_sentinel.h" } - module wrap_iter { private header "__iterator/wrap_iter.h" } - } - } - module latch { - @requires_LIBCXX_ENABLE_THREADS@ - header "latch" - export * - } +module std_private_charconv_chars_format [system] { header "__charconv/chars_format.h" } +module std_private_charconv_from_chars_integral [system] { header "__charconv/from_chars_integral.h" } +module std_private_charconv_from_chars_result [system] { header "__charconv/from_chars_result.h" } +module std_private_charconv_tables [system] { header "__charconv/tables.h" } +module std_private_charconv_to_chars [system] { header "__charconv/to_chars.h" } +module std_private_charconv_to_chars_base_10 [system] { header "__charconv/to_chars_base_10.h" } +module std_private_charconv_to_chars_floating_point [system] { header "__charconv/to_chars_floating_point.h" } +module std_private_charconv_to_chars_integral [system] { header "__charconv/to_chars_integral.h" } +module std_private_charconv_to_chars_result [system] { header "__charconv/to_chars_result.h" } +module std_private_charconv_traits [system] { header "__charconv/traits.h" } - module __debug_utils { - module randomize_range { private header "__debug_utils/randomize_range.h" } - } +module std_private_chrono_calendar [system] { header "__chrono/calendar.h" } +module std_private_chrono_concepts [system] { header "__chrono/concepts.h" } +module std_private_chrono_convert_to_timespec [system] { header "__chrono/convert_to_timespec.h" } +module std_private_chrono_convert_to_tm [system] { header "__chrono/convert_to_tm.h" } +module std_private_chrono_day [system] { header "__chrono/day.h" } +module std_private_chrono_duration [system] { + header "__chrono/duration.h" + export std_private_type_traits_is_convertible +} +module std_private_chrono_file_clock [system] { header "__chrono/file_clock.h" } +module std_private_chrono_formatter [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "__chrono/formatter.h" +} +module std_private_chrono_hh_mm_ss [system] { header "__chrono/hh_mm_ss.h" } +module std_private_chrono_high_resolution_clock [system] { + header "__chrono/high_resolution_clock.h" + export std_private_chrono_steady_clock + export std_private_chrono_system_clock +} +module std_private_chrono_literals [system] { header "__chrono/literals.h" } +module std_private_chrono_month [system] { header "__chrono/month.h" } +module std_private_chrono_month_weekday [system] { header "__chrono/month_weekday.h" } +module std_private_chrono_monthday [system] { header "__chrono/monthday.h" } +module std_private_chrono_ostream [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "__chrono/ostream.h" +} +module std_private_chrono_parser_std_format_spec [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "__chrono/parser_std_format_spec.h" +} +module std_private_chrono_statically_widen [system] { header "__chrono/statically_widen.h" } +module std_private_chrono_steady_clock [system] { + header "__chrono/steady_clock.h" + export std_private_chrono_time_point +} +module std_private_chrono_system_clock [system] { + header "__chrono/system_clock.h" + export std_private_chrono_time_point +} +module std_private_chrono_time_point [system] { header "__chrono/time_point.h" } +module std_private_chrono_weekday [system] { header "__chrono/weekday.h" } +module std_private_chrono_year [system] { header "__chrono/year.h" } +module std_private_chrono_year_month [system] { header "__chrono/year_month.h" } +module std_private_chrono_year_month_day [system] { header "__chrono/year_month_day.h" } +module std_private_chrono_year_month_weekday [system] { header "__chrono/year_month_weekday.h" } - module limits { - header "limits" - export * - } - module list { - header "list" - export initializer_list - export * - } - module locale { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "locale" - export * - } - module map { - header "map" - export initializer_list - export * - } - module memory { - header "memory" - export * +module std_private_compare_common_comparison_category [system] { header "__compare/common_comparison_category.h" } +module std_private_compare_compare_partial_order_fallback [system] { header "__compare/compare_partial_order_fallback.h" } +module std_private_compare_compare_strong_order_fallback [system] { header "__compare/compare_strong_order_fallback.h" } +module std_private_compare_compare_three_way [system] { header "__compare/compare_three_way.h" } +module std_private_compare_compare_three_way_result [system] { header "__compare/compare_three_way_result.h" } +module std_private_compare_compare_weak_order_fallback [system] { header "__compare/compare_weak_order_fallback.h" } +module std_private_compare_is_eq [system] { header "__compare/is_eq.h" } +module std_private_compare_ordering [system] { header "__compare/ordering.h" } +module std_private_compare_partial_order [system] { header "__compare/partial_order.h" } +module std_private_compare_strong_order [system] { header "__compare/strong_order.h" } +module std_private_compare_synth_three_way [system] { header "__compare/synth_three_way.h" } +module std_private_compare_three_way_comparable [system] { header "__compare/three_way_comparable.h" } +module std_private_compare_weak_order [system] { header "__compare/weak_order.h" } - module __memory { - module addressof { private header "__memory/addressof.h" } - module align { private header "__memory/align.h" } - module allocate_at_least { private header "__memory/allocate_at_least.h" } - module allocation_guard { private header "__memory/allocation_guard.h" } - module allocator { private header "__memory/allocator.h" } - module allocator_arg_t { private header "__memory/allocator_arg_t.h" } - module allocator_destructor { private header "__memory/allocator_destructor.h" } - module allocator_traits { private header "__memory/allocator_traits.h" } - module assume_aligned { private header "__memory/assume_aligned.h" } - module auto_ptr { private header "__memory/auto_ptr.h" } - module builtin_new_allocator { private header "__memory/builtin_new_allocator.h" } - module compressed_pair { private header "__memory/compressed_pair.h" } - module concepts { private header "__memory/concepts.h" } - module construct_at { private header "__memory/construct_at.h" } - module destruct_n { private header "__memory/destruct_n.h" } - module pointer_traits { private header "__memory/pointer_traits.h" } - module ranges_construct_at { private header "__memory/ranges_construct_at.h" } - module ranges_uninitialized_algorithms { - private header "__memory/ranges_uninitialized_algorithms.h" - export algorithm.__algorithm.in_out_result - } - module raw_storage_iterator { private header "__memory/raw_storage_iterator.h" } - module shared_ptr { private header "__memory/shared_ptr.h" } - module swap_allocator { private header "__memory/swap_allocator.h" } - module temp_value { private header "__memory/temp_value.h" } - module temporary_buffer { private header "__memory/temporary_buffer.h" } - module uninitialized_algorithms { private header "__memory/uninitialized_algorithms.h" } - module unique_ptr { private header "__memory/unique_ptr.h" } - module uses_allocator { private header "__memory/uses_allocator.h" } - module uses_allocator_construction { private header "__memory/uses_allocator_construction.h" } - module voidify { private header "__memory/voidify.h" } - } - } - module memory_resource { - header "memory_resource" - export * +module std_private_concepts_arithmetic [system] { header "__concepts/arithmetic.h" } +module std_private_concepts_assignable [system] { header "__concepts/assignable.h" } +module std_private_concepts_boolean_testable [system] { header "__concepts/boolean_testable.h" } +module std_private_concepts_class_or_enum [system] { header "__concepts/class_or_enum.h" } +module std_private_concepts_common_reference_with [system] { header "__concepts/common_reference_with.h" } +module std_private_concepts_common_with [system] { header "__concepts/common_with.h" } +module std_private_concepts_constructible [system] { + header "__concepts/constructible.h" + export std_private_concepts_destructible +} +module std_private_concepts_convertible_to [system] { header "__concepts/convertible_to.h" } +module std_private_concepts_copyable [system] { header "__concepts/copyable.h" } +module std_private_concepts_derived_from [system] { header "__concepts/derived_from.h" } +module std_private_concepts_destructible [system] { + header "__concepts/destructible.h" + export std_private_type_traits_is_nothrow_destructible +} +module std_private_concepts_different_from [system] { header "__concepts/different_from.h" } +module std_private_concepts_equality_comparable [system] { + header "__concepts/equality_comparable.h" + export std_private_type_traits_common_reference +} +module std_private_concepts_invocable [system] { header "__concepts/invocable.h" } +module std_private_concepts_movable [system] { + header "__concepts/movable.h" + export std_private_type_traits_is_object +} +module std_private_concepts_predicate [system] { header "__concepts/predicate.h" } +module std_private_concepts_regular [system] { header "__concepts/regular.h" } +module std_private_concepts_relation [system] { header "__concepts/relation.h" } +module std_private_concepts_same_as [system] { + header "__concepts/same_as.h" + export std_private_type_traits_is_same +} +module std_private_concepts_semiregular [system] { header "__concepts/semiregular.h" } +module std_private_concepts_swappable [system] { header "__concepts/swappable.h" } +module std_private_concepts_totally_ordered [system] { header "__concepts/totally_ordered.h" } - module __memory_resource { - module memory_resource { private header "__memory_resource/memory_resource.h" } - module memory_resource_fwd { private header "__fwd/memory_resource.h" } - module monotonic_buffer_resource { private header "__memory_resource/monotonic_buffer_resource.h" } - module polymorphic_allocator { private header "__memory_resource/polymorphic_allocator.h" } - module pool_options { private header "__memory_resource/pool_options.h" } - module synchronized_pool_resource { private header "__memory_resource/synchronized_pool_resource.h" } - module unsynchronized_pool_resource { private header "__memory_resource/unsynchronized_pool_resource.h" } - } - } - module mutex { - @requires_LIBCXX_ENABLE_THREADS@ - header "mutex" - export * - } - module new { - header "new" - export * - } - module numbers { - header "numbers" - export * - } - module numeric { - header "numeric" - export * +module std_private_condition_variable_condition_variable [system] { + header "__condition_variable/condition_variable.h" + export * +} - module __numeric { - module accumulate { private header "__numeric/accumulate.h" } - module adjacent_difference { private header "__numeric/adjacent_difference.h" } - module exclusive_scan { private header "__numeric/exclusive_scan.h" } - module gcd_lcm { private header "__numeric/gcd_lcm.h" } - module inclusive_scan { private header "__numeric/inclusive_scan.h" } - module inner_product { private header "__numeric/inner_product.h" } - module iota { private header "__numeric/iota.h" } - module midpoint { private header "__numeric/midpoint.h" } - module partial_sum { private header "__numeric/partial_sum.h" } - module reduce { private header "__numeric/reduce.h" } - module transform_exclusive_scan { private header "__numeric/transform_exclusive_scan.h" } - module transform_inclusive_scan { private header "__numeric/transform_inclusive_scan.h" } - module transform_reduce { private header "__numeric/transform_reduce.h" } - } - } - module optional { - header "optional" - export * - } - module ostream { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "ostream" - // FIXME: should re-export ios, streambuf? - export * - } - module queue { - header "queue" - export initializer_list - export * - } - module random { - header "random" - export initializer_list - export * +module std_private_coroutine_coroutine_handle [system] { header "__coroutine/coroutine_handle.h" } +module std_private_coroutine_coroutine_traits [system] { header "__coroutine/coroutine_traits.h" } +module std_private_coroutine_noop_coroutine_handle [system] { header "__coroutine/noop_coroutine_handle.h" } +module std_private_coroutine_trivial_awaitables [system] { header "__coroutine/trivial_awaitables.h" } - module __random { - module bernoulli_distribution { private header "__random/bernoulli_distribution.h" } - module binomial_distribution { private header "__random/binomial_distribution.h" } - module cauchy_distribution { private header "__random/cauchy_distribution.h" } - module chi_squared_distribution { private header "__random/chi_squared_distribution.h" } - module clamp_to_integral { private header "__random/clamp_to_integral.h" } - module default_random_engine { private header "__random/default_random_engine.h" } - module discard_block_engine { private header "__random/discard_block_engine.h" } - module discrete_distribution { - private header "__random/discrete_distribution.h" - export vector - } - module exponential_distribution { private header "__random/exponential_distribution.h" } - module extreme_value_distribution { private header "__random/extreme_value_distribution.h" } - module fisher_f_distribution { private header "__random/fisher_f_distribution.h" } - module gamma_distribution { private header "__random/gamma_distribution.h" } - module generate_canonical { private header "__random/generate_canonical.h" } - module geometric_distribution { private header "__random/geometric_distribution.h" } - module independent_bits_engine { private header "__random/independent_bits_engine.h" } - module is_seed_sequence { private header "__random/is_seed_sequence.h" } - module is_valid { private header "__random/is_valid.h" } - module knuth_b { private header "__random/knuth_b.h" } - module linear_congruential_engine { private header "__random/linear_congruential_engine.h" } - module log2 { private header "__random/log2.h" } - module lognormal_distribution { private header "__random/lognormal_distribution.h" } - module mersenne_twister_engine { private header "__random/mersenne_twister_engine.h" } - module negative_binomial_distribution { private header "__random/negative_binomial_distribution.h" } - module normal_distribution { private header "__random/normal_distribution.h" } - module piecewise_constant_distribution { - private header "__random/piecewise_constant_distribution.h" - export vector - } - module piecewise_linear_distribution { - private header "__random/piecewise_linear_distribution.h" - export vector - } - module poisson_distribution { private header "__random/poisson_distribution.h" } - module random_device { private header "__random/random_device.h" } - module ranlux { private header "__random/ranlux.h" } - module seed_seq { private header "__random/seed_seq.h" } - module shuffle_order_engine { private header "__random/shuffle_order_engine.h" } - module student_t_distribution { private header "__random/student_t_distribution.h" } - module subtract_with_carry_engine { private header "__random/subtract_with_carry_engine.h" } - module uniform_int_distribution { private header "__random/uniform_int_distribution.h" } - module uniform_random_bit_generator { private header "__random/uniform_random_bit_generator.h" } - module uniform_real_distribution { private header "__random/uniform_real_distribution.h" } - module weibull_distribution { private header "__random/weibull_distribution.h" } - } - } - module ranges { - header "ranges" - export compare - export initializer_list - export iterator - export * +module std_private_debug_utils_randomize_range [system] { header "__debug_utils/randomize_range.h" } +module std_private_debug_utils_strict_weak_ordering_check [system] { + header "__debug_utils/strict_weak_ordering_check.h" + export std_private_type_traits_is_constant_evaluated +} - module __ranges { - module access { private header "__ranges/access.h" } - module all { - private header "__ranges/all.h" - export functional.__functional.compose - export functional.__functional.perfect_forward - } - module as_rvalue_view { private header "__ranges/as_rvalue_view.h" } - module common_view { private header "__ranges/common_view.h" } - module concepts { private header "__ranges/concepts.h" } - module copyable_box { private header "__ranges/copyable_box.h" } - module counted { - private header "__ranges/counted.h" - export span - } - module dangling { private header "__ranges/dangling.h" } - module data { private header "__ranges/data.h" } - module drop_view { private header "__ranges/drop_view.h" } - module drop_while_view { private header "__ranges/drop_while_view.h" } - module elements_view { private header "__ranges/elements_view.h" } - module empty { private header "__ranges/empty.h" } - module empty_view { private header "__ranges/empty_view.h" } - module enable_borrowed_range { private header "__ranges/enable_borrowed_range.h" } - module enable_view { private header "__ranges/enable_view.h" } - module filter_view { private header "__ranges/filter_view.h" } - module iota_view { private header "__ranges/iota_view.h" } - module istream_view { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - private header "__ranges/istream_view.h" - } - module join_view { private header "__ranges/join_view.h" } - module lazy_split_view { private header "__ranges/lazy_split_view.h" } - module non_propagating_cache { private header "__ranges/non_propagating_cache.h" } - module owning_view { private header "__ranges/owning_view.h" } - module range_adaptor { private header "__ranges/range_adaptor.h" } - module rbegin { private header "__ranges/rbegin.h" } - module ref_view { private header "__ranges/ref_view.h" } - module rend { private header "__ranges/rend.h" } - module reverse_view { private header "__ranges/reverse_view.h" } - module single_view { private header "__ranges/single_view.h" } - module size { private header "__ranges/size.h" } - module split_view { private header "__ranges/split_view.h" } - module subrange { - private header "__ranges/subrange.h" +module std_private_exception_exception [system] { header "__exception/exception.h" } +module std_private_exception_exception_ptr [system] { + header "__exception/exception_ptr.h" + export std_private_exception_operations +} +module std_private_exception_nested_exception [system] { header "__exception/nested_exception.h" } +module std_private_exception_operations [system] { header "__exception/operations.h" } +module std_private_exception_terminate [system] { header "__exception/terminate.h" } - module subrange_fwd { private header "__fwd/subrange.h" } - } - module take_view { private header "__ranges/take_view.h" } - module take_while_view { private header "__ranges/take_while_view.h" } - module transform_view { - private header "__ranges/transform_view.h" - export functional.__functional.bind_back - export functional.__functional.perfect_forward - } - module view_interface { private header "__ranges/view_interface.h" } - module views { private header "__ranges/views.h" } - module zip_view { private header "__ranges/zip_view.h" } - } - } - module ratio { - header "ratio" - export * - } - module regex { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "regex" - export initializer_list - export * - } - module scoped_allocator { - header "scoped_allocator" - export * - } - module semaphore { - @requires_LIBCXX_ENABLE_THREADS@ - header "semaphore" - export * - } - module set { - header "set" - export initializer_list - export * - } - module shared_mutex { - @requires_LIBCXX_ENABLE_THREADS@ - header "shared_mutex" - export version - } - module source_location { - header "source_location" - export * - } - module span { - header "span" - export ranges.__ranges.enable_borrowed_range - export version - module span_fwd { private header "__fwd/span.h" } - } - module sstream { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "sstream" - // FIXME: should re-export istream, ostream, ios, streambuf, string? - export * - } - module stack { - header "stack" - export initializer_list - export * - } - module stdexcept { - header "stdexcept" - export * - } - module streambuf { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "streambuf" - export * - } - module string { - header "string" - export initializer_list - export string_view - module __string { - module char_traits { private header "__string/char_traits.h" } - module extern_template_lists { private header "__string/extern_template_lists.h" } - module string_fwd { private header "__fwd/string.h" } - } - export * - } - module string_view { - header "string_view" - export initializer_list - export * - module string_view_fwd { private header "__fwd/string_view.h" } - } - module strstream { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "strstream" - export * - } - module system_error { - header "system_error" - export * - } - module thread { - @requires_LIBCXX_ENABLE_THREADS@ - header "thread" - export * +module std_private_expected_bad_expected_access [system] { header "__expected/bad_expected_access.h" } +module std_private_expected_expected [system] { header "__expected/expected.h" } +module std_private_expected_unexpect [system] { header "__expected/unexpect.h" } +module std_private_expected_unexpected [system] { header "__expected/unexpected.h" } - module __thread { - module poll_with_backoff { private header "__thread/poll_with_backoff.h" } - module timed_backoff_policy { private header "__thread/timed_backoff_policy.h" } - } - } - module tuple { - header "tuple" - export * +module std_private_filesystem_copy_options [system] { header "__filesystem/copy_options.h" } +module std_private_filesystem_directory_entry [system] { + header "__filesystem/directory_entry.h" + export * +} +module std_private_filesystem_directory_iterator [system] { + header "__filesystem/directory_iterator.h" + export * +} +module std_private_filesystem_directory_options [system] { header "__filesystem/directory_options.h" } +module std_private_filesystem_file_status [system] { header "__filesystem/file_status.h" } +module std_private_filesystem_file_time_type [system] { header "__filesystem/file_time_type.h" } +module std_private_filesystem_file_type [system] { header "__filesystem/file_type.h" } +module std_private_filesystem_filesystem_error [system] { + header "__filesystem/filesystem_error.h" + export * +} +module std_private_filesystem_operations [system] { header "__filesystem/operations.h" } +module std_private_filesystem_path [system] { + header "__filesystem/path.h" + export * +} +module std_private_filesystem_path_iterator [system] { header "__filesystem/path_iterator.h" } +module std_private_filesystem_perm_options [system] { header "__filesystem/perm_options.h" } +module std_private_filesystem_perms [system] { header "__filesystem/perms.h" } +module std_private_filesystem_recursive_directory_iterator [system] { + header "__filesystem/recursive_directory_iterator.h" + export * +} +module std_private_filesystem_space_info [system] { header "__filesystem/space_info.h" } +module std_private_filesystem_u8path [system] { header "__filesystem/u8path.h" } - module apply_cv { private header "__tuple_dir/apply_cv.h" } - module get_fwd { private header "__fwd/get.h" } - module make_tuple_types { private header "__tuple_dir/make_tuple_types.h" } - module pair_like { private header "__tuple_dir/pair_like.h" } - module sfinae_helpers { private header "__tuple_dir/sfinae_helpers.h" } - module tuple_element { private header "__tuple_dir/tuple_element.h" } - module tuple_fwd { private header "__fwd/tuple.h" } - module tuple_indices { private header "__tuple_dir/tuple_indices.h" } - module tuple_like { private header "__tuple_dir/tuple_like.h" } - module tuple_like_ext { private header "__tuple_dir/tuple_like_ext.h" } - module tuple_size { private header "__tuple_dir/tuple_size.h" } - module tuple_types { private header "__tuple_dir/tuple_types.h" } - } - module type_traits { - header "type_traits" - export functional.__functional.unwrap_ref - export * +module std_private_format_buffer [system] { header "__format/buffer.h" } +module std_private_format_concepts [system] { header "__format/concepts.h" } +module std_private_format_container_adaptor [system] { header "__format/container_adaptor.h" } +module std_private_format_enable_insertable [system] { header "__format/enable_insertable.h" } +module std_private_format_escaped_output_table [system] { header "__format/escaped_output_table.h" } +module std_private_format_extended_grapheme_cluster_table [system] { header "__format/extended_grapheme_cluster_table.h" } +module std_private_format_format_arg [system] { header "__format/format_arg.h" } +module std_private_format_format_arg_store [system] { header "__format/format_arg_store.h" } +module std_private_format_format_args [system] { header "__format/format_args.h" } +module std_private_format_format_context [system] { + header "__format/format_context.h" + export * +} +module std_private_format_format_error [system] { header "__format/format_error.h" } +module std_private_format_format_functions [system] { + header "__format/format_functions.h" + export std_string +} +module std_private_format_format_fwd [system] { header "__format/format_fwd.h" } +module std_private_format_format_parse_context [system] { header "__format/format_parse_context.h" } +module std_private_format_format_string [system] { header "__format/format_string.h" } +module std_private_format_format_to_n_result [system] { + header "__format/format_to_n_result.h" + export std_private_iterator_incrementable_traits +} +module std_private_format_formatter [system] { header "__format/formatter.h" } +module std_private_format_formatter_bool [system] { header "__format/formatter_bool.h" } +module std_private_format_formatter_char [system] { header "__format/formatter_char.h" } +module std_private_format_formatter_floating_point [system] { header "__format/formatter_floating_point.h" } +module std_private_format_formatter_integer [system] { header "__format/formatter_integer.h" } +module std_private_format_formatter_integral [system] { header "__format/formatter_integral.h" } +module std_private_format_formatter_output [system] { header "__format/formatter_output.h" } +module std_private_format_formatter_pointer [system] { header "__format/formatter_pointer.h" } +module std_private_format_formatter_string [system] { header "__format/formatter_string.h" } +module std_private_format_formatter_tuple [system] { header "__format/formatter_tuple.h" } +module std_private_format_parser_std_format_spec [system] { header "__format/parser_std_format_spec.h" } +module std_private_format_range_default_formatter [system] { header "__format/range_default_formatter.h" } +module std_private_format_range_formatter [system] { header "__format/range_formatter.h" } +module std_private_format_unicode [system] { + header "__format/unicode.h" + export std_private_format_extended_grapheme_cluster_table +} +module std_private_format_width_estimation_table [system] { header "__format/width_estimation_table.h" } +module std_private_format_write_escaped [system] { header "__format/write_escaped.h" } - module add_const { private header "__type_traits/add_const.h" } - module add_cv { private header "__type_traits/add_cv.h" } - module add_lvalue_reference { private header "__type_traits/add_lvalue_reference.h" } - module add_pointer { private header "__type_traits/add_pointer.h" } - module add_rvalue_reference { private header "__type_traits/add_rvalue_reference.h" } - module add_volatile { private header "__type_traits/add_volatile.h" } - module aligned_storage { private header "__type_traits/aligned_storage.h" } - module aligned_union { private header "__type_traits/aligned_union.h" } - module alignment_of { private header "__type_traits/alignment_of.h" } - module apply_cv { private header "__type_traits/apply_cv.h" } - module can_extract_key { private header "__type_traits/can_extract_key.h" } - module common_reference { private header "__type_traits/common_reference.h" } - module common_type { private header "__type_traits/common_type.h" } - module conditional { private header "__type_traits/conditional.h" } - module conjunction { private header "__type_traits/conjunction.h" } - module copy_cv { private header "__type_traits/copy_cv.h" } - module copy_cvref { private header "__type_traits/copy_cvref.h" } - module decay { private header "__type_traits/decay.h" } - module dependent_type { private header "__type_traits/dependent_type.h" } - module disjunction { private header "__type_traits/disjunction.h" } - module enable_if { private header "__type_traits/enable_if.h" } - module extent { private header "__type_traits/extent.h" } - module has_unique_object_representation { private header "__type_traits/has_unique_object_representation.h" } - module has_virtual_destructor { private header "__type_traits/has_virtual_destructor.h" } - module integral_constant { private header "__type_traits/integral_constant.h" } - module is_abstract { private header "__type_traits/is_abstract.h" } - module is_aggregate { private header "__type_traits/is_aggregate.h" } - module is_allocator { private header "__type_traits/is_allocator.h" } - module is_always_bitcastable { private header "__type_traits/is_always_bitcastable.h" } - module is_arithmetic { - private header "__type_traits/is_arithmetic.h" - export integral_constant - } - module is_array { - private header "__type_traits/is_array.h" - export integral_constant - } - module is_assignable { private header "__type_traits/is_assignable.h" } - module is_base_of { private header "__type_traits/is_base_of.h" } - module is_bounded_array { private header "__type_traits/is_bounded_array.h" } - module is_callable { private header "__type_traits/is_callable.h" } - module is_char_like_type { private header "__type_traits/is_char_like_type.h" } - module is_class { private header "__type_traits/is_class.h" } - module is_compound { private header "__type_traits/is_compound.h" } - module is_const { private header "__type_traits/is_const.h" } - module is_constant_evaluated { private header "__type_traits/is_constant_evaluated.h" } - module is_constructible { private header "__type_traits/is_constructible.h" } - module is_convertible { private header "__type_traits/is_convertible.h" } - module is_copy_assignable { private header "__type_traits/is_copy_assignable.h" } - module is_copy_constructible { private header "__type_traits/is_copy_constructible.h" } - module is_core_convertible { - private header "__type_traits/is_core_convertible.h" - export integral_constant - } - module is_default_constructible { private header "__type_traits/is_default_constructible.h" } - module is_destructible { private header "__type_traits/is_destructible.h" } - module is_empty { private header "__type_traits/is_empty.h" } - module is_enum { private header "__type_traits/is_enum.h" } - module is_final { private header "__type_traits/is_final.h" } - module is_floating_point { private header "__type_traits/is_floating_point.h" } - module is_function { private header "__type_traits/is_function.h" } - module is_fundamental { private header "__type_traits/is_fundamental.h" } - module is_implicitly_default_constructible { private header "__type_traits/is_implicitly_default_constructible.h" } - module is_integral { private header "__type_traits/is_integral.h" } - module is_literal_type { private header "__type_traits/is_literal_type.h" } - module is_member_function_pointer { private header "__type_traits/is_member_function_pointer.h" } - module is_member_object_pointer { private header "__type_traits/is_member_object_pointer.h" } - module is_member_pointer { private header "__type_traits/is_member_pointer.h" } - module is_move_assignable { private header "__type_traits/is_move_assignable.h" } - module is_move_constructible { private header "__type_traits/is_move_constructible.h" } - module is_nothrow_assignable { private header "__type_traits/is_nothrow_assignable.h" } - module is_nothrow_constructible { private header "__type_traits/is_nothrow_constructible.h" } - module is_nothrow_convertible { private header "__type_traits/is_nothrow_convertible.h" } - module is_nothrow_copy_assignable { private header "__type_traits/is_nothrow_copy_assignable.h" } - module is_nothrow_copy_constructible { private header "__type_traits/is_nothrow_copy_constructible.h" } - module is_nothrow_default_constructible { private header "__type_traits/is_nothrow_default_constructible.h" } - module is_nothrow_destructible { private header "__type_traits/is_nothrow_destructible.h" } - module is_nothrow_move_assignable { private header "__type_traits/is_nothrow_move_assignable.h" } - module is_nothrow_move_constructible { private header "__type_traits/is_nothrow_move_constructible.h" } - module is_null_pointer { private header "__type_traits/is_null_pointer.h" } - module is_object { private header "__type_traits/is_object.h" } - module is_pod { private header "__type_traits/is_pod.h" } - module is_pointer { private header "__type_traits/is_pointer.h" } - module is_polymorphic { private header "__type_traits/is_polymorphic.h" } - module is_primary_template { private header "__type_traits/is_primary_template.h" } - module is_reference { private header "__type_traits/is_reference.h" } - module is_reference_wrapper { private header "__type_traits/is_reference_wrapper.h" } - module is_referenceable { private header "__type_traits/is_referenceable.h" } - module is_same { - private header "__type_traits/is_same.h" - export type_traits.integral_constant - } - module is_scalar { private header "__type_traits/is_scalar.h" } - module is_scoped_enum { private header "__type_traits/is_scoped_enum.h" } - module is_signed { private header "__type_traits/is_signed.h" } - module is_signed_integer { private header "__type_traits/is_signed_integer.h" } - module is_specialization { private header "__type_traits/is_specialization.h" } - module is_standard_layout { private header "__type_traits/is_standard_layout.h" } - module is_swappable { private header "__type_traits/is_swappable.h" } - module is_trivial { private header "__type_traits/is_trivial.h" } - module is_trivially_assignable { private header "__type_traits/is_trivially_assignable.h" } - module is_trivially_constructible { private header "__type_traits/is_trivially_constructible.h" } - module is_trivially_copy_assignable { private header "__type_traits/is_trivially_copy_assignable.h" } - module is_trivially_copy_constructible { private header "__type_traits/is_trivially_copy_constructible.h" } - module is_trivially_copyable { private header "__type_traits/is_trivially_copyable.h" } - module is_trivially_default_constructible { private header "__type_traits/is_trivially_default_constructible.h" } - module is_trivially_destructible { private header "__type_traits/is_trivially_destructible.h" } - module is_trivially_move_assignable { private header "__type_traits/is_trivially_move_assignable.h" } - module is_trivially_move_constructible { private header "__type_traits/is_trivially_move_constructible.h" } - module is_unbounded_array { private header "__type_traits/is_unbounded_array.h" } - module is_union { private header "__type_traits/is_union.h" } - module is_unsigned { private header "__type_traits/is_unsigned.h" } - module is_unsigned_integer { private header "__type_traits/is_unsigned_integer.h" } - module is_valid_expansion { private header "__type_traits/is_valid_expansion.h" } - module is_void { - private header "__type_traits/is_void.h" - export integral_constant - } - module is_volatile { private header "__type_traits/is_volatile.h" } - module lazy { private header "__type_traits/lazy.h" } - module make_32_64_or_128_bit { private header "__type_traits/make_32_64_or_128_bit.h" } - module make_const_lvalue_ref { private header "__type_traits/make_const_lvalue_ref.h" } - module make_signed { private header "__type_traits/make_signed.h" } - module make_unsigned { private header "__type_traits/make_unsigned.h" } - module maybe_const { private header "__type_traits/maybe_const.h" } - module nat { private header "__type_traits/nat.h" } - module negation { private header "__type_traits/negation.h" } - module noexcept_move_assign_container { private header "__type_traits/noexcept_move_assign_container.h" } - module promote { private header "__type_traits/promote.h" } - module rank { private header "__type_traits/rank.h" } - module remove_all_extents { private header "__type_traits/remove_all_extents.h" } - module remove_const { private header "__type_traits/remove_const.h" } - module remove_const_ref { private header "__type_traits/remove_const_ref.h" } - module remove_cv { private header "__type_traits/remove_cv.h" } - module remove_cvref { private header "__type_traits/remove_cvref.h" } - module remove_extent { private header "__type_traits/remove_extent.h" } - module remove_pointer { private header "__type_traits/remove_pointer.h" } - module remove_reference { private header "__type_traits/remove_reference.h" } - module remove_volatile { private header "__type_traits/remove_volatile.h" } - module result_of { private header "__type_traits/result_of.h" } - module strip_signature { private header "__type_traits/strip_signature.h" } - module type_identity { private header "__type_traits/type_identity.h" } - module type_list { private header "__type_traits/type_list.h" } - module underlying_type { private header "__type_traits/underlying_type.h" } - module void_t { private header "__type_traits/void_t.h" } - } - module typeindex { - header "typeindex" - export * - } - module typeinfo { - header "typeinfo" - export * - } - module unordered_map { - header "unordered_map" - export initializer_list - export * - } - module unordered_set { - header "unordered_set" - export initializer_list - export * - } - module utility { - header "utility" - export initializer_list - export * +module std_private_functional_binary_function [system] { header "__functional/binary_function.h" } +module std_private_functional_binary_negate [system] { header "__functional/binary_negate.h" } +module std_private_functional_bind [system] { header "__functional/bind.h" } +module std_private_functional_bind_back [system] { header "__functional/bind_back.h" } +module std_private_functional_bind_front [system] { header "__functional/bind_front.h" } +module std_private_functional_binder1st [system] { header "__functional/binder1st.h" } +module std_private_functional_binder2nd [system] { header "__functional/binder2nd.h" } +module std_private_functional_boyer_moore_searcher [system] { + header "__functional/boyer_moore_searcher.h" + export std_private_memory_shared_ptr +} +module std_private_functional_compose [system] { + header "__functional/compose.h" + export std_private_functional_perfect_forward +} +module std_private_functional_default_searcher [system] { header "__functional/default_searcher.h" } +module std_private_functional_function [system] { header "__functional/function.h" } +module std_private_functional_hash [system] { + header "__functional/hash.h" + export std_cstdint + export std_private_type_traits_underlying_type + export std_private_utility_pair +} +module std_private_functional_hash_fwd [system] { header "__fwd/hash.h" } +module std_private_functional_identity [system] { header "__functional/identity.h" } +module std_private_functional_invoke [system] { + header "__functional/invoke.h" + export * +} +module std_private_functional_is_transparent [system] { header "__functional/is_transparent.h" } +module std_private_functional_mem_fn [system] { header "__functional/mem_fn.h" } +module std_private_functional_mem_fun_ref [system] { header "__functional/mem_fun_ref.h" } +module std_private_functional_not_fn [system] { header "__functional/not_fn.h" } +module std_private_functional_operations [system] { header "__functional/operations.h" } +module std_private_functional_perfect_forward [system] { + header "__functional/perfect_forward.h" + export * +} +module std_private_functional_pointer_to_binary_function [system] { header "__functional/pointer_to_binary_function.h" } +module std_private_functional_pointer_to_unary_function [system] { header "__functional/pointer_to_unary_function.h" } +module std_private_functional_ranges_operations [system] { header "__functional/ranges_operations.h" } +module std_private_functional_reference_wrapper [system] { header "__functional/reference_wrapper.h" } +module std_private_functional_unary_function [system] { header "__functional/unary_function.h" } +module std_private_functional_unary_negate [system] { header "__functional/unary_negate.h" } +module std_private_functional_weak_result_type [system] { header "__functional/weak_result_type.h" } - module __utility { - module as_const { private header "__utility/as_const.h" } - module auto_cast { private header "__utility/auto_cast.h" } - module cmp { private header "__utility/cmp.h" } - module convert_to_integral { private header "__utility/convert_to_integral.h" } - module declval { private header "__utility/declval.h" } - module exception_guard { private header "__utility/exception_guard.h" } - module exchange { private header "__utility/exchange.h" } - module forward { private header "__utility/forward.h" } - module forward_like { private header "__utility/forward_like.h" } - module in_place { private header "__utility/in_place.h" } - module integer_sequence { private header "__utility/integer_sequence.h" } - module move { private header "__utility/move.h" } - module pair { private header "__utility/pair.h" } - module pair_fwd { private header "__fwd/pair.h" } - module piecewise_construct { private header "__utility/piecewise_construct.h" } - module priority_tag { private header "__utility/priority_tag.h" } - module rel_ops { private header "__utility/rel_ops.h" } - module swap { private header "__utility/swap.h" } - module to_underlying { private header "__utility/to_underlying.h" } - module unreachable { private header "__utility/unreachable.h" } - } - } - module valarray { - header "valarray" - export initializer_list - export * - } - module variant { - header "variant" - export * +module std_private_ios_fpos [system] { header "__ios/fpos.h" } - module __variant { - module monostate { private header "__variant/monostate.h" } - } - } - module vector { - header "vector" - export initializer_list - export * - } - module version { - header "version" - export * - } +module std_private_iosfwd_fstream_fwd [system] { header "__fwd/fstream.h" } +module std_private_iosfwd_ios_fwd [system] { header "__fwd/ios.h" } +module std_private_iosfwd_istream_fwd [system] { header "__fwd/istream.h" } +module std_private_iosfwd_ostream_fwd [system] { header "__fwd/ostream.h" } +module std_private_iosfwd_sstream_fwd [system] { header "__fwd/sstream.h" } +module std_private_iosfwd_streambuf_fwd [system] { header "__fwd/streambuf.h" } - // FIXME: These should be private. - module __assert { header "__assert" export * } - module __availability { private header "__availability" export * } - module __bit_reference { private header "__bit_reference" export * } - module __debug { header "__debug" export * } - module __errc { private header "__errc" export * } - module __hash_table { header "__hash_table" export * } - module __locale { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - private header "__locale" export * - } - module __mbstate_t { private header "__mbstate_t.h" export * } - module __mutex_base { private header "__mutex_base" export * } - module __node_handle { private header "__node_handle" export * } - module __split_buffer { private header "__split_buffer" export * } - module __std_stream { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - private header "__std_stream" export * - } - module __threading_support { header "__threading_support" export * } - module __tree { header "__tree" export * } - module __undef_macros { header "__undef_macros" export * } - module __verbose_abort { header "__verbose_abort" export * } +module std_private_iterator_access [system] { header "__iterator/access.h" } +module std_private_iterator_advance [system] { header "__iterator/advance.h" } +module std_private_iterator_back_insert_iterator [system] { header "__iterator/back_insert_iterator.h" } +module std_private_iterator_bounded_iter [system] { header "__iterator/bounded_iter.h" } +module std_private_iterator_common_iterator [system] { header "__iterator/common_iterator.h" } +module std_private_iterator_concepts [system] { + header "__iterator/concepts.h" + export std_private_concepts_constructible + export std_private_concepts_equality_comparable + export std_private_concepts_movable + export std_private_type_traits_common_reference + export std_private_type_traits_is_reference + export std_private_type_traits_remove_cvref +} +module std_private_iterator_counted_iterator [system] { header "__iterator/counted_iterator.h" } +module std_private_iterator_cpp17_iterator_concepts [system] { header "__iterator/cpp17_iterator_concepts.h" } +module std_private_iterator_data [system] { header "__iterator/data.h" } +module std_private_iterator_default_sentinel [system] { header "__iterator/default_sentinel.h" } +module std_private_iterator_distance [system] { + header "__iterator/distance.h" + export std_private_ranges_size +} +module std_private_iterator_empty [system] { header "__iterator/empty.h" } +module std_private_iterator_erase_if_container [system] { header "__iterator/erase_if_container.h" } +module std_private_iterator_front_insert_iterator [system] { header "__iterator/front_insert_iterator.h" } +module std_private_iterator_incrementable_traits [system] { header "__iterator/incrementable_traits.h" } +module std_private_iterator_indirectly_comparable [system] { header "__iterator/indirectly_comparable.h" } +module std_private_iterator_insert_iterator [system] { header "__iterator/insert_iterator.h" } +module std_private_iterator_istream_iterator [system] { header "__iterator/istream_iterator.h" } +module std_private_iterator_istreambuf_iterator [system] { header "__iterator/istreambuf_iterator.h" } +module std_private_iterator_iter_move [system] { header "__iterator/iter_move.h" } +module std_private_iterator_iter_swap [system] { header "__iterator/iter_swap.h" } +module std_private_iterator_iterator [system] { header "__iterator/iterator.h" } +module std_private_iterator_iterator_traits [system] { + header "__iterator/iterator_traits.h" + export std_private_type_traits_is_primary_template +} +module std_private_iterator_iterator_with_data [system] { header "__iterator/iterator_with_data.h" } +module std_private_iterator_mergeable [system] { + header "__iterator/mergeable.h" + export std_private_functional_ranges_operations +} +module std_private_iterator_move_iterator [system] { header "__iterator/move_iterator.h" } +module std_private_iterator_move_sentinel [system] { header "__iterator/move_sentinel.h" } +module std_private_iterator_next [system] { header "__iterator/next.h" } +module std_private_iterator_ostream_iterator [system] { header "__iterator/ostream_iterator.h" } +module std_private_iterator_ostreambuf_iterator [system] { + header "__iterator/ostreambuf_iterator.h" + export * +} +module std_private_iterator_permutable [system] { header "__iterator/permutable.h" } +module std_private_iterator_prev [system] { header "__iterator/prev.h" } +module std_private_iterator_projected [system] { header "__iterator/projected.h" } +module std_private_iterator_ranges_iterator_traits [system] { header "__iterator/ranges_iterator_traits.h" } +module std_private_iterator_readable_traits [system] { header "__iterator/readable_traits.h" } +module std_private_iterator_reverse_access [system] { header "__iterator/reverse_access.h" } +module std_private_iterator_reverse_iterator [system] { header "__iterator/reverse_iterator.h" } +module std_private_iterator_segmented_iterator [system] { header "__iterator/segmented_iterator.h" } +module std_private_iterator_size [system] { header "__iterator/size.h" } +module std_private_iterator_sortable [system] { + header "__iterator/sortable.h" + export std_private_functional_ranges_operations +} +module std_private_iterator_unreachable_sentinel [system] { header "__iterator/unreachable_sentinel.h" } +module std_private_iterator_wrap_iter [system] { header "__iterator/wrap_iter.h" } + +module std_private_locale_locale_base_api_bsd_locale_defaults [system] { textual header "__locale_dir/locale_base_api/bsd_locale_defaults.h" } +module std_private_locale_locale_base_api_bsd_locale_fallbacks [system] { textual header "__locale_dir/locale_base_api/bsd_locale_fallbacks.h" } +module std_private_locale_locale_base_api_locale_guard [system] { header "__locale_dir/locale_base_api/locale_guard.h" } - module experimental { - requires cplusplus11 +module std_private_mdspan_default_accessor [system] { header "__mdspan/default_accessor.h" } +module std_private_mdspan_extents [system] { + header "__mdspan/extents.h" + export * +} +module std_private_mdspan_layout_left [system] { header "__mdspan/layout_left.h" } +module std_private_mdspan_layout_right [system] { header "__mdspan/layout_right.h" } +module std_private_mdspan_mdspan_fwd [system] { header "__fwd/mdspan.h" } - module algorithm { - header "experimental/algorithm" - export * - } - module coroutine { - requires coroutines - header "experimental/coroutine" - export * - } - module deque { - header "experimental/deque" - export * - } - module forward_list { - header "experimental/forward_list" - export * - } - module functional { - header "experimental/functional" - export * - } - module iterator { - header "experimental/iterator" - export * - } - module list { - header "experimental/list" - export * - } - module map { - header "experimental/map" - export * - } - module memory_resource { - header "experimental/memory_resource" - export * - } - module propagate_const { - header "experimental/propagate_const" - export * - } - module regex { - @requires_LIBCXX_ENABLE_LOCALIZATION@ - header "experimental/regex" - export * - } - module simd { - header "experimental/simd" - export * - } - module set { - header "experimental/set" - export * - } - module span { - header "span" - export * - } - module string { - header "experimental/string" - export * - } - module type_traits { - header "experimental/type_traits" - export * - } - module unordered_map { - header "experimental/unordered_map" - export * - } - module unordered_set { - header "experimental/unordered_set" - export * - } - module utility { - header "experimental/utility" - export * - } - module vector { - header "experimental/vector" - export * - } - // FIXME these should be private - module __memory { - header "experimental/__memory" - export * - } - } // end experimental +module std_private_memory_addressof [system] { header "__memory/addressof.h" } +module std_private_memory_align [system] { header "__memory/align.h" } +module std_private_memory_aligned_alloc [system] { header "__memory/aligned_alloc.h" } +module std_private_memory_allocate_at_least [system] { header "__memory/allocate_at_least.h" } +module std_private_memory_allocation_guard [system] { header "__memory/allocation_guard.h" } +module std_private_memory_allocator [system] { header "__memory/allocator.h" } +module std_private_memory_allocator_arg_t [system] { header "__memory/allocator_arg_t.h" } +module std_private_memory_allocator_destructor [system] { header "__memory/allocator_destructor.h" } +module std_private_memory_allocator_traits [system] { header "__memory/allocator_traits.h" } +module std_private_memory_assume_aligned [system] { header "__memory/assume_aligned.h" } +module std_private_memory_auto_ptr [system] { header "__memory/auto_ptr.h" } +module std_private_memory_builtin_new_allocator [system] { header "__memory/builtin_new_allocator.h" } +module std_private_memory_compressed_pair [system] { header "__memory/compressed_pair.h" } +module std_private_memory_concepts [system] { + header "__memory/concepts.h" + export std_private_type_traits_remove_reference } +module std_private_memory_construct_at [system] { header "__memory/construct_at.h" } +module std_private_memory_destruct_n [system] { header "__memory/destruct_n.h" } +module std_private_memory_pointer_traits [system] { header "__memory/pointer_traits.h" } +module std_private_memory_ranges_construct_at [system] { header "__memory/ranges_construct_at.h" } +module std_private_memory_ranges_uninitialized_algorithms [system] { + header "__memory/ranges_uninitialized_algorithms.h" + export std_private_algorithm_in_out_result +} +module std_private_memory_raw_storage_iterator [system] { header "__memory/raw_storage_iterator.h" } +module std_private_memory_shared_ptr [system] { + header "__memory/shared_ptr.h" + export std_private_memory_uninitialized_algorithms +} +module std_private_memory_swap_allocator [system] { header "__memory/swap_allocator.h" } +module std_private_memory_temp_value [system] { header "__memory/temp_value.h" } +module std_private_memory_temporary_buffer [system] { header "__memory/temporary_buffer.h" } +module std_private_memory_uninitialized_algorithms [system] { + header "__memory/uninitialized_algorithms.h" + export std_private_algorithm_copy +} +module std_private_memory_unique_ptr [system] { + header "__memory/unique_ptr.h" + export std_private_type_traits_add_lvalue_reference + export std_private_type_traits_is_pointer + export std_private_type_traits_type_identity +} +module std_private_memory_uses_allocator [system] { header "__memory/uses_allocator.h" } +module std_private_memory_uses_allocator_construction [system] { header "__memory/uses_allocator_construction.h" } +module std_private_memory_voidify [system] { header "__memory/voidify.h" } + +module std_private_memory_resource_memory_resource [system] { header "__memory_resource/memory_resource.h" } +module std_private_memory_resource_memory_resource_fwd [system] { header "__fwd/memory_resource.h" } +module std_private_memory_resource_monotonic_buffer_resource [system] { header "__memory_resource/monotonic_buffer_resource.h" } +module std_private_memory_resource_polymorphic_allocator [system] { header "__memory_resource/polymorphic_allocator.h" } +module std_private_memory_resource_pool_options [system] { header "__memory_resource/pool_options.h" } +module std_private_memory_resource_synchronized_pool_resource [system] { + header "__memory_resource/synchronized_pool_resource.h" + export * +} +module std_private_memory_resource_unsynchronized_pool_resource [system] { header "__memory_resource/unsynchronized_pool_resource.h" } + +module std_private_mutex_lock_guard [system] { header "__mutex/lock_guard.h" } +module std_private_mutex_mutex [system] { header "__mutex/mutex.h" } +module std_private_mutex_tag_types [system] { header "__mutex/tag_types.h" } +module std_private_mutex_unique_lock [system] { header "__mutex/unique_lock.h" } + +module std_private_numeric_accumulate [system] { header "__numeric/accumulate.h" } +module std_private_numeric_adjacent_difference [system] { header "__numeric/adjacent_difference.h" } +module std_private_numeric_exclusive_scan [system] { header "__numeric/exclusive_scan.h" } +module std_private_numeric_gcd_lcm [system] { header "__numeric/gcd_lcm.h" } +module std_private_numeric_inclusive_scan [system] { header "__numeric/inclusive_scan.h" } +module std_private_numeric_inner_product [system] { header "__numeric/inner_product.h" } +module std_private_numeric_iota [system] { header "__numeric/iota.h" } +module std_private_numeric_midpoint [system] { header "__numeric/midpoint.h" } +module std_private_numeric_partial_sum [system] { header "__numeric/partial_sum.h" } +module std_private_numeric_pstl_reduce [system] { header "__numeric/pstl_reduce.h" } +module std_private_numeric_pstl_transform_reduce [system] { + header "__numeric/pstl_transform_reduce.h" + export * +} +module std_private_numeric_reduce [system] { header "__numeric/reduce.h" } +module std_private_numeric_transform_exclusive_scan [system] { header "__numeric/transform_exclusive_scan.h" } +module std_private_numeric_transform_inclusive_scan [system] { header "__numeric/transform_inclusive_scan.h" } +module std_private_numeric_transform_reduce [system] { header "__numeric/transform_reduce.h" } + +module std_private_random_bernoulli_distribution [system] { header "__random/bernoulli_distribution.h" } +module std_private_random_binomial_distribution [system] { header "__random/binomial_distribution.h" } +module std_private_random_cauchy_distribution [system] { header "__random/cauchy_distribution.h" } +module std_private_random_chi_squared_distribution [system] { header "__random/chi_squared_distribution.h" } +module std_private_random_clamp_to_integral [system] { header "__random/clamp_to_integral.h" } +module std_private_random_default_random_engine [system] { header "__random/default_random_engine.h" } +module std_private_random_discard_block_engine [system] { header "__random/discard_block_engine.h" } +module std_private_random_discrete_distribution [system] { + header "__random/discrete_distribution.h" + export * +} +module std_private_random_exponential_distribution [system] { header "__random/exponential_distribution.h" } +module std_private_random_extreme_value_distribution [system] { header "__random/extreme_value_distribution.h" } +module std_private_random_fisher_f_distribution [system] { header "__random/fisher_f_distribution.h" } +module std_private_random_gamma_distribution [system] { header "__random/gamma_distribution.h" } +module std_private_random_generate_canonical [system] { header "__random/generate_canonical.h" } +module std_private_random_geometric_distribution [system] { header "__random/geometric_distribution.h" } +module std_private_random_independent_bits_engine [system] { header "__random/independent_bits_engine.h" } +module std_private_random_is_seed_sequence [system] { header "__random/is_seed_sequence.h" } +module std_private_random_is_valid [system] { header "__random/is_valid.h" } +module std_private_random_knuth_b [system] { header "__random/knuth_b.h" } +module std_private_random_linear_congruential_engine [system] { header "__random/linear_congruential_engine.h" } +module std_private_random_log2 [system] { header "__random/log2.h" } +module std_private_random_lognormal_distribution [system] { header "__random/lognormal_distribution.h" } +module std_private_random_mersenne_twister_engine [system] { header "__random/mersenne_twister_engine.h" } +module std_private_random_negative_binomial_distribution [system] { header "__random/negative_binomial_distribution.h" } +module std_private_random_normal_distribution [system] { header "__random/normal_distribution.h" } +module std_private_random_piecewise_constant_distribution [system] { + header "__random/piecewise_constant_distribution.h" + export * +} +module std_private_random_piecewise_linear_distribution [system] { + header "__random/piecewise_linear_distribution.h" + export * +} +module std_private_random_poisson_distribution [system] { header "__random/poisson_distribution.h" } +module std_private_random_random_device [system] { header "__random/random_device.h" } +module std_private_random_ranlux [system] { header "__random/ranlux.h" } +module std_private_random_seed_seq [system] { header "__random/seed_seq.h" } +module std_private_random_shuffle_order_engine [system] { header "__random/shuffle_order_engine.h" } +module std_private_random_student_t_distribution [system] { header "__random/student_t_distribution.h" } +module std_private_random_subtract_with_carry_engine [system] { header "__random/subtract_with_carry_engine.h" } +module std_private_random_uniform_int_distribution [system] { header "__random/uniform_int_distribution.h" } +module std_private_random_uniform_random_bit_generator [system] { header "__random/uniform_random_bit_generator.h" } +module std_private_random_uniform_real_distribution [system] { header "__random/uniform_real_distribution.h" } +module std_private_random_weibull_distribution [system] { header "__random/weibull_distribution.h" } + +module std_private_ranges_access [system] { header "__ranges/access.h" } +module std_private_ranges_all [system] { + header "__ranges/all.h" + export std_private_functional_compose + export std_private_functional_perfect_forward + export std_private_ranges_owning_view +} +module std_private_ranges_as_rvalue_view [system] { header "__ranges/as_rvalue_view.h" } +module std_private_ranges_common_view [system] { header "__ranges/common_view.h" } +module std_private_ranges_concepts [system] { + header "__ranges/concepts.h" + export std_private_iterator_concepts +} +module std_private_ranges_container_compatible_range [system] { header "__ranges/container_compatible_range.h" } +module std_private_ranges_counted [system] { + header "__ranges/counted.h" + export std_span +} +module std_private_ranges_dangling [system] { header "__ranges/dangling.h" } +module std_private_ranges_data [system] { header "__ranges/data.h" } +module std_private_ranges_drop_view [system] { header "__ranges/drop_view.h" } +module std_private_ranges_drop_while_view [system] { header "__ranges/drop_while_view.h" } +module std_private_ranges_elements_view [system] { header "__ranges/elements_view.h" } +module std_private_ranges_empty [system] { header "__ranges/empty.h" } +module std_private_ranges_empty_view [system] { header "__ranges/empty_view.h" } +module std_private_ranges_enable_borrowed_range [system] { header "__ranges/enable_borrowed_range.h" } +module std_private_ranges_enable_view [system] { header "__ranges/enable_view.h" } +module std_private_ranges_filter_view [system] { + header "__ranges/filter_view.h" + export std_private_ranges_range_adaptor +} +module std_private_ranges_from_range [system] { header "__ranges/from_range.h" } +module std_private_ranges_iota_view [system] { header "__ranges/iota_view.h" } +module std_private_ranges_istream_view [system] { + @requires_LIBCXX_ENABLE_LOCALIZATION@ + header "__ranges/istream_view.h" +} +module std_private_ranges_join_view [system] { + header "__ranges/join_view.h" + export std_private_iterator_iterator_with_data + export std_private_iterator_segmented_iterator +} +module std_private_ranges_lazy_split_view [system] { + header "__ranges/lazy_split_view.h" + export std_private_ranges_non_propagating_cache +} +module std_private_ranges_movable_box [system] { header "__ranges/movable_box.h" } +module std_private_ranges_non_propagating_cache [system] { header "__ranges/non_propagating_cache.h" } +module std_private_ranges_owning_view [system] { header "__ranges/owning_view.h" } +module std_private_ranges_range_adaptor [system] { header "__ranges/range_adaptor.h" } +module std_private_ranges_rbegin [system] { header "__ranges/rbegin.h" } +module std_private_ranges_ref_view [system] { header "__ranges/ref_view.h" } +module std_private_ranges_rend [system] { header "__ranges/rend.h" } +module std_private_ranges_repeat_view [system] { header "__ranges/repeat_view.h" } +module std_private_ranges_reverse_view [system] { header "__ranges/reverse_view.h" } +module std_private_ranges_single_view [system] { header "__ranges/single_view.h" } +module std_private_ranges_size [system] { + header "__ranges/size.h" + export std_private_type_traits_make_unsigned +} +module std_private_ranges_split_view [system] { header "__ranges/split_view.h" } +module std_private_ranges_subrange [system] { + header "__ranges/subrange.h" + export std_private_ranges_subrange_fwd +} +module std_private_ranges_subrange_fwd [system] { + header "__fwd/subrange.h" + export std_private_iterator_concepts +} +module std_private_ranges_take_view [system] { header "__ranges/take_view.h" } +module std_private_ranges_take_while_view [system] { header "__ranges/take_while_view.h" } +module std_private_ranges_to [system] { header "__ranges/to.h" } +module std_private_ranges_transform_view [system] { + header "__ranges/transform_view.h" + export std_private_functional_bind_back + export std_private_functional_perfect_forward + export std_private_ranges_movable_box +} +module std_private_ranges_view_interface [system] { header "__ranges/view_interface.h" } +module std_private_ranges_views [system] { header "__ranges/views.h" } +module std_private_ranges_zip_view [system] { header "__ranges/zip_view.h" } + +module std_private_span_span_fwd [system] { header "__fwd/span.h" } + +module std_private_stop_token_atomic_unique_lock [system] { header "__stop_token/atomic_unique_lock.h" } +module std_private_stop_token_intrusive_list_view [system] { header "__stop_token/intrusive_list_view.h" } +module std_private_stop_token_intrusive_shared_ptr [system] { header "__stop_token/intrusive_shared_ptr.h" } +module std_private_stop_token_stop_callback [system] { header "__stop_token/stop_callback.h" } +module std_private_stop_token_stop_source [system] { + header "__stop_token/stop_source.h" + export * +} +module std_private_stop_token_stop_state [system] { + header "__stop_token/stop_state.h" + export * +} +module std_private_stop_token_stop_token [system] { + header "__stop_token/stop_token.h" + export * +} + +module std_private_string_char_traits [system] { header "__string/char_traits.h" } +module std_private_string_constexpr_c_functions [system] { + header "__string/constexpr_c_functions.h" + export std_private_type_traits_is_equality_comparable +} +module std_private_string_extern_template_lists [system] { header "__string/extern_template_lists.h" } +module std_private_string_string_fwd [system] { header "__fwd/string.h" } + +module std_private_string_view_string_view_fwd [system] { header "__fwd/string_view.h" } + +module std_private_system_error_errc [system] { header "__system_error/errc.h" } +module std_private_system_error_error_category [system] { header "__system_error/error_category.h" } +module std_private_system_error_error_code [system] { + header "__system_error/error_code.h" + export std_private_functional_hash + export std_private_functional_unary_function +} +module std_private_system_error_error_condition [system] { + header "__system_error/error_condition.h" + export std_private_functional_hash + export std_private_functional_unary_function +} +module std_private_system_error_system_error [system] { header "__system_error/system_error.h" } + +module std_private_thread_formatter [system] { header "__thread/formatter.h" } +module std_private_thread_id [system] { header "__thread/id.h" } +module std_private_thread_poll_with_backoff [system] { header "__thread/poll_with_backoff.h" } +module std_private_thread_this_thread [system] { header "__thread/this_thread.h" } +module std_private_thread_thread [system] { + header "__thread/thread.h" + export * +} +module std_private_thread_timed_backoff_policy [system] { header "__thread/timed_backoff_policy.h" } + +module std_private_tuple_get_fwd [system] { header "__fwd/get.h" } +module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" } +module std_private_tuple_pair_like [system] { + header "__tuple/pair_like.h" + export std_private_tuple_tuple_like +} +module std_private_tuple_sfinae_helpers [system] { header "__tuple/sfinae_helpers.h" } +module std_private_tuple_tuple_element [system] { header "__tuple/tuple_element.h" } +module std_private_tuple_tuple_fwd [system] { header "__fwd/tuple.h" } +module std_private_tuple_tuple_indices [system] { header "__tuple/tuple_indices.h" } +module std_private_tuple_tuple_like [system] { header "__tuple/tuple_like.h" } +module std_private_tuple_tuple_like_ext [system] { header "__tuple/tuple_like_ext.h" } +module std_private_tuple_tuple_size [system] { header "__tuple/tuple_size.h" } +module std_private_tuple_tuple_types [system] { header "__tuple/tuple_types.h" } + +module std_private_type_traits_add_const [system] { header "__type_traits/add_const.h" } +module std_private_type_traits_add_cv [system] { header "__type_traits/add_cv.h" } +module std_private_type_traits_add_lvalue_reference [system] { + header "__type_traits/add_lvalue_reference.h" + export std_private_type_traits_is_referenceable +} +module std_private_type_traits_add_pointer [system] { header "__type_traits/add_pointer.h" } +module std_private_type_traits_add_rvalue_reference [system] { header "__type_traits/add_rvalue_reference.h" } +module std_private_type_traits_add_volatile [system] { header "__type_traits/add_volatile.h" } +module std_private_type_traits_aligned_storage [system] { header "__type_traits/aligned_storage.h" } +module std_private_type_traits_aligned_union [system] { header "__type_traits/aligned_union.h" } +module std_private_type_traits_alignment_of [system] { header "__type_traits/alignment_of.h" } +module std_private_type_traits_apply_cv [system] { + header "__type_traits/apply_cv.h" + export std_private_type_traits_is_const + export std_private_type_traits_is_volatile +} +module std_private_type_traits_can_extract_key [system] { header "__type_traits/can_extract_key.h" } +module std_private_type_traits_common_reference [system] { + header "__type_traits/common_reference.h" + export std_private_type_traits_remove_cvref +} +module std_private_type_traits_common_type [system] { + header "__type_traits/common_type.h" + export std_private_utility_declval +} +module std_private_type_traits_conditional [system] { header "__type_traits/conditional.h" } +module std_private_type_traits_conjunction [system] { header "__type_traits/conjunction.h" } +module std_private_type_traits_copy_cv [system] { header "__type_traits/copy_cv.h" } +module std_private_type_traits_copy_cvref [system] { header "__type_traits/copy_cvref.h" } +module std_private_type_traits_datasizeof [system] { header "__type_traits/datasizeof.h" } +module std_private_type_traits_decay [system] { + header "__type_traits/decay.h" + export std_private_type_traits_add_pointer +} +module std_private_type_traits_dependent_type [system] { header "__type_traits/dependent_type.h" } +module std_private_type_traits_disjunction [system] { header "__type_traits/disjunction.h" } +module std_private_type_traits_enable_if [system] { header "__type_traits/enable_if.h" } +module std_private_type_traits_extent [system] { header "__type_traits/extent.h" } +module std_private_type_traits_has_unique_object_representation [system] { header "__type_traits/has_unique_object_representation.h" } +module std_private_type_traits_has_virtual_destructor [system] { header "__type_traits/has_virtual_destructor.h" } +module std_private_type_traits_integral_constant [system] { header "__type_traits/integral_constant.h" } +module std_private_type_traits_invoke [system] { + header "__type_traits/invoke.h" + export std_private_type_traits_conditional + export std_private_type_traits_decay + export std_private_type_traits_decay + export std_private_type_traits_enable_if + export std_private_type_traits_is_base_of + export std_private_type_traits_is_core_convertible + export std_private_type_traits_is_reference_wrapper + export std_private_type_traits_is_same + export std_private_type_traits_is_void + export std_private_type_traits_nat + export std_private_type_traits_remove_cv +} +module std_private_type_traits_is_abstract [system] { header "__type_traits/is_abstract.h" } +module std_private_type_traits_is_aggregate [system] { header "__type_traits/is_aggregate.h" } +module std_private_type_traits_is_allocator [system] { header "__type_traits/is_allocator.h" } +module std_private_type_traits_is_always_bitcastable [system] { header "__type_traits/is_always_bitcastable.h" } +module std_private_type_traits_is_arithmetic [system] { + header "__type_traits/is_arithmetic.h" + export std_private_type_traits_integral_constant +} +module std_private_type_traits_is_array [system] { + header "__type_traits/is_array.h" + export std_private_type_traits_integral_constant +} +module std_private_type_traits_is_assignable [system] { header "__type_traits/is_assignable.h" } +module std_private_type_traits_is_base_of [system] { header "__type_traits/is_base_of.h" } +module std_private_type_traits_is_bounded_array [system] { header "__type_traits/is_bounded_array.h" } +module std_private_type_traits_is_callable [system] { header "__type_traits/is_callable.h" } +module std_private_type_traits_is_char_like_type [system] { header "__type_traits/is_char_like_type.h" } +module std_private_type_traits_is_class [system] { header "__type_traits/is_class.h" } +module std_private_type_traits_is_compound [system] { header "__type_traits/is_compound.h" } +module std_private_type_traits_is_const [system] { header "__type_traits/is_const.h" } +module std_private_type_traits_is_constant_evaluated [system] { header "__type_traits/is_constant_evaluated.h" } +module std_private_type_traits_is_constructible [system] { header "__type_traits/is_constructible.h" } +module std_private_type_traits_is_convertible [system] { + header "__type_traits/is_convertible.h" + export std_private_type_traits_is_array +} +module std_private_type_traits_is_copy_assignable [system] { header "__type_traits/is_copy_assignable.h" } +module std_private_type_traits_is_copy_constructible [system] { header "__type_traits/is_copy_constructible.h" } +module std_private_type_traits_is_core_convertible [system] { + header "__type_traits/is_core_convertible.h" + export std_private_type_traits_integral_constant +} +module std_private_type_traits_is_default_constructible [system] { header "__type_traits/is_default_constructible.h" } +module std_private_type_traits_is_destructible [system] { header "__type_traits/is_destructible.h" } +module std_private_type_traits_is_empty [system] { header "__type_traits/is_empty.h" } +module std_private_type_traits_is_enum [system] { + header "__type_traits/is_enum.h" + export std_private_type_traits_integral_constant +} +module std_private_type_traits_is_equality_comparable [system] { + header "__type_traits/is_equality_comparable.h" + export std_private_type_traits_integral_constant +} +module std_private_type_traits_is_execution_policy [system] { + header "__type_traits/is_execution_policy.h" + export std_private_type_traits_remove_cvref +} +module std_private_type_traits_is_final [system] { header "__type_traits/is_final.h" } +module std_private_type_traits_is_floating_point [system] { header "__type_traits/is_floating_point.h" } +module std_private_type_traits_is_function [system] { header "__type_traits/is_function.h" } +module std_private_type_traits_is_fundamental [system] { header "__type_traits/is_fundamental.h" } +module std_private_type_traits_is_implicitly_default_constructible [system] { header "__type_traits/is_implicitly_default_constructible.h" } +module std_private_type_traits_is_integral [system] { header "__type_traits/is_integral.h" } +module std_private_type_traits_is_literal_type [system] { header "__type_traits/is_literal_type.h" } +module std_private_type_traits_is_member_function_pointer [system] { header "__type_traits/is_member_function_pointer.h" } +module std_private_type_traits_is_member_object_pointer [system] { header "__type_traits/is_member_object_pointer.h" } +module std_private_type_traits_is_member_pointer [system] { header "__type_traits/is_member_pointer.h" } +module std_private_type_traits_is_move_assignable [system] { header "__type_traits/is_move_assignable.h" } +module std_private_type_traits_is_move_constructible [system] { header "__type_traits/is_move_constructible.h" } +module std_private_type_traits_is_nothrow_assignable [system] { header "__type_traits/is_nothrow_assignable.h" } +module std_private_type_traits_is_nothrow_constructible [system] { header "__type_traits/is_nothrow_constructible.h" } +module std_private_type_traits_is_nothrow_convertible [system] { header "__type_traits/is_nothrow_convertible.h" } +module std_private_type_traits_is_nothrow_copy_assignable [system] { header "__type_traits/is_nothrow_copy_assignable.h" } +module std_private_type_traits_is_nothrow_copy_constructible [system] { header "__type_traits/is_nothrow_copy_constructible.h" } +module std_private_type_traits_is_nothrow_default_constructible [system] { header "__type_traits/is_nothrow_default_constructible.h" } +module std_private_type_traits_is_nothrow_destructible [system] { + header "__type_traits/is_nothrow_destructible.h" + export std_private_type_traits_is_destructible +} +module std_private_type_traits_is_nothrow_move_assignable [system] { header "__type_traits/is_nothrow_move_assignable.h" } +module std_private_type_traits_is_nothrow_move_constructible [system] { + header "__type_traits/is_nothrow_move_constructible.h" + export std_private_type_traits_is_nothrow_constructible +} +module std_private_type_traits_is_null_pointer [system] { + header "__type_traits/is_null_pointer.h" + export std_cstddef +} +module std_private_type_traits_is_object [system] { + header "__type_traits/is_object.h" + export std_private_type_traits_is_scalar +} +module std_private_type_traits_is_pod [system] { header "__type_traits/is_pod.h" } +module std_private_type_traits_is_pointer [system] { header "__type_traits/is_pointer.h" } +module std_private_type_traits_is_polymorphic [system] { header "__type_traits/is_polymorphic.h" } +module std_private_type_traits_is_primary_template [system] { + header "__type_traits/is_primary_template.h" + export std_private_type_traits_enable_if +} +module std_private_type_traits_is_reference [system] { header "__type_traits/is_reference.h" } +module std_private_type_traits_is_reference_wrapper [system] { header "__type_traits/is_reference_wrapper.h" } +module std_private_type_traits_is_referenceable [system] { header "__type_traits/is_referenceable.h" } +module std_private_type_traits_is_same [system] { + header "__type_traits/is_same.h" + export std_private_type_traits_integral_constant +} +module std_private_type_traits_is_scalar [system] { + header "__type_traits/is_scalar.h" + export std_private_type_traits_is_null_pointer +} +module std_private_type_traits_is_scoped_enum [system] { header "__type_traits/is_scoped_enum.h" } +module std_private_type_traits_is_signed [system] { header "__type_traits/is_signed.h" } +module std_private_type_traits_is_signed_integer [system] { header "__type_traits/is_signed_integer.h" } +module std_private_type_traits_is_specialization [system] { header "__type_traits/is_specialization.h" } +module std_private_type_traits_is_standard_layout [system] { header "__type_traits/is_standard_layout.h" } +module std_private_type_traits_is_swappable [system] { + header "__type_traits/is_swappable.h" + export std_private_type_traits_is_move_constructible +} +module std_private_type_traits_is_trivial [system] { header "__type_traits/is_trivial.h" } +module std_private_type_traits_is_trivially_assignable [system] { header "__type_traits/is_trivially_assignable.h" } +module std_private_type_traits_is_trivially_constructible [system] { header "__type_traits/is_trivially_constructible.h" } +module std_private_type_traits_is_trivially_copy_assignable [system] { header "__type_traits/is_trivially_copy_assignable.h" } +module std_private_type_traits_is_trivially_copy_constructible [system] { header "__type_traits/is_trivially_copy_constructible.h" } +module std_private_type_traits_is_trivially_copyable [system] { header "__type_traits/is_trivially_copyable.h" } +module std_private_type_traits_is_trivially_default_constructible [system] { header "__type_traits/is_trivially_default_constructible.h" } +module std_private_type_traits_is_trivially_destructible [system] { header "__type_traits/is_trivially_destructible.h" } +module std_private_type_traits_is_trivially_lexicographically_comparable [system] { header "__type_traits/is_trivially_lexicographically_comparable.h" } +module std_private_type_traits_is_trivially_move_assignable [system] { header "__type_traits/is_trivially_move_assignable.h" } +module std_private_type_traits_is_trivially_move_constructible [system] { header "__type_traits/is_trivially_move_constructible.h" } +module std_private_type_traits_is_unbounded_array [system] { header "__type_traits/is_unbounded_array.h" } +module std_private_type_traits_is_union [system] { header "__type_traits/is_union.h" } +module std_private_type_traits_is_unsigned [system] { header "__type_traits/is_unsigned.h" } +module std_private_type_traits_is_unsigned_integer [system] { header "__type_traits/is_unsigned_integer.h" } +module std_private_type_traits_is_valid_expansion [system] { header "__type_traits/is_valid_expansion.h" } +module std_private_type_traits_is_void [system] { + header "__type_traits/is_void.h" + export std_private_type_traits_integral_constant +} +module std_private_type_traits_is_volatile [system] { header "__type_traits/is_volatile.h" } +module std_private_type_traits_lazy [system] { header "__type_traits/lazy.h" } +module std_private_type_traits_make_32_64_or_128_bit [system] { header "__type_traits/make_32_64_or_128_bit.h" } +module std_private_type_traits_make_const_lvalue_ref [system] { header "__type_traits/make_const_lvalue_ref.h" } +module std_private_type_traits_make_signed [system] { header "__type_traits/make_signed.h" } +module std_private_type_traits_make_unsigned [system] { + header "__type_traits/make_unsigned.h" + export std_private_type_traits_is_unsigned +} +module std_private_type_traits_maybe_const [system] { header "__type_traits/maybe_const.h" } +module std_private_type_traits_nat [system] { header "__type_traits/nat.h" } +module std_private_type_traits_negation [system] { header "__type_traits/negation.h" } +module std_private_type_traits_noexcept_move_assign_container [system] { header "__type_traits/noexcept_move_assign_container.h" } +module std_private_type_traits_operation_traits [system] { header "__type_traits/operation_traits.h" } +module std_private_type_traits_predicate_traits [system] { header "__type_traits/predicate_traits.h" } +module std_private_type_traits_promote [system] { header "__type_traits/promote.h" } +module std_private_type_traits_rank [system] { header "__type_traits/rank.h" } +module std_private_type_traits_remove_all_extents [system] { header "__type_traits/remove_all_extents.h" } +module std_private_type_traits_remove_const [system] { header "__type_traits/remove_const.h" } +module std_private_type_traits_remove_const_ref [system] { header "__type_traits/remove_const_ref.h" } +module std_private_type_traits_remove_cv [system] { + header "__type_traits/remove_cv.h" + export std_private_type_traits_remove_const + export std_private_type_traits_remove_volatile +} +module std_private_type_traits_remove_cvref [system] { header "__type_traits/remove_cvref.h" } +module std_private_type_traits_remove_extent [system] { header "__type_traits/remove_extent.h" } +module std_private_type_traits_remove_pointer [system] { header "__type_traits/remove_pointer.h" } +module std_private_type_traits_remove_reference [system] { header "__type_traits/remove_reference.h" } +module std_private_type_traits_remove_volatile [system] { header "__type_traits/remove_volatile.h" } +module std_private_type_traits_result_of [system] { header "__type_traits/result_of.h" } +module std_private_type_traits_strip_signature [system] { header "__type_traits/strip_signature.h" } +module std_private_type_traits_type_identity [system] { header "__type_traits/type_identity.h" } +module std_private_type_traits_type_list [system] { header "__type_traits/type_list.h" } +module std_private_type_traits_underlying_type [system] { + header "__type_traits/underlying_type.h" + export std_private_type_traits_is_enum +} +module std_private_type_traits_unwrap_ref [system] { header "__type_traits/unwrap_ref.h" } +module std_private_type_traits_void_t [system] { header "__type_traits/void_t.h" } + +module std_private_utility_as_const [system] { header "__utility/as_const.h" } +module std_private_utility_auto_cast [system] { + header "__utility/auto_cast.h" + export std_private_type_traits_decay +} +module std_private_utility_cmp [system] { + header "__utility/cmp.h" + export std_private_type_traits_make_unsigned +} +module std_private_utility_convert_to_integral [system] { header "__utility/convert_to_integral.h" } +module std_private_utility_declval [system] { header "__utility/declval.h" } +module std_private_utility_exception_guard [system] { header "__utility/exception_guard.h" } +module std_private_utility_exchange [system] { header "__utility/exchange.h" } +module std_private_utility_forward [system] { header "__utility/forward.h" } +module std_private_utility_forward_like [system] { header "__utility/forward_like.h" } +module std_private_utility_in_place [system] { header "__utility/in_place.h" } +module std_private_utility_integer_sequence [system] { header "__utility/integer_sequence.h" } +module std_private_utility_is_pointer_in_range [system] { header "__utility/is_pointer_in_range.h" } +module std_private_utility_move [system] { + header "__utility/move.h" + export std_private_type_traits_is_copy_constructible + export std_private_type_traits_is_nothrow_move_constructible + export std_private_type_traits_remove_reference +} +module std_private_utility_pair [system] { + header "__utility/pair.h" + export std_private_ranges_subrange_fwd + export std_private_tuple_pair_like + export std_private_type_traits_is_assignable + export std_private_type_traits_is_constructible + export std_private_type_traits_is_convertible + export std_private_type_traits_is_copy_assignable + export std_private_type_traits_is_move_assignable + export std_private_type_traits_is_nothrow_copy_constructible + export std_private_type_traits_is_nothrow_default_constructible + export std_private_type_traits_is_nothrow_move_assignable + export std_private_utility_pair_fwd +} +module std_private_utility_pair_fwd [system] { header "__fwd/pair.h" } +module std_private_utility_piecewise_construct [system] { header "__utility/piecewise_construct.h" } +module std_private_utility_priority_tag [system] { header "__utility/priority_tag.h" } +module std_private_utility_rel_ops [system] { header "__utility/rel_ops.h" } +module std_private_utility_swap [system] { + header "__utility/swap.h" + export std_private_type_traits_is_swappable +} +module std_private_utility_terminate_on_exception [system] { header "__utility/terminate_on_exception.h" } +module std_private_utility_to_underlying [system] { header "__utility/to_underlying.h" } +module std_private_utility_unreachable [system] { header "__utility/unreachable.h" } + +module std_private_variant_monostate [system] { header "__variant/monostate.h" } diff --git a/libcxx/include/mutex b/libcxx/include/mutex index d93fba8f801c..320899a9e3ff 100644 --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -187,12 +187,20 @@ template<class Callable, class ...Args> */ #include <__assert> // all public C++ headers provide the assertion handler +#include <__chrono/steady_clock.h> +#include <__chrono/time_point.h> +#include <__condition_variable/condition_variable.h> #include <__config> #include <__memory/shared_ptr.h> -#include <__mutex_base> +#include <__mutex/lock_guard.h> +#include <__mutex/mutex.h> +#include <__mutex/tag_types.h> +#include <__mutex/unique_lock.h> +#include <__thread/id.h> #include <__threading_support> #include <__utility/forward.h> #include <cstdint> +#include <limits> #ifndef _LIBCPP_CXX03_LANG # include <tuple> #endif @@ -210,7 +218,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_HAS_NO_THREADS -class _LIBCPP_TYPE_VIS recursive_mutex +class _LIBCPP_EXPORTED_FROM_ABI recursive_mutex { __libcpp_recursive_mutex_t __m_; @@ -231,7 +239,7 @@ public: native_handle_type native_handle() {return &__m_;} }; -class _LIBCPP_TYPE_VIS timed_mutex +class _LIBCPP_EXPORTED_FROM_ABI timed_mutex { mutex __m_; condition_variable __cv_; @@ -262,9 +270,9 @@ timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; unique_lock<mutex> __lk(__m_); - bool no_timeout = _Clock::now() < __t; - while (no_timeout && __locked_) - no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; + bool __no_timeout = _Clock::now() < __t; + while (__no_timeout && __locked_) + __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; if (!__locked_) { __locked_ = true; @@ -273,7 +281,7 @@ timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) return false; } -class _LIBCPP_TYPE_VIS recursive_timed_mutex +class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex { mutex __m_; condition_variable __cv_; @@ -304,7 +312,7 @@ recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration { using namespace chrono; __thread_id __id = this_thread::get_id(); - unique_lock<mutex> lk(__m_); + unique_lock<mutex> __lk(__m_); if (__id == __id_) { if (__count_ == numeric_limits<size_t>::max()) @@ -312,9 +320,9 @@ recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration ++__count_; return true; } - bool no_timeout = _Clock::now() < __t; - while (no_timeout && __count_ != 0) - no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; + bool __no_timeout = _Clock::now() < __t; + while (__no_timeout && __count_ != 0) + __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; if (__count_ == 0) { __count_ = 1; @@ -328,7 +336,7 @@ template <class _L0, class _L1> _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) { - unique_lock<_L0> __u0(__l0, try_to_lock); + unique_lock<_L0> __u0(__l0, try_to_lock_t()); if (__u0.owns_lock()) { if (__l1.try_lock()) @@ -467,7 +475,7 @@ void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { #endif // _LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class ..._Mutexes> class _LIBCPP_TEMPLATE_VIS scoped_lock; @@ -544,7 +552,7 @@ private: }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock); -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // !_LIBCPP_HAS_NO_THREADS struct _LIBCPP_TEMPLATE_VIS once_flag; @@ -652,8 +660,7 @@ __call_once_proxy(void* __vp) (*__p)(); } -_LIBCPP_FUNC_VIS void __call_once(volatile once_flag::_State_type&, void*, - void (*)(void*)); +_LIBCPP_EXPORTED_FROM_ABI void __call_once(volatile once_flag::_State_type&, void*, void (*)(void*)); #ifndef _LIBCPP_CXX03_LANG @@ -704,9 +711,17 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <atomic> # include <concepts> -# include <functional> +# include <cstdlib> +# include <cstring> +# include <ctime> +# include <initializer_list> +# include <new> +# include <stdexcept> +# include <system_error> # include <type_traits> +# include <typeinfo> #endif #endif // _LIBCPP_MUTEX diff --git a/libcxx/include/new b/libcxx/include/new index 0c826f4a061c..3064a0e2f080 100644 --- a/libcxx/include/new +++ b/libcxx/include/new @@ -89,12 +89,14 @@ void operator delete[](void* ptr, void*) noexcept; #include <__assert> // all public C++ headers provide the assertion handler #include <__availability> #include <__config> +#include <__exception/exception.h> +#include <__type_traits/alignment_of.h> #include <__type_traits/is_function.h> #include <__type_traits/is_same.h> #include <__type_traits/remove_cv.h> +#include <__verbose_abort> #include <cstddef> #include <cstdlib> -#include <exception> #include <version> #if defined(_LIBCPP_ABI_VCRUNTIME) @@ -123,10 +125,10 @@ namespace std // purposefully not using versioning namespace { #if !defined(_LIBCPP_ABI_VCRUNTIME) -struct _LIBCPP_TYPE_VIS nothrow_t { explicit nothrow_t() = default; }; -extern _LIBCPP_FUNC_VIS const nothrow_t nothrow; +struct _LIBCPP_EXPORTED_FROM_ABI nothrow_t { explicit nothrow_t() = default; }; +extern _LIBCPP_EXPORTED_FROM_ABI const nothrow_t nothrow; -class _LIBCPP_EXCEPTION_ABI bad_alloc +class _LIBCPP_EXPORTED_FROM_ABI bad_alloc : public exception { public: @@ -135,7 +137,7 @@ public: const char* what() const _NOEXCEPT override; }; -class _LIBCPP_EXCEPTION_ABI bad_array_new_length +class _LIBCPP_EXPORTED_FROM_ABI bad_array_new_length : public bad_alloc { public: @@ -145,8 +147,8 @@ public: }; typedef void (*new_handler)(); -_LIBCPP_FUNC_VIS new_handler set_new_handler(new_handler) _NOEXCEPT; -_LIBCPP_FUNC_VIS new_handler get_new_handler() _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI new_handler set_new_handler(new_handler) _NOEXCEPT; +_LIBCPP_EXPORTED_FROM_ABI new_handler get_new_handler() _NOEXCEPT; #elif defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS == 0 // !_LIBCPP_ABI_VCRUNTIME @@ -168,15 +170,15 @@ public: }; #endif // defined(_LIBCPP_ABI_VCRUNTIME) && defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS == 0 -_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_bad_alloc(); // not in C++ spec +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_bad_alloc(); // not in C++ spec _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_array_new_length() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_array_new_length(); #else - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("bad_array_new_length was thrown in -fno-exceptions mode"); #endif } @@ -189,14 +191,14 @@ enum align_val_t { __zero = 0, __max = (size_t)-1 }; #endif #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // Enable the declaration even if the compiler doesn't support the language // feature. struct destroying_delete_t { explicit destroying_delete_t() = default; }; inline constexpr destroying_delete_t destroying_delete{}; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 } // namespace std @@ -332,46 +334,6 @@ inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate_unsized(void* __ptr, s #endif } -#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) -// Low-level helpers to call the aligned allocation and deallocation functions -// on the target platform. This is used to implement libc++'s own memory -// allocation routines -- if you need to allocate memory inside the library, -// chances are that you want to use `__libcpp_allocate` instead. -// -// Returns the allocated memory, or `nullptr` on failure. -inline _LIBCPP_INLINE_VISIBILITY void* __libcpp_aligned_alloc(std::size_t __alignment, std::size_t __size) { -# if defined(_LIBCPP_MSVCRT_LIKE) - return ::_aligned_malloc(__size, __alignment); -# elif _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_C11_ALIGNED_ALLOC) - // aligned_alloc() requires that __size is a multiple of __alignment, - // but for C++ [new.delete.general], only states "if the value of an - // alignment argument passed to any of these functions is not a valid - // alignment value, the behavior is undefined". - // To handle calls such as ::operator new(1, std::align_val_t(128)), we - // round __size up to the next multiple of __alignment. - size_t __rounded_size = (__size + __alignment - 1) & ~(__alignment - 1); - // Rounding up could have wrapped around to zero, so we have to add another - // max() ternary to the actual call site to avoid succeeded in that case. - return ::aligned_alloc(__alignment, __size > __rounded_size ? __size : __rounded_size); -# else - void* __result = nullptr; - (void)::posix_memalign(&__result, __alignment, __size); - // If posix_memalign fails, __result is unmodified so we still return `nullptr`. - return __result; -# endif -} - -inline _LIBCPP_INLINE_VISIBILITY -void __libcpp_aligned_free(void* __ptr) { -#if defined(_LIBCPP_MSVCRT_LIKE) - ::_aligned_free(__ptr); -#else - ::free(__ptr); -#endif -} -#endif // !_LIBCPP_HAS_NO_ALIGNED_ALLOCATION - - template <class _Tp> _LIBCPP_NODISCARD_AFTER_CXX17 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __launder(_Tp* __p) _NOEXCEPT @@ -381,7 +343,7 @@ _LIBCPP_CONSTEXPR _Tp* __launder(_Tp* __p) _NOEXCEPT return __builtin_launder(__p); } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> _LIBCPP_NODISCARD_AFTER_CXX17 inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp* launder(_Tp* __p) noexcept @@ -390,7 +352,7 @@ constexpr _Tp* launder(_Tp* __p) noexcept } #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 #if defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE) @@ -399,11 +361,12 @@ inline constexpr size_t hardware_constructive_interference_size = __GCC_CONSTRUC #endif // defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE) -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <exception> # include <type_traits> #endif diff --git a/libcxx/include/numbers b/libcxx/include/numbers index 72034a6bc06b..ec9eea5df37e 100644 --- a/libcxx/include/numbers +++ b/libcxx/include/numbers @@ -63,7 +63,7 @@ namespace std::numbers { #include <__config> #include <version> -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -128,7 +128,7 @@ inline constexpr double phi = phi_v<double>; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> diff --git a/libcxx/include/numeric b/libcxx/include/numeric index 100dbe1c3232..3fcf6cefdb4b 100644 --- a/libcxx/include/numeric +++ b/libcxx/include/numeric @@ -158,6 +158,8 @@ template<class T> #include <__numeric/iota.h> #include <__numeric/midpoint.h> #include <__numeric/partial_sum.h> +#include <__numeric/pstl_reduce.h> +#include <__numeric/pstl_transform_reduce.h> #include <__numeric/reduce.h> #include <__numeric/transform_exclusive_scan.h> #include <__numeric/transform_inclusive_scan.h> @@ -167,10 +169,6 @@ template<class T> # pragma GCC system_header #endif -#if defined(_LIBCPP_HAS_PARALLEL_ALGORITHMS) && _LIBCPP_STD_VER >= 17 -# include <__pstl_numeric> -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> # include <functional> diff --git a/libcxx/include/optional b/libcxx/include/optional index 6a7e2d2941de..e7e5193a0bb6 100644 --- a/libcxx/include/optional +++ b/libcxx/include/optional @@ -16,107 +16,126 @@ // C++1z namespace std { - // 23.6.3, optional for object types - template <class T> class optional; + // [optional.optional], class template optional + template <class T> + class optional; - // 23.6.4, no-value state indicator + template<class T> + concept is-derived-from-optional = requires(const T& t) { // exposition only + []<class U>(const optional<U>&){ }(t); + }; + + // [optional.nullopt], no-value state indicator struct nullopt_t{see below }; inline constexpr nullopt_t nullopt(unspecified ); - // 23.6.5, class bad_optional_access + // [optional.bad.access], class bad_optional_access class bad_optional_access; - // 23.6.6, relational operators + // [optional.relops], relational operators template <class T, class U> - constexpr bool operator==(const optional<T>&, const optional<U>&); + constexpr bool operator==(const optional<T>&, const optional<U>&); template <class T, class U> - constexpr bool operator!=(const optional<T>&, const optional<U>&); + constexpr bool operator!=(const optional<T>&, const optional<U>&); template <class T, class U> - constexpr bool operator<(const optional<T>&, const optional<U>&); + constexpr bool operator<(const optional<T>&, const optional<U>&); template <class T, class U> - constexpr bool operator>(const optional<T>&, const optional<U>&); + constexpr bool operator>(const optional<T>&, const optional<U>&); template <class T, class U> - constexpr bool operator<=(const optional<T>&, const optional<U>&); + constexpr bool operator<=(const optional<T>&, const optional<U>&); template <class T, class U> - constexpr bool operator>=(const optional<T>&, const optional<U>&); - - // 23.6.7 comparison with nullopt - template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; - template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; - template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; - template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; - template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; - template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; - template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; - template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; - template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; - template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; - template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; - template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; - - // 23.6.8, comparison with T - template <class T, class U> constexpr bool operator==(const optional<T>&, const U&); - template <class T, class U> constexpr bool operator==(const T&, const optional<U>&); - template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&); - template <class T, class U> constexpr bool operator!=(const T&, const optional<U>&); - template <class T, class U> constexpr bool operator<(const optional<T>&, const U&); - template <class T, class U> constexpr bool operator<(const T&, const optional<U>&); - template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&); - template <class T, class U> constexpr bool operator<=(const T&, const optional<U>&); - template <class T, class U> constexpr bool operator>(const optional<T>&, const U&); - template <class T, class U> constexpr bool operator>(const T&, const optional<U>&); - template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&); - template <class T, class U> constexpr bool operator>=(const T&, const optional<U>&); - - // 23.6.9, specialized algorithms - template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20 - template <class T> constexpr optional<see below > make_optional(T&&); - template <class T, class... Args> + constexpr bool operator>=(const optional<T>&, const optional<U>&); + template<class T, three_way_comparable_with<T> U> + constexpr compare_three_way_result_t<T, U> + operator<=>(const optional<T>&, const optional<U>&); // since C++20 + + // [optional.nullops], comparison with nullopt + template<class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; + template<class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; // until C++17 + template<class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; // until C++17 + template<class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; // until C++17 + template<class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; // until C++17 + template<class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; // until C++17 + template<class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; // until C++17 + template<class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; // until C++17 + template<class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; // until C++17 + template<class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; // until C++17 + template<class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; // until C++17 + template<class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; // until C++17 + template<class T> + constexpr strong_ordering operator<=>(const optional<T>&, nullopt_t) noexcept; // since C++20 + + // [optional.comp.with.t], comparison with T + template<class T, class U> constexpr bool operator==(const optional<T>&, const U&); + template<class T, class U> constexpr bool operator==(const T&, const optional<U>&); + template<class T, class U> constexpr bool operator!=(const optional<T>&, const U&); + template<class T, class U> constexpr bool operator!=(const T&, const optional<U>&); + template<class T, class U> constexpr bool operator<(const optional<T>&, const U&); + template<class T, class U> constexpr bool operator<(const T&, const optional<U>&); + template<class T, class U> constexpr bool operator<=(const optional<T>&, const U&); + template<class T, class U> constexpr bool operator<=(const T&, const optional<U>&); + template<class T, class U> constexpr bool operator>(const optional<T>&, const U&); + template<class T, class U> constexpr bool operator>(const T&, const optional<U>&); + template<class T, class U> constexpr bool operator>=(const optional<T>&, const U&); + template<class T, class U> constexpr bool operator>=(const T&, const optional<U>&); + template<class T, class U> + requires (!is-derived-from-optional<U>) && three_way_comparable_with<T, U> + constexpr compare_three_way_result_t<T, U> + operator<=>(const optional<T>&, const U&); // since C++20 + + // [optional.specalg], specialized algorithms + template<class T> + void swap(optional<T>&, optional<T>&) noexcept(see below ); // constexpr in C++20 + + template<class T> + constexpr optional<see below > make_optional(T&&); + template<class T, class... Args> constexpr optional<T> make_optional(Args&&... args); - template <class T, class U, class... Args> + template<class T, class U, class... Args> constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); - // 23.6.10, hash support - template <class T> struct hash; - template <class T> struct hash<optional<T>>; + // [optional.hash], hash support + template<class T> struct hash; + template<class T> struct hash<optional<T>>; - template <class T> class optional { + template<class T> + class optional { public: using value_type = T; - // 23.6.3.1, constructors + // [optional.ctor], constructors constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept; constexpr optional(const optional &); constexpr optional(optional &&) noexcept(see below); - template <class... Args> constexpr explicit optional(in_place_t, Args &&...); - template <class U, class... Args> + template<class... Args> + constexpr explicit optional(in_place_t, Args &&...); + template<class U, class... Args> constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...); - template <class U = T> + template<class U = T> constexpr explicit(see-below) optional(U &&); - template <class U> - explicit(see-below) optional(const optional<U> &); // constexpr in C++20 - template <class U> - explicit(see-below) optional(optional<U> &&); // constexpr in C++20 + template<class U> + explicit(see-below) optional(const optional<U> &); // constexpr in C++20 + template<class U> + explicit(see-below) optional(optional<U> &&); // constexpr in C++20 - // 23.6.3.2, destructor + // [optional.dtor], destructor ~optional(); // constexpr in C++20 - // 23.6.3.3, assignment - optional &operator=(nullopt_t) noexcept; // constexpr in C++20 + // [optional.assign], assignment + optional &operator=(nullopt_t) noexcept; // constexpr in C++20 constexpr optional &operator=(const optional &); constexpr optional &operator=(optional &&) noexcept(see below); - template <class U = T> optional &operator=(U &&); // constexpr in C++20 - template <class U> optional &operator=(const optional<U> &); // constexpr in C++20 - template <class U> optional &operator=(optional<U> &&); // constexpr in C++20 - template <class... Args> T& emplace(Args &&...); // constexpr in C++20 - template <class U, class... Args> - T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20 - - // 23.6.3.4, swap + template<class U = T> optional &operator=(U &&); // constexpr in C++20 + template<class U> optional &operator=(const optional<U> &); // constexpr in C++20 + template<class U> optional &operator=(optional<U> &&); // constexpr in C++20 + template<class... Args> T& emplace(Args &&...); // constexpr in C++20 + template<class U, class... Args> T& emplace(initializer_list<U>, Args &&...); // constexpr in C++20 + + // [optional.swap], swap void swap(optional &) noexcept(see below ); // constexpr in C++20 - // 23.6.3.5, observers + // [optional.observe], observers constexpr T const *operator->() const; constexpr T *operator->(); constexpr T const &operator*() const &; @@ -129,8 +148,8 @@ namespace std { constexpr T &value() &; constexpr T &&value() &&; constexpr const T &&value() const &&; - template <class U> constexpr T value_or(U &&) const &; - template <class U> constexpr T value_or(U &&) &&; + template<class U> constexpr T value_or(U &&) const &; + template<class U> constexpr T value_or(U &&) &&; // [optional.monadic], monadic operations template<class F> constexpr auto and_then(F&& f) &; // since C++23 @@ -144,15 +163,15 @@ namespace std { template<class F> constexpr optional or_else(F&& f) &&; // since C++23 template<class F> constexpr optional or_else(F&& f) const&; // since C++23 - // 23.6.3.6, modifiers - void reset() noexcept; // constexpr in C++20 + // [optional.mod], modifiers + void reset() noexcept; // constexpr in C++20 private: - T *val; // exposition only + T *val; // exposition only }; -template<class T> - optional(T) -> optional<T>; + template<class T> + optional(T) -> optional<T>; } // namespace std @@ -160,21 +179,55 @@ template<class T> #include <__assert> // all public C++ headers provide the assertion handler #include <__availability> +#include <__compare/compare_three_way_result.h> +#include <__compare/three_way_comparable.h> #include <__concepts/invocable.h> #include <__config> #include <__functional/hash.h> #include <__functional/invoke.h> +#include <__functional/reference_wrapper.h> #include <__functional/unary_function.h> +#include <__memory/addressof.h> #include <__memory/construct_at.h> -#include <__tuple_dir/sfinae_helpers.h> +#include <__tuple/sfinae_helpers.h> +#include <__type_traits/add_pointer.h> +#include <__type_traits/conditional.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/decay.h> +#include <__type_traits/disjunction.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_assignable.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_destructible.h> +#include <__type_traits/is_move_assignable.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_object.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_scalar.h> +#include <__type_traits/is_swappable.h> +#include <__type_traits/is_trivially_copy_assignable.h> +#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_trivially_destructible.h> +#include <__type_traits/is_trivially_move_assignable.h> +#include <__type_traits/is_trivially_move_constructible.h> +#include <__type_traits/negation.h> +#include <__type_traits/remove_const.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> #include <__utility/swap.h> +#include <__verbose_abort> #include <initializer_list> #include <new> #include <stdexcept> -#include <type_traits> #include <version> // standard-mandated includes @@ -186,10 +239,13 @@ template<class T> # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + namespace std // purposefully not using versioning namespace { -class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access : public exception { public: @@ -200,7 +256,7 @@ public: } // namespace std -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD @@ -208,16 +264,16 @@ _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS void __throw_bad_optional_access() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_optional_access(); #else - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("bad_optional_access was thrown in -fno-exceptions mode"); #endif } struct nullopt_t { - struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; }; + struct __secret_tag { explicit __secret_tag() = default; }; _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} }; @@ -259,7 +315,7 @@ struct __optional_destruct_base<_Tp, false> : __val_(_VSTD::forward<_Args>(__args)...), __engaged_(true) {} -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _Fp, class... _Args> _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) @@ -301,7 +357,7 @@ struct __optional_destruct_base<_Tp, true> : __val_(_VSTD::forward<_Args>(__args)...), __engaged_(true) {} -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _Fp, class... _Args> _LIBCPP_HIDE_FROM_ABI constexpr __optional_destruct_base(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) @@ -356,8 +412,8 @@ struct __optional_storage_base : __optional_destruct_base<_Tp> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_Args&&... __args) { - _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); -#if _LIBCPP_STD_VER > 17 + _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage"); +#if _LIBCPP_STD_VER >= 20 _VSTD::construct_at(_VSTD::addressof(this->__val_), _VSTD::forward<_Args>(__args)...); #else ::new ((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); @@ -403,7 +459,7 @@ struct __optional_storage_base<_Tp, true> __raw_type* __value_; template <class _Up> - static constexpr bool __can_bind_reference() { + static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() { using _RawUp = __libcpp_remove_reference_t<_Up>; using _UpPtr = _RawUp*; using _RawTp = __libcpp_remove_reference_t<_Tp>; @@ -451,7 +507,7 @@ struct __optional_storage_base<_Tp, true> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) { - _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); + _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage"); static_assert(__can_bind_reference<_UArg>(), "Attempted to construct a reference element in tuple from a " "possible temporary"); @@ -623,12 +679,20 @@ using __optional_sfinae_assign_base_t = __sfinae_assign_base< template<class _Tp> class optional; + +#if _LIBCPP_STD_VER >= 20 + +template <class _Tp> +concept __is_derived_from_optional = requires(const _Tp& __t) { []<class _Up>(const optional<_Up>&) {}(__t); }; + +# endif // _LIBCPP_STD_VER >= 20 + template <class _Tp> struct __is_std_optional : false_type {}; template <class _Tp> struct __is_std_optional<optional<_Tp>> : true_type {}; template <class _Tp> -class optional +class _LIBCPP_DECLSPEC_EMPTY_BASES optional : private __optional_move_assign_base<_Tp> , private __optional_sfinae_ctor_base_t<_Tp> , private __optional_sfinae_assign_base_t<_Tp> @@ -653,13 +717,13 @@ private: // LWG2756: conditionally explicit conversion from _Up struct _CheckOptionalArgsConstructor { template <class _Up> - static constexpr bool __enable_implicit() { + _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() { return is_constructible_v<_Tp, _Up&&> && is_convertible_v<_Up&&, _Tp>; } template <class _Up> - static constexpr bool __enable_explicit() { + _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() { return is_constructible_v<_Tp, _Up&&> && !is_convertible_v<_Up&&, _Tp>; } @@ -692,17 +756,17 @@ private: is_assignable<_Tp&, _Opt const&&> >; template <class _Up, class _QUp = _QualUp> - static constexpr bool __enable_implicit() { + _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_implicit() { return is_convertible<_QUp, _Tp>::value && !__check_constructible_from_opt<_Up>::value; } template <class _Up, class _QUp = _QualUp> - static constexpr bool __enable_explicit() { + _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_explicit() { return !is_convertible<_QUp, _Tp>::value && !__check_constructible_from_opt<_Up>::value; } template <class _Up, class _QUp = _QualUp> - static constexpr bool __enable_assign() { + _LIBCPP_HIDE_FROM_ABI static constexpr bool __enable_assign() { // Construction and assignability of _QUp to _Tp has already been // checked. return !__check_constructible_from_opt<_Up>::value && @@ -805,7 +869,7 @@ public: this->__construct_from(_VSTD::move(__v)); } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template<class _Fp, class... _Args> _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(__optional_construct_from_invoke_tag, _Fp&& __f, _Args&&... __args) @@ -820,8 +884,8 @@ public: return *this; } - constexpr optional& operator=(const optional&) = default; - constexpr optional& operator=(optional&&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(const optional&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr optional& operator=(optional&&) = default; // LWG2756 template <class _Up = value_type, @@ -932,7 +996,7 @@ public: add_pointer_t<value_type const> operator->() const { - _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value"); return _VSTD::addressof(this->__get()); } @@ -941,7 +1005,7 @@ public: add_pointer_t<value_type> operator->() { - _LIBCPP_ASSERT(this->has_value(), "optional operator-> called on a disengaged value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value"); return _VSTD::addressof(this->__get()); } @@ -950,7 +1014,7 @@ public: const value_type& operator*() const& noexcept { - _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); return this->__get(); } @@ -959,7 +1023,7 @@ public: value_type& operator*() & noexcept { - _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); return this->__get(); } @@ -968,7 +1032,7 @@ public: value_type&& operator*() && noexcept { - _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); return _VSTD::move(this->__get()); } @@ -977,7 +1041,7 @@ public: const value_type&& operator*() const&& noexcept { - _LIBCPP_ASSERT(this->has_value(), "optional operator* called on a disengaged value"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); return _VSTD::move(this->__get()); } @@ -1047,7 +1111,7 @@ public: static_cast<value_type>(_VSTD::forward<_Up>(__v)); } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template<class _Func> _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr auto and_then(_Func&& __f) & { @@ -1171,7 +1235,7 @@ public: return _VSTD::move(*this); return _VSTD::forward<_Func>(__f)(); } -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 using __base::reset; }; @@ -1278,6 +1342,18 @@ operator>=(const optional<_Tp>& __x, const optional<_Up>& __y) return *__x >= *__y; } +#if _LIBCPP_STD_VER >= 20 + +template <class _Tp, three_way_comparable_with<_Tp> _Up> +_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up> +operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) { + if (__x && __y) + return *__x <=> *__y; + return __x.has_value() <=> __y.has_value(); +} + +#endif // _LIBCPP_STD_VER >= 20 + // Comparisons with nullopt template <class _Tp> _LIBCPP_INLINE_VISIBILITY constexpr @@ -1287,6 +1363,8 @@ operator==(const optional<_Tp>& __x, nullopt_t) noexcept return !static_cast<bool>(__x); } +#if _LIBCPP_STD_VER <= 17 + template <class _Tp> _LIBCPP_INLINE_VISIBILITY constexpr bool @@ -1375,6 +1453,15 @@ operator>=(nullopt_t, const optional<_Tp>& __x) noexcept return !static_cast<bool>(__x); } +#else // _LIBCPP_STD_VER <= 17 + +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept { + return __x.has_value() <=> false; +} + +#endif // _LIBCPP_STD_VER <= 17 + // Comparisons with T template <class _Tp, class _Up> _LIBCPP_INLINE_VISIBILITY constexpr @@ -1520,6 +1607,17 @@ operator>=(const _Tp& __v, const optional<_Up>& __x) return static_cast<bool>(__x) ? __v >= *__x : true; } +#if _LIBCPP_STD_VER >= 20 + +template <class _Tp, class _Up> + requires(!__is_derived_from_optional<_Up>) && three_way_comparable_with<_Tp, _Up> +_LIBCPP_HIDE_FROM_ABI constexpr compare_three_way_result_t<_Tp, _Up> +operator<=>(const optional<_Tp>& __x, const _Up& __v) { + return __x.has_value() ? *__x <=> __v : strong_ordering::less; +} + +#endif // _LIBCPP_STD_VER >= 20 + template <class _Tp> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -1572,7 +1670,9 @@ struct _LIBCPP_TEMPLATE_VIS hash< _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 + +_LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <atomic> @@ -1583,6 +1683,7 @@ _LIBCPP_END_NAMESPACE_STD # include <memory> # include <ratio> # include <tuple> +# include <type_traits> # include <typeinfo> # include <utility> # include <variant> diff --git a/libcxx/include/ostream b/libcxx/include/ostream index 4780c763ea03..168a75376bd9 100644 --- a/libcxx/include/ostream +++ b/libcxx/include/ostream @@ -165,8 +165,16 @@ basic_ostream<wchar_t, traits>& operator<<(basic_ostream<wchar_t, traits>&, cons #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__exception/operations.h> +#include <__fwd/ostream.h> #include <__memory/shared_ptr.h> #include <__memory/unique_ptr.h> +#include <__system_error/error_code.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_base_of.h> +#include <__type_traits/void_t.h> +#include <__utility/declval.h> #include <bitset> #include <ios> #include <locale> @@ -244,7 +252,7 @@ public: basic_ostream& operator<<(long double __f); basic_ostream& operator<<(const void* __p); -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI basic_ostream& operator<<(const volatile void* __p) { return operator<<(const_cast<const void*>(__p)); @@ -253,7 +261,7 @@ public: basic_ostream& operator<<(basic_streambuf<char_type, traits_type>* __sb); -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 // LWG 2221 - nullptr. This is not backported to older standards modes. // See https://reviews.llvm.org/D127033 for more info on the rationale. _LIBCPP_INLINE_VISIBILITY @@ -314,18 +322,18 @@ basic_ostream<_CharT, _Traits>::sentry::~sentry() if (__os_.rdbuf() && __os_.good() && (__os_.flags() & ios_base::unitbuf) && !uncaught_exception()) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (__os_.rdbuf()->pubsync() == -1) __os_.setstate(ios_base::badbit); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -352,19 +360,19 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf<char_type, traits_type>* __sb) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { if (__sb) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef istreambuf_iterator<_CharT, _Traits> _Ip; typedef ostreambuf_iterator<_CharT, _Traits> _Op; _Ip __i(__sb); @@ -379,24 +387,24 @@ basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf<char_type, traits_typ } if (__c == 0) this->setstate(ios_base::failbit); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_failbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } else this->setstate(ios_base::badbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -404,10 +412,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(bool __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -416,13 +424,13 @@ basic_ostream<_CharT, _Traits>::operator<<(bool __n) if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -430,10 +438,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(short __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -446,13 +454,13 @@ basic_ostream<_CharT, _Traits>::operator<<(short __n) static_cast<long>(__n)).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -460,10 +468,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned short __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -472,13 +480,13 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned short __n) if (__f.put(*this, *this, this->fill(), static_cast<unsigned long>(__n)).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -486,10 +494,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(int __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -502,13 +510,13 @@ basic_ostream<_CharT, _Traits>::operator<<(int __n) static_cast<long>(__n)).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -516,10 +524,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned int __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -528,13 +536,13 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned int __n) if (__f.put(*this, *this, this->fill(), static_cast<unsigned long>(__n)).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -542,10 +550,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -554,13 +562,13 @@ basic_ostream<_CharT, _Traits>::operator<<(long __n) if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -568,10 +576,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned long __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -580,13 +588,13 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned long __n) if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -594,10 +602,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long long __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -606,13 +614,13 @@ basic_ostream<_CharT, _Traits>::operator<<(long long __n) if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -620,10 +628,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(unsigned long long __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -632,13 +640,13 @@ basic_ostream<_CharT, _Traits>::operator<<(unsigned long long __n) if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -646,10 +654,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(float __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -658,13 +666,13 @@ basic_ostream<_CharT, _Traits>::operator<<(float __n) if (__f.put(*this, *this, this->fill(), static_cast<double>(__n)).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -672,10 +680,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(double __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -684,13 +692,13 @@ basic_ostream<_CharT, _Traits>::operator<<(double __n) if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -698,10 +706,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(long double __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -710,13 +718,13 @@ basic_ostream<_CharT, _Traits>::operator<<(long double __n) if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -724,10 +732,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(const void* __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -736,13 +744,13 @@ basic_ostream<_CharT, _Traits>::operator<<(const void* __n) if (__f.put(*this, *this, this->fill(), __n).failed()) this->setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -751,10 +759,10 @@ _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& __put_character_sequence(basic_ostream<_CharT, _Traits>& __os, const _CharT* __str, size_t __len) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typename basic_ostream<_CharT, _Traits>::sentry __s(__os); if (__s) { @@ -769,13 +777,13 @@ __put_character_sequence(basic_ostream<_CharT, _Traits>& __os, __os.fill()).failed()) __os.setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __os.__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return __os; } @@ -791,10 +799,10 @@ template<class _CharT, class _Traits> _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, char __cn) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typename basic_ostream<_CharT, _Traits>::sentry __s(__os); if (__s) { @@ -810,13 +818,13 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, char __cn) __os.fill()).failed()) __os.setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __os.__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return __os; } @@ -852,10 +860,10 @@ template<class _CharT, class _Traits> _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const char* __strn) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typename basic_ostream<_CharT, _Traits>::sentry __s(__os); if (__s) { @@ -884,13 +892,13 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const char* __strn) __os.fill()).failed()) __os.setstate(ios_base::badbit | ios_base::failbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __os.__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return __os; } @@ -921,10 +929,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::put(char_type __c) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __s(*this); if (__s) { @@ -934,13 +942,13 @@ basic_ostream<_CharT, _Traits>::put(char_type __c) if (__o.failed()) this->setstate(ios_base::badbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -948,23 +956,23 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::write(const char_type* __s, streamsize __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS sentry __sen(*this); if (__sen && __n) { if (this->rdbuf()->sputn(__s, __n) != __n) this->setstate(ios_base::badbit); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -972,10 +980,10 @@ template <class _CharT, class _Traits> basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::flush() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS if (this->rdbuf()) { sentry __s(*this); @@ -985,13 +993,13 @@ basic_ostream<_CharT, _Traits>::flush() this->setstate(ios_base::badbit); } } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { this->__set_badbit_and_consider_rethrow(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS return *this; } @@ -1130,7 +1138,7 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const bitset<_Size>& __x) std::use_facet<ctype<_CharT> >(__os.getloc()).widen('1')); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template <class _Traits> @@ -1179,7 +1187,7 @@ basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>&, const ch template <class _Traits> basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>&, const char32_t*) = delete; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream<char>; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -1189,7 +1197,9 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ostream<wchar_t>; _LIBCPP_END_NAMESPACE_STD #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <atomic> # include <concepts> +# include <cstdlib> # include <iterator> # include <type_traits> #endif diff --git a/libcxx/include/print b/libcxx/include/print new file mode 100644 index 000000000000..d119c8bda749 --- /dev/null +++ b/libcxx/include/print @@ -0,0 +1,389 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_PRINT +#define _LIBCPP_PRINT + +/* +namespace std { + // [print.fun], print functions + template<class... Args> + void print(format_string<Args...> fmt, Args&&... args); + template<class... Args> + void print(FILE* stream, format_string<Args...> fmt, Args&&... args); + + template<class... Args> + void println(format_string<Args...> fmt, Args&&... args); + template<class... Args> + void println(FILE* stream, format_string<Args...> fmt, Args&&... args); + + void vprint_unicode(string_view fmt, format_args args); + void vprint_unicode(FILE* stream, string_view fmt, format_args args); + + void vprint_nonunicode(string_view fmt, format_args args); + void vprint_nonunicode(FILE* stream, string_view fmt, format_args args); +} +*/ + +#include <__assert> // all public C++ headers provide the assertion handler +#include <__concepts/same_as.h> +#include <__config> +#include <__format/buffer.h> +#include <__format/format_arg_store.h> +#include <__format/format_args.h> +#include <__format/format_context.h> +#include <__format/format_error.h> +#include <__format/format_functions.h> +#include <__format/unicode.h> +#include <__system_error/system_error.h> +#include <__utility/forward.h> +#include <cerrno> +#include <cstdio> +#include <string> +#include <string_view> +#include <version> + +#if __has_include(<unistd.h>) +# include <unistd.h> +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifdef _WIN32 +_LIBCPP_EXPORTED_FROM_ABI bool __is_windows_terminal(FILE* __stream); + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +// A wrapper for WriteConsoleW which is used to write to the Windows +// console. This function is in the dylib to avoid pulling in windows.h +// in the library headers. The function itself uses some private parts +// of the dylib too. +// +// The function does not depend on the language standard used. Guarding +// it with C++23 would fail since the dylib is currently built using C++20. +// +// Note the function is only implemented on the Windows platform. +_LIBCPP_EXPORTED_FROM_ABI void __write_to_windows_console(FILE* __stream, wstring_view __view); +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +#endif // _WIN32 + +#if _LIBCPP_STD_VER >= 23 + +# ifndef _LIBCPP_HAS_NO_UNICODE +// This is the code to transcode UTF-8 to UTF-16. This is used on +// Windows for the native Unicode API. The code is modeled to make it +// easier to extend to +// +// P2728R0 Unicode in the Library, Part 1: UTF Transcoding +// +// This paper is still under heavy development so it makes no sense yet +// to strictly follow the paper. +namespace __unicode { + +// The names of these concepts are modelled after P2728R0, but the +// implementation is not. char16_t may contain 32-bits so depending on the +// number of bits is an issue. +# ifdef _LIBCPP_SHORT_WCHAR +template <class _Tp> +concept __utf16_code_unit = + same_as<_Tp, char16_t> +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + || same_as<_Tp, wchar_t> +# endif + ; +template <class _Tp> +concept __utf32_code_unit = same_as<_Tp, char32_t>; +# else // _LIBCPP_SHORT_WCHAR +template <class _Tp> +concept __utf16_code_unit = same_as<_Tp, char16_t>; +template <class _Tp> +concept __utf32_code_unit = + same_as<_Tp, char32_t> +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + || same_as<_Tp, wchar_t> +# endif + ; +# endif // _LIBCPP_SHORT_WCHAR + +// Pass by reference since an output_iterator may not be copyable. +template <class _OutIt> +_LIBCPP_HIDE_FROM_ABI constexpr void __encode(_OutIt&, char32_t) = delete; + +template <class _OutIt> + requires __utf16_code_unit<iter_value_t<_OutIt>> +_LIBCPP_HIDE_FROM_ABI constexpr void __encode(_OutIt& __out_it, char32_t __value) { + _LIBCPP_ASSERT_UNCATEGORIZED(__is_scalar_value(__value), "an invalid unicode scalar value results in invalid UTF-16"); + + if (__value < 0x10000) { + *__out_it++ = __value; + return; + } + + __value -= 0x10000; + *__out_it++ = 0xd800 + (__value >> 10); + *__out_it++ = 0xdc00 + (__value & 0x3FF); +} + +template <class _OutIt> + requires __utf32_code_unit<iter_value_t<_OutIt>> +_LIBCPP_HIDE_FROM_ABI constexpr void __encode(_OutIt& __out_it, char32_t __value) { + _LIBCPP_ASSERT_UNCATEGORIZED(__is_scalar_value(__value), "an invalid unicode scalar value results in invalid UTF-32"); + *__out_it++ = __value; +} + +template <class _OutIt, input_iterator _InIt> + requires output_iterator<_OutIt, const iter_value_t<_OutIt>&> && (!same_as<iter_value_t<_OutIt>, iter_value_t<_InIt>>) +_LIBCPP_HIDE_FROM_ABI constexpr _OutIt __transcode(_InIt __first, _InIt __last, _OutIt __out_it) { + // The __code_point_view has a basic_string_view interface. + // When transcoding becomes part of the standard we probably want to + // look at smarter algorithms. + // For example, when processing a code point that is encoded in + // 1 to 3 code units in UTF-8, the result will always be encoded + // in 1 code unit in UTF-16 (code points that require 4 code + // units in UTF-8 will require 2 code units in UTF-16). + // + // Note if P2728 is accepted types like int may become valid. In that case + // the __code_point_view should use a span. Libc++ will remove support for + // char_traits<int>. + + // TODO PRINT Validate with clang-tidy + // NOLINTNEXTLINE(bugprone-dangling-handle) + basic_string_view<iter_value_t<_InIt>> __data{__first, __last}; + __code_point_view<iter_value_t<_InIt>> __view{__data.begin(), __data.end()}; + while (!__view.__at_end()) + __unicode::__encode(__out_it, __view.__consume().__code_point); + return __out_it; +} + +} // namespace __unicode + +# endif // _LIBCPP_HAS_NO_UNICODE + +namespace __print { + +// [print.fun]/2 +// Effects: If the ordinary literal encoding ([lex.charset]) is UTF-8, equivalent to: +// vprint_unicode(stream, fmt.str, make_format_args(args...)); +// Otherwise, equivalent to: +// vprint_nonunicode(stream, fmt.str, make_format_args(args...)); +// +// Based on the compiler and its compilation flags this value is or is +// not true. As mentioned in P2093R14 this only affects Windows. The +// test below could also be done for +// - GCC using __GNUC_EXECUTION_CHARSET_NAME +// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html +// - Clang using __clang_literal_encoding__ +// https://clang.llvm.org/docs/LanguageExtensions.html#builtin-macros +// (note at the time of writing Clang is hard-coded to UTF-8.) +// + +# ifdef _LIBCPP_HAS_NO_UNICODE +inline constexpr bool __use_unicode = false; +# elif defined(_MSVC_EXECUTION_CHARACTER_SET) +// This is the same test MSVC STL uses in their implementation of <print> +// See: https://learn.microsoft.com/en-us/windows/win32/intl/code-page-identifiers +inline constexpr bool __use_unicode = _MSVC_EXECUTION_CHARACTER_SET == 65001; +# else +inline constexpr bool __use_unicode = true; +# endif + +_LIBCPP_HIDE_FROM_ABI inline bool __is_terminal(FILE* __stream) { +# ifdef _WIN32 + return std::__is_windows_terminal(__stream); +# elif __has_include(<unistd.h>) + return isatty(fileno(__stream)); +# else +# error "Provide a way to determine whether a FILE* is a terminal" +# endif +} + +template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void +__vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args, bool __write_nl) { + _LIBCPP_ASSERT_UNCATEGORIZED(__stream, "__stream is a valid pointer to an output C stream"); + string __str = std::vformat(__fmt, __args); + if (__write_nl) + __str.push_back('\n'); + + size_t __size = fwrite(__str.data(), 1, __str.size(), __stream); + if (__size < __str.size()) { + if (std::feof(__stream)) + std::__throw_system_error(EIO, "EOF while writing the formatted output"); + std::__throw_system_error(std::ferror(__stream), "failed to write formatted output"); + } +} + +# ifndef _LIBCPP_HAS_NO_UNICODE + +// Note these helper functions are mainly used to aid testing. +// On POSIX systems and Windows the output is no longer considered a +// terminal when the output is redirected. Typically during testing the +// output is redirected to be able to capture it. This makes it hard to +// test this code path. +template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void +__vprint_unicode_posix(FILE* __stream, string_view __fmt, format_args __args, bool __write_nl, bool __is_terminal) { + // TODO PRINT Should flush errors throw too? + if (__is_terminal) + std::fflush(__stream); + + __print::__vprint_nonunicode(__stream, __fmt, __args, __write_nl); +} + +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void +__vprint_unicode_windows(FILE* __stream, string_view __fmt, format_args __args, bool __write_nl, bool __is_terminal) { + if (!__is_terminal) + return __print::__vprint_nonunicode(__stream, __fmt, __args, __write_nl); + + // TODO PRINT Should flush errors throw too? + std::fflush(__stream); + + string __str = std::vformat(__fmt, __args); + // UTF-16 uses the same number or less code units than UTF-8. + // However the size of the code unit is 16 bits instead of 8 bits. + // + // The buffer uses the worst-case estimate and should never resize. + // However when the string is large this could lead to OOM. Using a + // smaller size might work, but since the buffer uses a grow factor + // the final size might be larger when the estimate is wrong. + // + // TODO PRINT profile and improve the speed of this code. + __format::__retarget_buffer<wchar_t> __buffer{__str.size()}; + __unicode::__transcode(__str.begin(), __str.end(), __buffer.__make_output_iterator()); + if (__write_nl) + __buffer.push_back(L'\n'); + + [[maybe_unused]] wstring_view __view = __buffer.__view(); + + // The macro _LIBCPP_TESTING_PRINT_WRITE_TO_WINDOWS_CONSOLE_FUNCTION is used to change + // the behavior in the test. This is not part of the public API. +# ifdef _LIBCPP_TESTING_PRINT_WRITE_TO_WINDOWS_CONSOLE_FUNCTION + _LIBCPP_TESTING_PRINT_WRITE_TO_WINDOWS_CONSOLE_FUNCTION(__stream, __view); +# elif defined(_WIN32) + std::__write_to_windows_console(__stream, __view); +# else + std::__throw_runtime_error("No defintion of _LIBCPP_TESTING_PRINT_WRITE_TO_WINDOWS_CONSOLE_FUNCTION and " + "__write_to_windows_console is not available."); +# endif +} +# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void +__vprint_unicode([[maybe_unused]] FILE* __stream, + [[maybe_unused]] string_view __fmt, + [[maybe_unused]] format_args __args, + [[maybe_unused]] bool __write_nl) { + _LIBCPP_ASSERT_UNCATEGORIZED(__stream, "__stream is a valid pointer to an output C stream"); + + // [print.fun] + // 7 - Effects: If stream refers to a terminal capable of displaying + // Unicode, writes out to the terminal using the native Unicode + // API; if out contains invalid code units, the behavior is + // undefined and implementations are encouraged to diagnose it. + // Otherwise writes out to stream unchanged. If the native + // Unicode API is used, the function flushes stream before + // writing out. + // 8 - Throws: Any exception thrown by the call to vformat + // ([format.err.report]). system_error if writing to the terminal + // or stream fails. May throw bad_alloc. + // 9 - Recommended practice: If invoking the native Unicode API + // requires transcoding, implementations should substitute + // invalid code units with U+FFFD replacement character per the + // Unicode Standard, Chapter 3.9 U+FFFD Substitution in + // Conversion. + + // On non-Windows platforms the Unicode API is the normal file I/O API + // so there the call can be forwarded to the non_unicode API. On + // Windows there is a different API. This API requires transcoding. + +# ifndef _WIN32 + __print::__vprint_unicode_posix(__stream, __fmt, __args, __write_nl, __print::__is_terminal(__stream)); +# elif !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) + __print::__vprint_unicode_windows(__stream, __fmt, __args, __write_nl, __print::__is_terminal(__stream)); +# else +# error "Windows builds with wchar_t disabled are not supported." +# endif +} + +# endif // _LIBCPP_HAS_NO_UNICODE + +} // namespace __print + +template <class... _Args> +_LIBCPP_HIDE_FROM_ABI void print(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args) { +# ifndef _LIBCPP_HAS_NO_UNICODE + if constexpr (__print::__use_unicode) + __print::__vprint_unicode(__stream, __fmt.get(), std::make_format_args(__args...), false); + else + __print::__vprint_nonunicode(__stream, __fmt.get(), std::make_format_args(__args...), false); +# else // _LIBCPP_HAS_NO_UNICODE + __print::__vprint_nonunicode(__stream, __fmt.get(), std::make_format_args(__args...), false); +# endif // _LIBCPP_HAS_NO_UNICODE +} + +template <class... _Args> +_LIBCPP_HIDE_FROM_ABI void print(format_string<_Args...> __fmt, _Args&&... __args) { + std::print(stdout, __fmt, std::forward<_Args>(__args)...); +} + +template <class... _Args> +_LIBCPP_HIDE_FROM_ABI void println(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args) { +# ifndef _LIBCPP_HAS_NO_UNICODE + // Note the wording in the Standard is inefficient. The output of + // std::format is a std::string which is then copied. This solution + // just appends a newline at the end of the output. + if constexpr (__print::__use_unicode) + __print::__vprint_unicode(__stream, __fmt.get(), std::make_format_args(__args...), true); + else + __print::__vprint_nonunicode(__stream, __fmt.get(), std::make_format_args(__args...), true); +# else // _LIBCPP_HAS_NO_UNICODE + __print::__vprint_nonunicode(__stream, __fmt.get(), std::make_format_args(__args...), true); +# endif // _LIBCPP_HAS_NO_UNICODE +} + +template <class... _Args> +_LIBCPP_HIDE_FROM_ABI void println(format_string<_Args...> __fmt, _Args&&... __args) { + std::println(stdout, __fmt, std::forward<_Args>(__args)...); +} + +# ifndef _LIBCPP_HAS_NO_UNICODE +template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(FILE* __stream, string_view __fmt, format_args __args) { + __print::__vprint_unicode(__stream, __fmt, __args, false); +} + +template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(string_view __fmt, format_args __args) { + std::vprint_unicode(stdout, __fmt, __args); +} + +# endif // _LIBCPP_HAS_NO_UNICODE + +template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args) { + __print::__vprint_nonunicode(__stream, __fmt, __args, false); +} + +template <class = void> // TODO PRINT template or availability markup fires too eagerly (http://llvm.org/PR61563). +_LIBCPP_HIDE_FROM_ABI inline void vprint_nonunicode(string_view __fmt, format_args __args) { + std::vprint_nonunicode(stdout, __fmt, __args); +} + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_PRINT diff --git a/libcxx/include/queue b/libcxx/include/queue index 6c1b892efadc..b5944e8f9f92 100644 --- a/libcxx/include/queue +++ b/libcxx/include/queue @@ -43,6 +43,7 @@ public: explicit queue(container_type&& c) template<class InputIterator> queue(InputIterator first, InputIterator last); // since C++23 + template<container-compatible-range<T> R> queue(from_range_t, R&& rg); // since C++23 template <class Alloc> explicit queue(const Alloc& a); template <class Alloc> @@ -55,6 +56,8 @@ public: queue(queue&& q, const Alloc& a); template <class InputIterator, class Alloc> queue(InputIterator first, InputIterator last, const Alloc&); // since C++23 + template<container-compatible-range<T> R, class Alloc> + queue(from_range_t, R&& rg, const Alloc&); // since C++23 bool empty() const; size_type size() const; @@ -66,6 +69,8 @@ public: void push(const value_type& v); void push(value_type&& v); + template<container-compatible-range<T> R> + void push_range(R&& rg); // C++23 template <class... Args> reference emplace(Args&&... args); // reference in C++17 void pop(); @@ -78,6 +83,9 @@ template<class Container> template<class InputIterator> queue(InputIterator, InputIterator) -> queue<iter-value-type<InputIterator>>; // since C++23 +template<ranges::input_range R> + queue(from_range_t, R&&) -> queue<ranges::range_value_t<R>>; // since C++23 + template<class Container, class Allocator> queue(Container, Allocator) -> queue<typename Container::value_type, Container>; // C++17 @@ -86,6 +94,10 @@ template<class InputIterator, class Allocator> -> queue<iter-value-type<InputIterator>, deque<iter-value-type<InputIterator>, Allocator>>; // since C++23 +template<ranges::input_range R, class Allocator> + queue(from_range_t, R&&, Allocator) + -> queue<ranges::range_value_t<R>, deque<ranges::range_value_t<R>, Allocator>>; // since C++23 + template <class T, class Container> bool operator==(const queue<T, Container>& x,const queue<T, Container>& y); @@ -104,6 +116,10 @@ template <class T, class Container> template <class T, class Container> bool operator<=(const queue<T, Container>& x,const queue<T, Container>& y); +template<class T, three_way_comparable Container> + compare_three_way_result_t<Container> + operator<=>(const queue<T, Container>& x, const queue<T, Container>& y); // since C++20 + template <class T, class Container> void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y))); @@ -138,6 +154,8 @@ public: template <class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& comp, Container&& c); + template <container-compatible-range<T> R> + priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); // since C++23 template <class Alloc> explicit priority_queue(const Alloc& a); template <class Alloc> @@ -160,6 +178,10 @@ public: template <class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& comp, Container&& c, const Alloc& a); + template <container-compatible-range<T> R, class Alloc> + priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&); // since C++23 + template <container-compatible-range<T> R, class Alloc> + priority_queue(from_range_t, R&& rg, const Alloc&); // since C++23 template <class Alloc> priority_queue(const priority_queue& q, const Alloc& a); template <class Alloc> @@ -171,6 +193,8 @@ public: void push(const value_type& v); void push(value_type&& v); + template<container-compatible-range<T> R> + void push_range(R&& rg); // C++23 template <class... Args> void emplace(Args&&... args); void pop(); @@ -189,6 +213,10 @@ template<class InputIterator, priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) -> priority_queue<iter-value-type<InputIterator>, Container, Compare>; // C++17 +template<ranges::input_range R, class Compare = less<ranges::range_value_t<R>>> + priority_queue(from_range_t, R&&, Compare = Compare()) + -> priority_queue<ranges::range_value_t<R>, vector<ranges::range_value_t<R>>, Compare>; // C++23 + template<class Compare, class Container, class Allocator> priority_queue(Compare, Container, Allocator) -> priority_queue<typename Container::value_type, Container, Compare>; // C++17 @@ -208,6 +236,15 @@ template<class InputIterator, class Compare, class Container, class Allocator> priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) -> priority_queue<typename Container::value_type, Container, Compare>; // C++17 +template<ranges::input_range R, class Compare, class Allocator> + priority_queue(from_range_t, R&&, Compare, Allocator) + -> priority_queue<ranges::range_value_t<R>, vector<ranges::range_value_t<R>, Allocator>, + Compare>; // C++23 + +template<ranges::input_range R, class Allocator> + priority_queue(from_range_t, R&&, Allocator) + -> priority_queue<ranges::range_value_t<R>, vector<ranges::range_value_t<R>, Allocator>>; // C++23 + template <class T, class Container, class Compare> void swap(priority_queue<T, Container, Compare>& x, priority_queue<T, Container, Compare>& y) @@ -220,14 +257,19 @@ template <class T, class Container, class Compare> #include <__algorithm/make_heap.h> #include <__algorithm/pop_heap.h> #include <__algorithm/push_heap.h> +#include <__algorithm/ranges_copy.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__functional/operations.h> +#include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> #include <__memory/uses_allocator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> #include <__utility/forward.h> #include <deque> -#include <type_traits> #include <vector> #include <version> @@ -278,18 +320,30 @@ public: _LIBCPP_INLINE_VISIBILITY queue(const queue& __q) : c(__q.c) {} -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _InputIterator, - class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>> + class = __enable_if_t<__has_input_iterator_category<_InputIterator>::value>> _LIBCPP_HIDE_FROM_ABI queue(_InputIterator __first, _InputIterator __last) : c(__first, __last) {} + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + queue(from_range_t, _Range&& __range) : c(from_range, std::forward<_Range>(__range)) {} + template <class _InputIterator, class _Alloc, - class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = __enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = __enable_if_t<uses_allocator<container_type, _Alloc>::value>> _LIBCPP_HIDE_FROM_ABI queue(_InputIterator __first, _InputIterator __second, const _Alloc& __alloc) : c(__first, __second, __alloc) {} + + template <_ContainerCompatibleRange<_Tp> _Range, + class _Alloc, + class = __enable_if_t<uses_allocator<container_type, _Alloc>::value>> + _LIBCPP_HIDE_FROM_ABI + queue(from_range_t, _Range&& __range, const _Alloc& __alloc) + : c(from_range, std::forward<_Range>(__range), __alloc) {} + #endif _LIBCPP_INLINE_VISIBILITY @@ -361,9 +415,24 @@ public: #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void push(value_type&& __v) {c.push_back(_VSTD::move(__v));} + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void push_range(_Range&& __range) { + if constexpr (requires (container_type& __c) { + __c.append_range(std::forward<_Range>(__range)); + }) { + c.append_range(std::forward<_Range>(__range)); + } else { + ranges::copy(std::forward<_Range>(__range), std::back_inserter(c)); + } + } +#endif + template <class... _Args> _LIBCPP_INLINE_VISIBILITY -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 decltype(auto) emplace(_Args&&... __args) { return c.emplace_back(_VSTD::forward<_Args>(__args)...);} #else @@ -384,20 +453,20 @@ public: _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI const _Container& __get_container() const { return c; } - template <class _T1, class _C1> + template <class _T1, class _OtherContainer> friend _LIBCPP_INLINE_VISIBILITY bool - operator==(const queue<_T1, _C1>& __x,const queue<_T1, _C1>& __y); + operator==(const queue<_T1, _OtherContainer>& __x,const queue<_T1, _OtherContainer>& __y); - template <class _T1, class _C1> + template <class _T1, class _OtherContainer> friend _LIBCPP_INLINE_VISIBILITY bool - operator< (const queue<_T1, _C1>& __x,const queue<_T1, _C1>& __y); + operator< (const queue<_T1, _OtherContainer>& __x,const queue<_T1, _OtherContainer>& __y); }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template<class _Container, class = enable_if_t<!__is_allocator<_Container>::value> > @@ -413,18 +482,28 @@ queue(_Container, _Alloc) -> queue<typename _Container::value_type, _Container>; #endif -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _InputIterator, - class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>> + class = __enable_if_t<__has_input_iterator_category<_InputIterator>::value>> queue(_InputIterator, _InputIterator) -> queue<__iter_value_type<_InputIterator>>; +template <ranges::input_range _Range> +queue(from_range_t, _Range&&) + -> queue<ranges::range_value_t<_Range>>; + template <class _InputIterator, class _Alloc, - class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = __enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = __enable_if_t<__is_allocator<_Alloc>::value>> queue(_InputIterator, _InputIterator, _Alloc) -> queue<__iter_value_type<_InputIterator>, deque<__iter_value_type<_InputIterator>, _Alloc>>; + +template <ranges::input_range _Range, + class _Alloc, + class = __enable_if_t<__is_allocator<_Alloc>::value>> +queue(from_range_t, _Range&&, _Alloc) + -> queue<ranges::range_value_t<_Range>, deque<ranges::range_value_t<_Range>, _Alloc>>; #endif template <class _Tp, class _Container> @@ -475,6 +554,17 @@ operator<=(const queue<_Tp, _Container>& __x,const queue<_Tp, _Container>& __y) return !(__y < __x); } +#if _LIBCPP_STD_VER >= 20 + +template <class _Tp, three_way_comparable _Container> +_LIBCPP_HIDE_FROM_ABI compare_three_way_result_t<_Container> +operator<=>(const queue<_Tp, _Container>& __x, const queue<_Tp, _Container>& __y) { + // clang 16 bug: declaring `friend operator<=>` causes "use of overloaded operator '*' is ambiguous" errors + return __x.__get_container() <=> __y.__get_container(); +} + +#endif + template <class _Tp, class _Container> inline _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_swappable<_Container>::value, void> @@ -544,20 +634,31 @@ public: _LIBCPP_INLINE_VISIBILITY priority_queue(const value_compare& __comp, container_type&& __c); #endif - template <class _InputIter, class = __enable_if_t<__is_cpp17_input_iterator<_InputIter>::value> > + template <class _InputIter, class = __enable_if_t<__has_input_iterator_category<_InputIter>::value> > _LIBCPP_INLINE_VISIBILITY priority_queue(_InputIter __f, _InputIter __l, const value_compare& __comp = value_compare()); - template <class _InputIter, class = __enable_if_t<__is_cpp17_input_iterator<_InputIter>::value> > + template <class _InputIter, class = __enable_if_t<__has_input_iterator_category<_InputIter>::value> > _LIBCPP_INLINE_VISIBILITY priority_queue(_InputIter __f, _InputIter __l, const value_compare& __comp, const container_type& __c); #ifndef _LIBCPP_CXX03_LANG - template <class _InputIter, class = __enable_if_t<__is_cpp17_input_iterator<_InputIter>::value> > + template <class _InputIter, class = __enable_if_t<__has_input_iterator_category<_InputIter>::value> > _LIBCPP_INLINE_VISIBILITY priority_queue(_InputIter __f, _InputIter __l, const value_compare& __comp, container_type&& __c); #endif // _LIBCPP_CXX03_LANG + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + priority_queue(from_range_t, _Range&& __range, const value_compare& __comp = value_compare()) + : c(from_range, std::forward<_Range>(__range)), + comp(__comp) { + std::make_heap(c.begin(), c.end(), comp); + } +#endif + template <class _Alloc> _LIBCPP_INLINE_VISIBILITY explicit priority_queue(const _Alloc& __a, @@ -587,31 +688,55 @@ public: __enable_if_t<uses_allocator<container_type, _Alloc>::value>* = 0); #endif // _LIBCPP_CXX03_LANG - template <class _InputIter, class _Alloc, class = __enable_if_t<__is_cpp17_input_iterator<_InputIter>::value> > + template <class _InputIter, class _Alloc, class = __enable_if_t<__has_input_iterator_category<_InputIter>::value> > _LIBCPP_INLINE_VISIBILITY priority_queue(_InputIter __f, _InputIter __l, const _Alloc& __a, __enable_if_t<uses_allocator<container_type, _Alloc>::value>* = 0); - template <class _InputIter, class _Alloc, class = __enable_if_t<__is_cpp17_input_iterator<_InputIter>::value> > + template <class _InputIter, class _Alloc, class = __enable_if_t<__has_input_iterator_category<_InputIter>::value> > _LIBCPP_INLINE_VISIBILITY priority_queue(_InputIter __f, _InputIter __l, const value_compare& __comp, const _Alloc& __a, __enable_if_t<uses_allocator<container_type, _Alloc>::value>* = 0); - template <class _InputIter, class _Alloc, class = __enable_if_t<__is_cpp17_input_iterator<_InputIter>::value> > + template <class _InputIter, class _Alloc, class = __enable_if_t<__has_input_iterator_category<_InputIter>::value> > _LIBCPP_INLINE_VISIBILITY priority_queue(_InputIter __f, _InputIter __l, const value_compare& __comp, const container_type& __c, const _Alloc& __a, __enable_if_t<uses_allocator<container_type, _Alloc>::value>* = 0); #ifndef _LIBCPP_CXX03_LANG - template <class _InputIter, class _Alloc, class = __enable_if_t<__is_cpp17_input_iterator<_InputIter>::value> > + template <class _InputIter, class _Alloc, class = __enable_if_t<__has_input_iterator_category<_InputIter>::value> > _LIBCPP_INLINE_VISIBILITY priority_queue(_InputIter __f, _InputIter __l, const value_compare& __comp, container_type&& __c, const _Alloc& __a, __enable_if_t<uses_allocator<container_type, _Alloc>::value>* = 0); #endif // _LIBCPP_CXX03_LANG +#if _LIBCPP_STD_VER >= 23 + + template <_ContainerCompatibleRange<_Tp> _Range, + class _Alloc, + class = enable_if_t<uses_allocator<_Container, _Alloc>::value>> + _LIBCPP_HIDE_FROM_ABI + priority_queue(from_range_t, _Range&& __range, const value_compare& __comp, const _Alloc& __a) + : c(from_range, std::forward<_Range>(__range), __a), + comp(__comp) { + std::make_heap(c.begin(), c.end(), comp); + } + + template <_ContainerCompatibleRange<_Tp> _Range, + class _Alloc, + class = enable_if_t<uses_allocator<_Container, _Alloc>::value>> + _LIBCPP_HIDE_FROM_ABI + priority_queue(from_range_t, _Range&& __range, const _Alloc& __a) + : c(from_range, std::forward<_Range>(__range), __a), + comp() { + std::make_heap(c.begin(), c.end(), comp); + } + +#endif + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool empty() const {return c.empty();} _LIBCPP_INLINE_VISIBILITY @@ -624,6 +749,23 @@ public: #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void push(value_type&& __v); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void push_range(_Range&& __range) { + if constexpr (requires (container_type& __c) { + __c.append_range(std::forward<_Range>(__range)); + }) { + c.append_range(std::forward<_Range>(__range)); + } else { + ranges::copy(std::forward<_Range>(__range), std::back_inserter(c)); + } + + std::make_heap(c.begin(), c.end(), comp); + } +#endif + template <class... _Args> _LIBCPP_INLINE_VISIBILITY void emplace(_Args&&... __args); @@ -651,7 +793,7 @@ priority_queue(_Compare, _Container) template<class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>, class _Container = vector<__iter_value_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Compare>::value>, class = enable_if_t<!__is_allocator<_Container>::value> > @@ -669,7 +811,7 @@ priority_queue(_Compare, _Container, _Alloc) -> priority_queue<typename _Container::value_type, _Container, _Compare>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Allocator>::value> > priority_queue(_InputIterator, _InputIterator, _Allocator) @@ -678,7 +820,7 @@ priority_queue(_InputIterator, _InputIterator, _Allocator) less<__iter_value_type<_InputIterator>>>; template<class _InputIterator, class _Compare, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Compare>::value>, class = enable_if_t<__is_allocator<_Allocator>::value> > @@ -687,7 +829,7 @@ priority_queue(_InputIterator, _InputIterator, _Compare, _Allocator) vector<__iter_value_type<_InputIterator>, _Allocator>, _Compare>; template<class _InputIterator, class _Compare, class _Container, class _Alloc, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Compare>::value>, class = enable_if_t<!__is_allocator<_Container>::value>, class = enable_if_t<uses_allocator<_Container, _Alloc>::value> @@ -696,6 +838,31 @@ priority_queue(_InputIterator, _InputIterator, _Compare, _Container, _Alloc) -> priority_queue<typename _Container::value_type, _Container, _Compare>; #endif +#if _LIBCPP_STD_VER >= 23 + +template <ranges::input_range _Range, + class _Compare = less<ranges::range_value_t<_Range>>, + class = enable_if_t<!__is_allocator<_Compare>::value>> +priority_queue(from_range_t, _Range&&, _Compare = _Compare()) + -> priority_queue<ranges::range_value_t<_Range>, vector<ranges::range_value_t<_Range>>, _Compare>; + +template <ranges::input_range _Range, + class _Compare, + class _Alloc, + class = enable_if_t<!__is_allocator<_Compare>::value>, + class = enable_if_t<__is_allocator<_Alloc>::value>> +priority_queue(from_range_t, _Range&&, _Compare, _Alloc) + -> priority_queue<ranges::range_value_t<_Range>, vector<ranges::range_value_t<_Range>, _Alloc>, + _Compare>; + +template <ranges::input_range _Range, + class _Alloc, + class = enable_if_t<__is_allocator<_Alloc>::value>> +priority_queue(from_range_t, _Range&&, _Alloc) + -> priority_queue<ranges::range_value_t<_Range>, vector<ranges::range_value_t<_Range>, _Alloc>>; + +#endif + template <class _Tp, class _Container, class _Compare> inline priority_queue<_Tp, _Container, _Compare>::priority_queue(const _Compare& __comp, @@ -964,7 +1131,9 @@ _LIBCPP_END_NAMESPACE_STD #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> +# include <cstdlib> # include <functional> +# include <type_traits> #endif #endif // _LIBCPP_QUEUE diff --git a/libcxx/include/random b/libcxx/include/random index 5fe4906cb027..02d71ad6dd25 100644 --- a/libcxx/include/random +++ b/libcxx/include/random @@ -1734,6 +1734,7 @@ class piecewise_linear_distribution # include <concepts> # include <cstddef> # include <cstdint> +# include <cstdlib> # include <iosfwd> # include <limits> # include <numeric> diff --git a/libcxx/include/ranges b/libcxx/include/ranges index f999fa00c335..523f7cdcb360 100644 --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -49,6 +49,8 @@ namespace std::ranges { using range_reference_t = iter_reference_t<iterator_t<R>>; template<range R> using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>; + template <range R> + using range_common_reference_t = iter_common_reference_t<iterator_t<R>>; // [range.sized], sized ranges template<class> @@ -136,6 +138,16 @@ namespace std::ranges { inline constexpr auto values = elements<1>; } + // [range.utility.conv], range conversions + template<class C, input_range R, class... Args> requires (!view<C>) + constexpr C to(R&& r, Args&&... args); // Since C++23 + template<template<class...> class C, input_range R, class... Args> + constexpr auto to(R&& r, Args&&... args); // Since C++23 + template<class C, class... Args> requires (!view<C>) + constexpr auto to(Args&&... args); // Since C++23 + template<template<class...> class C, class... Args> + constexpr auto to(Args&&... args); // Since C++23 + // [range.empty], empty view template<class T> requires is_object_v<T> @@ -250,6 +262,19 @@ namespace std::ranges { template<class W, class Bound> inline constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true; + // [range.repeat], repeat view + template<class T> + concept integer-like-with-usable-difference-type = // exposition only + is-signed-integer-like<T> || (is-integer-like<T> && weakly_incrementable<T>); + + template<move_constructible T, semiregular Bound = unreachable_sentinel_t> + requires (is_object_v<T> && same_as<T, remove_cv_t<T>> && + (integer-like-with-usable-difference-type<Bound> || + same_as<Bound, unreachable_sentinel_t>)) + class repeat_view; + + namespace views { inline constexpr unspecified repeat = unspecified; } + // [range.join], join view template<input_range V> requires view<V> && input_range<range_reference_t<V>> @@ -292,13 +317,13 @@ namespace std::ranges { // [range.zip], zip view template<input_range... Views> requires (view<Views> && ...) && (sizeof...(Views) > 0) - class zip_view; // C++2b + class zip_view; // C++23 template<class... Views> - inline constexpr bool enable_borrowed_range<zip_view<Views...>> = // C++2b + inline constexpr bool enable_borrowed_range<zip_view<Views...>> = // C++23 (enable_borrowed_range<Views> && ...); - namespace views { inline constexpr unspecified zip = unspecified; } // C++2b + namespace views { inline constexpr unspecified zip = unspecified; } // C++23 // [range.as.rvalue] template <view V> @@ -337,6 +362,9 @@ namespace std { struct tuple_element<1, const ranges::subrange<I, S, K>> { using type = S; }; + + struct from_range_t { explicit from_range_t() = default; }; // Since C++23 + inline constexpr from_range_t from_range{}; // Since C++23 } */ @@ -358,12 +386,14 @@ namespace std { #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> #include <__ranges/filter_view.h> +#include <__ranges/from_range.h> #include <__ranges/iota_view.h> #include <__ranges/join_view.h> #include <__ranges/lazy_split_view.h> #include <__ranges/rbegin.h> #include <__ranges/ref_view.h> #include <__ranges/rend.h> +#include <__ranges/repeat_view.h> #include <__ranges/reverse_view.h> #include <__ranges/single_view.h> #include <__ranges/size.h> @@ -371,11 +401,11 @@ namespace std { #include <__ranges/subrange.h> #include <__ranges/take_view.h> #include <__ranges/take_while_view.h> +#include <__ranges/to.h> #include <__ranges/transform_view.h> #include <__ranges/view_interface.h> #include <__ranges/views.h> #include <__ranges/zip_view.h> -#include <type_traits> #include <version> #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) @@ -390,11 +420,16 @@ namespace std { #include <iterator> // [tuple.helper] -#include <__tuple_dir/tuple_element.h> -#include <__tuple_dir/tuple_size.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_size.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstdlib> +# include <type_traits> +#endif + #endif // _LIBCPP_RANGES diff --git a/libcxx/include/ratio b/libcxx/include/ratio index 3969a392f3c6..c9637ab818cd 100644 --- a/libcxx/include/ratio +++ b/libcxx/include/ratio @@ -40,6 +40,8 @@ template <class R1, class R2> struct ratio_greater; template <class R1, class R2> struct ratio_greater_equal; // convenience SI typedefs +using quecto = ratio <1, 1'000'000'000'000'000'000'000'000'000'000>; // Since C++26; not supported +using ronto = ratio <1, 1'000'000'000'000'000'000'000'000'000>; // Since C++26; not supported typedef ratio<1, 1000000000000000000000000> yocto; // not supported typedef ratio<1, 1000000000000000000000> zepto; // not supported typedef ratio<1, 1000000000000000000> atto; @@ -60,6 +62,8 @@ typedef ratio< 1000000000000000, 1> peta; typedef ratio< 1000000000000000000, 1> exa; typedef ratio< 1000000000000000000000, 1> zetta; // not supported typedef ratio<1000000000000000000000000, 1> yotta; // not supported +using ronna = ratio <1'000'000'000'000'000'000'000'000'000, 1>; // Since C++26; not supported +using quetta = ratio <1'000'000'000'000'000'000'000'000'000'000, 1>; // Since C++26; not supported // 20.11.5, ratio comparison template <class R1, class R2> inline constexpr bool ratio_equal_v @@ -501,7 +505,7 @@ struct __ratio_gcd __static_lcm<_R1::den, _R2::den>::value> type; }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _R1, class _R2> inline constexpr bool ratio_equal_v = ratio_equal<_R1, _R2>::value; diff --git a/libcxx/include/regex b/libcxx/include/regex index 06c017fcce38..be1bce10ebd1 100644 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -13,6 +13,7 @@ /* regex synopsis +#include <compare> #include <initializer_list> namespace std @@ -225,6 +226,8 @@ public: int compare(const sub_match& s) const; int compare(const string_type& s) const; int compare(const value_type* s) const; + + void swap(sub_match& s) noexcept(see below); }; typedef sub_match<const char*> csub_match; @@ -237,50 +240,54 @@ template <class BiIter> operator==(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); template <class BiIter> + auto + operator<=>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); // Since C++20 + + template <class BiIter> // Removed in C++20 bool operator!=(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator<(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator<=(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator>=(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); -template <class BiIter, class ST, class SA> +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator==(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs); -template <class BiIter, class ST, class SA> +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator!=(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs); -template <class BiIter, class ST, class SA> +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator<(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs); -template <class BiIter, class ST, class SA> +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator>(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs); -template <class BiIter, class ST, class SA> +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator>=(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs); -template <class BiIter, class ST, class SA> +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator<=(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs, const sub_match<BiIter>& rhs); @@ -290,56 +297,62 @@ template <class BiIter, class ST, class SA> operator==(const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); -template <class BiIter, class ST, class SA> +template <class BiIter, class ST, class SA> // Since C++20 + auto + operator<=>(const sub_match<BiIter>& lhs, + const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); + +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator!=(const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); -template <class BiIter, class ST, class SA> +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator<(const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); -template <class BiIter, class ST, class SA> - bool operator>(const sub_match<BiIter>& lhs, +template <class BiIter, class ST, class SA> // Removed in C++20 + bool + operator>(const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); -template <class BiIter, class ST, class SA> +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator>=(const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); -template <class BiIter, class ST, class SA> +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator<=(const sub_match<BiIter>& lhs, const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator==(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator!=(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator<(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator>(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator>=(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator<=(typename iterator_traits<BiIter>::value_type const* lhs, const sub_match<BiIter>& rhs); @@ -349,57 +362,62 @@ template <class BiIter> operator==(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs); -template <class BiIter> +template <class BiIter> // Since C++20 + auto + operator<=>(const sub_match<BiIter>& lhs, + typename iterator_traits<BiIter>::value_type const* rhs); + +template <class BiIter, class ST, class SA> // Removed in C++20 bool operator!=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator<(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator>(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator>=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator<=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const* rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator==(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator!=(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator<(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator>(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator>=(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator<=(typename iterator_traits<BiIter>::value_type const& lhs, const sub_match<BiIter>& rhs); @@ -409,27 +427,32 @@ template <class BiIter> operator==(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs); -template <class BiIter> +template <class BiIter> // Since C++20 + auto + operator<=>(const sub_match<BiIter>& lhs, + typename iterator_traits<BiIter>::value_type const& rhs); + +template <class BiIter> // Removed in C++20 bool operator!=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator<(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator>(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator>=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs); -template <class BiIter> +template <class BiIter> // Removed in C++20 bool operator<=(const sub_match<BiIter>& lhs, typename iterator_traits<BiIter>::value_type const& rhs); @@ -520,7 +543,7 @@ template <class BidirectionalIterator, class Allocator> operator==(const match_results<BidirectionalIterator, Allocator>& m1, const match_results<BidirectionalIterator, Allocator>& m2); -template <class BidirectionalIterator, class Allocator> +template <class BidirectionalIterator, class Allocator> // Removed in C++20 bool operator!=(const match_results<BidirectionalIterator, Allocator>& m1, const match_results<BidirectionalIterator, Allocator>& m2); @@ -687,7 +710,8 @@ public: regex_iterator& operator=(const regex_iterator&); bool operator==(const regex_iterator&) const; - bool operator!=(const regex_iterator&) const; + bool operator==(default_sentinel_t) const { return *this == regex_iterator(); } // since C++20 + bool operator!=(const regex_iterator&) const; // Removed in C++20 const value_type& operator*() const; const value_type* operator->() const; @@ -745,7 +769,8 @@ public: regex_token_iterator& operator=(const regex_token_iterator&); bool operator==(const regex_token_iterator&) const; - bool operator!=(const regex_token_iterator&) const; + bool operator==(default_sentinel_t) const { return *this == regex_token_iterator(); } // since C++20 + bool operator!=(const regex_token_iterator&) const; // Removed in C++20 const value_type& operator*() const; const value_type* operator->() const; @@ -765,15 +790,19 @@ typedef regex_token_iterator<wstring::const_iterator> wsregex_token_iterator; #include <__algorithm/find.h> #include <__algorithm/search.h> #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> #include <__config> #include <__iterator/back_insert_iterator.h> +#include <__iterator/default_sentinel.h> #include <__iterator/wrap_iter.h> #include <__locale> +#include <__memory/shared_ptr.h> #include <__memory_resource/polymorphic_allocator.h> +#include <__type_traits/is_swappable.h> #include <__utility/move.h> #include <__utility/pair.h> #include <__utility/swap.h> -#include <cstring> +#include <__verbose_abort> #include <deque> #include <stdexcept> #include <string> @@ -996,13 +1025,13 @@ enum error_type } // namespace regex_constants -class _LIBCPP_EXCEPTION_ABI regex_error +class _LIBCPP_EXPORTED_FROM_ABI regex_error : public runtime_error { regex_constants::error_type __code_; public: explicit regex_error(regex_constants::error_type __ecode); - regex_error(const regex_error&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI regex_error(const regex_error&) _NOEXCEPT = default; ~regex_error() _NOEXCEPT override; _LIBCPP_INLINE_VISIBILITY regex_constants::error_type code() const {return __code_;} @@ -1012,10 +1041,10 @@ template <regex_constants::error_type _Ev> _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_regex_error() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw regex_error(_Ev); #else - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("regex_error was thrown in -fno-exceptions mode"); #endif } @@ -1221,7 +1250,7 @@ regex_traits<_CharT>::__transform_primary(_ForwardIterator __f, // lookup_collatename is very FreeBSD-specific -_LIBCPP_FUNC_VIS string __get_collation_name(const char* __s); +_LIBCPP_EXPORTED_FROM_ABI string __get_collation_name(const char* __s); template <class _CharT> template <class _ForwardIterator> @@ -1284,8 +1313,7 @@ regex_traits<_CharT>::__lookup_collatename(_ForwardIterator __f, // lookup_classname -regex_traits<char>::char_class_type _LIBCPP_FUNC_VIS -__get_classname(const char* __s, bool __icase); +regex_traits<char>::char_class_type _LIBCPP_EXPORTED_FROM_ABI __get_classname(const char* __s, bool __icase); template <class _CharT> template <class _ForwardIterator> @@ -1467,7 +1495,7 @@ public: _LIBCPP_INLINE_VISIBILITY __end_state() {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -1533,7 +1561,7 @@ public: explicit __empty_state(__node<_CharT>* __s) : base(__s) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -1559,7 +1587,7 @@ public: explicit __empty_non_own_state(__node<_CharT>* __s) : base(__s) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -1585,7 +1613,7 @@ public: explicit __repeat_one_loop(__node<_CharT>* __s) : base(__s) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -1611,7 +1639,7 @@ public: explicit __owns_two_states(__node<_CharT>* __s1, base* __s2) : base(__s1), __second_(__s2) {} - virtual ~__owns_two_states(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual ~__owns_two_states(); _LIBCPP_INLINE_VISIBILITY base* second() const {return __second_;} @@ -1654,8 +1682,8 @@ public: __mexp_begin_(__mexp_begin), __mexp_end_(__mexp_end), __greedy_(__greedy) {} - virtual void __exec(__state& __s) const; - virtual void __exec_split(bool __second, __state& __s) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state& __s) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec_split(bool __second, __state& __s) const; private: _LIBCPP_INLINE_VISIBILITY @@ -1747,8 +1775,8 @@ public: __owns_one_state<_CharT>* __s2) : base(__s1, __s2) {} - virtual void __exec(__state& __s) const; - virtual void __exec_split(bool __second, __state& __s) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state& __s) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec_split(bool __second, __state& __s) const; }; template <class _CharT> @@ -1785,7 +1813,7 @@ public: explicit __begin_marked_subexpression(unsigned __mexp, __node<_CharT>* __s) : base(__s), __mexp_(__mexp) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -1813,7 +1841,7 @@ public: explicit __end_marked_subexpression(unsigned __mexp, __node<_CharT>* __s) : base(__s), __mexp_(__mexp) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -1842,7 +1870,7 @@ public: explicit __back_ref(unsigned __mexp, __node<_CharT>* __s) : base(__s), __mexp_(__mexp) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -1893,7 +1921,7 @@ public: __node<_CharT>* __s) : base(__s), __traits_(__traits), __mexp_(__mexp) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT, class _Traits> @@ -1948,7 +1976,7 @@ public: __node<_CharT>* __s) : base(__s), __traits_(__traits), __mexp_(__mexp) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT, class _Traits> @@ -2003,7 +2031,7 @@ public: __node<_CharT>* __s) : base(__s), __traits_(__traits), __invert_(__invert) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT, class _Traits> @@ -2079,7 +2107,7 @@ public: __l_anchor_multiline(bool __multiline, __node<_CharT>* __s) : base(__s), __multiline_(__multiline) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -2123,7 +2151,7 @@ public: __r_anchor_multiline(bool __multiline, __node<_CharT>* __s) : base(__s), __multiline_(__multiline) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -2163,7 +2191,7 @@ public: __match_any(__node<_CharT>* __s) : base(__s) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -2201,9 +2229,9 @@ public: void __exec(__state&) const override; }; -template <> _LIBCPP_FUNC_VIS void __match_any_but_newline<char>::__exec(__state&) const; +template <> _LIBCPP_EXPORTED_FROM_ABI void __match_any_but_newline<char>::__exec(__state&) const; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> _LIBCPP_FUNC_VIS void __match_any_but_newline<wchar_t>::__exec(__state&) const; +template <> _LIBCPP_EXPORTED_FROM_ABI void __match_any_but_newline<wchar_t>::__exec(__state&) const; #endif // __match_char @@ -2225,7 +2253,7 @@ public: __match_char(_CharT __c, __node<_CharT>* __s) : base(__s), __c_(__c) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT> @@ -2265,7 +2293,7 @@ public: __match_char_icase(const _Traits& __traits, _CharT __c, __node<_CharT>* __s) : base(__s), __traits_(__traits), __c_(__traits.translate_nocase(__c)) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT, class _Traits> @@ -2306,7 +2334,7 @@ public: __match_char_collate(const _Traits& __traits, _CharT __c, __node<_CharT>* __s) : base(__s), __traits_(__traits), __c_(__traits.translate(__c)) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT, class _Traits> @@ -2361,7 +2389,7 @@ public: __negate_(__negate), __icase_(__icase), __collate_(__collate), __might_have_digraph_(__traits_.getloc().name() != "C") {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; _LIBCPP_INLINE_VISIBILITY bool __negated() const {return __negate_;} @@ -2750,7 +2778,7 @@ public: template <class _InputIterator> _LIBCPP_INLINE_VISIBILITY - typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value, basic_regex&>::type + typename enable_if<__has_exactly_input_iterator_category<_InputIterator>::value, basic_regex&>::type assign(_InputIterator __first, _InputIterator __last, flag_type __f = regex_constants::ECMAScript) { @@ -2774,7 +2802,7 @@ public: _LIBCPP_INLINE_VISIBILITY typename enable_if < - __is_cpp17_forward_iterator<_ForwardIterator>::value, + __has_forward_iterator_category<_ForwardIterator>::value, basic_regex& >::type assign(_ForwardIterator __first, _ForwardIterator __last, @@ -3082,7 +3110,7 @@ private: #if _LIBCPP_STD_VER >= 17 template <class _ForwardIterator, - class = typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value, nullptr_t>::type + class = typename enable_if<__has_forward_iterator_category<_ForwardIterator>::value, nullptr_t>::type > basic_regex(_ForwardIterator, _ForwardIterator, regex_constants::syntax_option_type = regex_constants::ECMAScript) @@ -3153,7 +3181,7 @@ public: __lookahead(const basic_regex<_CharT, _Traits>& __exp, bool __invert, __node<_CharT>* __s, unsigned __mexp) : base(__s), __exp_(__exp), __mexp_(__mexp), __invert_(__invert) {} - virtual void __exec(__state&) const; + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __exec(__state&) const; }; template <class _CharT, class _Traits> @@ -4131,9 +4159,9 @@ basic_regex<_CharT, _Traits>::__parse_equivalence_class(_ForwardIterator __first { // Found [= // This means =] must exist - value_type _Equal_close[2] = {'=', ']'}; - _ForwardIterator __temp = _VSTD::search(__first, __last, _Equal_close, - _Equal_close+2); + value_type __equal_close[2] = {'=', ']'}; + _ForwardIterator __temp = _VSTD::search(__first, __last, __equal_close, + __equal_close+2); if (__temp == __last) __throw_regex_error<regex_constants::error_brack>(); // [__first, __temp) contains all text in [= ... =] @@ -4173,9 +4201,9 @@ basic_regex<_CharT, _Traits>::__parse_character_class(_ForwardIterator __first, { // Found [: // This means :] must exist - value_type _Colon_close[2] = {':', ']'}; - _ForwardIterator __temp = _VSTD::search(__first, __last, _Colon_close, - _Colon_close+2); + value_type __colon_close[2] = {':', ']'}; + _ForwardIterator __temp = _VSTD::search(__first, __last, __colon_close, + __colon_close+2); if (__temp == __last) __throw_regex_error<regex_constants::error_brack>(); // [__first, __temp) contains all text in [: ... :] @@ -4198,9 +4226,9 @@ basic_regex<_CharT, _Traits>::__parse_collating_symbol(_ForwardIterator __first, { // Found [. // This means .] must exist - value_type _Dot_close[2] = {'.', ']'}; - _ForwardIterator __temp = _VSTD::search(__first, __last, _Dot_close, - _Dot_close+2); + value_type __dot_close[2] = {'.', ']'}; + _ForwardIterator __temp = _VSTD::search(__first, __last, __dot_close, + __dot_close+2); if (__temp == __last) __throw_regex_error<regex_constants::error_brack>(); // [__first, __temp) contains all text in [. ... .] @@ -5009,6 +5037,16 @@ public: _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {return str().compare(__s);} + + _LIBCPP_HIDE_FROM_ABI + void swap(sub_match& __s) +#ifndef _LIBCPP_CXX03_LANG + _NOEXCEPT(__is_nothrow_swappable<_BidirectionalIterator>::value) +#endif // _LIBCPP_CXX03_LANG + { + this->pair<_BidirectionalIterator, _BidirectionalIterator>::swap(__s); + std::swap(matched, __s.matched); + } }; template <class _BiIter> @@ -5019,6 +5057,15 @@ operator==(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y) return __x.compare(__y) == 0; } +#if _LIBCPP_STD_VER >= 20 +template<class _BiIter> +using __sub_match_cat = compare_three_way_result_t<basic_string<typename iterator_traits<_BiIter>::value_type>>; + +template <class _BiIter> +_LIBCPP_HIDE_FROM_ABI auto operator<=>(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y) { + return static_cast<__sub_match_cat<_BiIter>>(__x.compare(__y) <=> 0); +} +#else // _LIBCPP_STD_VER >= 20 template <class _BiIter> inline _LIBCPP_INLINE_VISIBILITY bool @@ -5111,6 +5158,7 @@ operator<=(const basic_string<typename iterator_traits<_BiIter>::value_type, _ST { return !(__y < __x); } +#endif // _LIBCPP_STD_VER >= 20 template <class _BiIter, class _ST, class _SA> inline _LIBCPP_INLINE_VISIBILITY @@ -5121,6 +5169,14 @@ operator==(const sub_match<_BiIter>& __x, return __x.compare(typename sub_match<_BiIter>::string_type(__y.data(), __y.size())) == 0; } +#if _LIBCPP_STD_VER >= 20 +template <class _BiIter, class _ST, class _SA> +_LIBCPP_HIDE_FROM_ABI auto operator<=>( + const sub_match<_BiIter>& __x, const basic_string<typename iterator_traits<_BiIter>::value_type, _ST, _SA>& __y) { + return static_cast<__sub_match_cat<_BiIter>>( + __x.compare(typename sub_match<_BiIter>::string_type(__y.data(), __y.size())) <=> 0); +} +#else // _LIBCPP_STD_VER >= 20 template <class _BiIter, class _ST, class _SA> inline _LIBCPP_INLINE_VISIBILITY bool @@ -5218,6 +5274,7 @@ operator<=(typename iterator_traits<_BiIter>::value_type const* __x, { return !(__y < __x); } +#endif // _LIBCPP_STD_VER >= 20 template <class _BiIter> inline _LIBCPP_INLINE_VISIBILITY @@ -5228,6 +5285,13 @@ operator==(const sub_match<_BiIter>& __x, return __x.compare(__y) == 0; } +#if _LIBCPP_STD_VER >= 20 +template <class _BiIter> +_LIBCPP_HIDE_FROM_ABI auto +operator<=>(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const* __y) { + return static_cast<__sub_match_cat<_BiIter>>(__x.compare(__y) <=> 0); +} +#else // _LIBCPP_STD_VER >= 20 template <class _BiIter> inline _LIBCPP_INLINE_VISIBILITY bool @@ -5328,6 +5392,7 @@ operator<=(typename iterator_traits<_BiIter>::value_type const& __x, { return !(__y < __x); } +#endif // _LIBCPP_STD_VER >= 20 template <class _BiIter> inline _LIBCPP_INLINE_VISIBILITY @@ -5339,6 +5404,14 @@ operator==(const sub_match<_BiIter>& __x, return __x.compare(string_type(1, __y)) == 0; } +#if _LIBCPP_STD_VER >= 20 +template <class _BiIter> +_LIBCPP_HIDE_FROM_ABI auto +operator<=>(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const& __y) { + using string_type = basic_string<typename iterator_traits<_BiIter>::value_type>; + return static_cast<__sub_match_cat<_BiIter>>(__x.compare(string_type(1, __y)) <=> 0); +} +#else // _LIBCPP_STD_VER >= 20 template <class _BiIter> inline _LIBCPP_INLINE_VISIBILITY bool @@ -5384,6 +5457,7 @@ operator<=(const sub_match<_BiIter>& __x, { return !(__y < __x); } +#endif // _LIBCPP_STD_VER >= 20 template <class _CharT, class _ST, class _BiIter> inline _LIBCPP_INLINE_VISIBILITY @@ -5460,38 +5534,38 @@ public: _LIBCPP_INLINE_VISIBILITY difference_type length(size_type __sub = 0) const { - _LIBCPP_ASSERT(ready(), "match_results::length() called when not ready"); + _LIBCPP_ASSERT_UNCATEGORIZED(ready(), "match_results::length() called when not ready"); return (*this)[__sub].length(); } _LIBCPP_INLINE_VISIBILITY difference_type position(size_type __sub = 0) const { - _LIBCPP_ASSERT(ready(), "match_results::position() called when not ready"); + _LIBCPP_ASSERT_UNCATEGORIZED(ready(), "match_results::position() called when not ready"); return _VSTD::distance(__position_start_, (*this)[__sub].first); } _LIBCPP_INLINE_VISIBILITY string_type str(size_type __sub = 0) const { - _LIBCPP_ASSERT(ready(), "match_results::str() called when not ready"); + _LIBCPP_ASSERT_UNCATEGORIZED(ready(), "match_results::str() called when not ready"); return (*this)[__sub].str(); } _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const { - _LIBCPP_ASSERT(ready(), "match_results::operator[]() called when not ready"); + _LIBCPP_ASSERT_UNCATEGORIZED(ready(), "match_results::operator[]() called when not ready"); return __n < __matches_.size() ? __matches_[__n] : __unmatched_; } _LIBCPP_INLINE_VISIBILITY const_reference prefix() const { - _LIBCPP_ASSERT(ready(), "match_results::prefix() called when not ready"); + _LIBCPP_ASSERT_UNCATEGORIZED(ready(), "match_results::prefix() called when not ready"); return __prefix_; } _LIBCPP_INLINE_VISIBILITY const_reference suffix() const { - _LIBCPP_ASSERT(ready(), "match_results::suffix() called when not ready"); + _LIBCPP_ASSERT_UNCATEGORIZED(ready(), "match_results::suffix() called when not ready"); return __suffix_; } @@ -5631,7 +5705,7 @@ match_results<_BidirectionalIterator, _Allocator>::format(_OutputIter __output_i const char_type* __fmt_first, const char_type* __fmt_last, regex_constants::match_flag_type __flags) const { - _LIBCPP_ASSERT(ready(), "match_results::format() called when not ready"); + _LIBCPP_ASSERT_UNCATEGORIZED(ready(), "match_results::format() called when not ready"); if (__flags & regex_constants::format_sed) { for (; __fmt_first != __fmt_last; ++__fmt_first) @@ -5747,6 +5821,7 @@ operator==(const match_results<_BidirectionalIterator, _Allocator>& __x, __x.__suffix_ == __y.__suffix_; } +#if _LIBCPP_STD_VER < 20 template <class _BidirectionalIterator, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY bool @@ -5755,6 +5830,7 @@ operator!=(const match_results<_BidirectionalIterator, _Allocator>& __x, { return !(__x == __y); } +#endif template <class _BidirectionalIterator, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY @@ -5861,7 +5937,7 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_nosubs( { deque<__state> __states; ptrdiff_t __highest_j = 0; - ptrdiff_t _Np = _VSTD::distance(__first, __last); + ptrdiff_t __np = _VSTD::distance(__first, __last); __node* __st = __start_.get(); if (__st) { @@ -5904,7 +5980,7 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_nosubs( if (!__matched || __highest_j < __s.__current_ - __s.__first_) __highest_j = __s.__current_ - __s.__first_; __matched = true; - if (__highest_j == _Np) + if (__highest_j == __np) __states.clear(); else __states.pop_back(); @@ -5956,7 +6032,7 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_subs( vector<__state> __states; __state __best_state; ptrdiff_t __highest_j = 0; - ptrdiff_t _Np = _VSTD::distance(__first, __last); + ptrdiff_t __np = _VSTD::distance(__first, __last); __node* __st = __start_.get(); if (__st) { @@ -6008,7 +6084,7 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_subs( __best_state = __s; } __matched = true; - if (__highest_j == _Np) + if (__highest_j == __np) __states.clear(); else __states.pop_back(); @@ -6214,7 +6290,7 @@ regex_search(const basic_string<_CharT, _ST, _SA>& __s, return __r; } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _ST, class _SA, class _Ap, class _Cp, class _Tp> bool regex_search(const basic_string<_Cp, _ST, _SA>&& __s, @@ -6277,7 +6353,7 @@ regex_match(const basic_string<_CharT, _ST, _SA>& __s, return _VSTD::regex_match(__s.begin(), __s.end(), __m, __e, __flags); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _ST, class _SA, class _Allocator, class _CharT, class _Traits> inline _LIBCPP_INLINE_VISIBILITY bool @@ -6350,16 +6426,21 @@ public: const regex_type& __re, regex_constants::match_flag_type __m = regex_constants::match_default); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 regex_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type&& __re, regex_constants::match_flag_type __m = regex_constants::match_default) = delete; #endif - bool operator==(const regex_iterator& __x) const; + _LIBCPP_HIDE_FROM_ABI bool operator==(const regex_iterator& __x) const; +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI bool operator==(default_sentinel_t) const { return *this == regex_iterator(); } +#endif +#if _LIBCPP_STD_VER < 20 _LIBCPP_INLINE_VISIBILITY bool operator!=(const regex_iterator& __x) const {return !(*this == __x);} +#endif _LIBCPP_INLINE_VISIBILITY reference operator*() const {return __match_;} @@ -6482,7 +6563,7 @@ public: const regex_type& __re, int __submatch = 0, regex_constants::match_flag_type __m = regex_constants::match_default); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type&& __re, int __submatch = 0, regex_constants::match_flag_type __m = @@ -6493,7 +6574,7 @@ public: const regex_type& __re, const vector<int>& __submatches, regex_constants::match_flag_type __m = regex_constants::match_default); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type&& __re, const vector<int>& __submatches, regex_constants::match_flag_type __m = @@ -6507,7 +6588,7 @@ public: regex_constants::match_flag_type __m = regex_constants::match_default); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, const regex_type&& __re, initializer_list<int> __submatches, @@ -6522,7 +6603,7 @@ public: const int (&__submatches)[_Np], regex_constants::match_flag_type __m = regex_constants::match_default); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <size_t _Np> regex_token_iterator(_BidirectionalIterator __a, _BidirectionalIterator __b, @@ -6535,9 +6616,16 @@ public: regex_token_iterator(const regex_token_iterator&); regex_token_iterator& operator=(const regex_token_iterator&); - bool operator==(const regex_token_iterator& __x) const; + _LIBCPP_HIDE_FROM_ABI bool operator==(const regex_token_iterator& __x) const; +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI bool operator==(default_sentinel_t) const { + return *this == regex_token_iterator(); + } +#endif +#if _LIBCPP_STD_VER < 20 _LIBCPP_INLINE_VISIBILITY bool operator!=(const regex_token_iterator& __x) const {return !(*this == __x);} +#endif _LIBCPP_INLINE_VISIBILITY const value_type& operator*() const {return *__result_;} @@ -6844,18 +6932,18 @@ regex_replace(const _CharT* __s, _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template <class _BidirT> -using match_results = std::match_results<_BidirT, polymorphic_allocator<std::sub_match<_BidirT>>>; +using match_results _LIBCPP_AVAILABILITY_PMR = std::match_results<_BidirT, polymorphic_allocator<std::sub_match<_BidirT>>>; -using cmatch = match_results<const char*>; -using smatch = match_results<std::pmr::string::const_iterator>; +using cmatch _LIBCPP_AVAILABILITY_PMR = match_results<const char*>; +using smatch _LIBCPP_AVAILABILITY_PMR = match_results<std::pmr::string::const_iterator>; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -using wcmatch = match_results<const wchar_t*>; -using wsmatch = match_results<std::pmr::wstring::const_iterator>; +using wcmatch _LIBCPP_AVAILABILITY_PMR = match_results<const wchar_t*>; +using wsmatch _LIBCPP_AVAILABILITY_PMR = match_results<std::pmr::wstring::const_iterator>; #endif } // namespace pmr _LIBCPP_END_NAMESPACE_STD @@ -6866,9 +6954,11 @@ _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <atomic> # include <concepts> +# include <cstdlib> # include <iosfwd> # include <iterator> # include <new> +# include <type_traits> # include <typeinfo> # include <utility> #endif diff --git a/libcxx/include/scoped_allocator b/libcxx/include/scoped_allocator index 461c67e9b656..90c6f84b7de7 100644 --- a/libcxx/include/scoped_allocator +++ b/libcxx/include/scoped_allocator @@ -103,7 +103,7 @@ template <class OuterA1, class OuterA2, class... InnerAllocs> template <class OuterA1, class OuterA2, class... InnerAllocs> bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, - const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept; + const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept; // removed in C++20 } // std @@ -130,6 +130,9 @@ template <class OuterA1, class OuterA2, class... InnerAllocs> # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD #if !defined(_LIBCPP_CXX03_LANG) @@ -531,7 +534,7 @@ public: __p, _VSTD::forward<_Args>(__args)...);} template <class _T1, class _T2, class... _Args1, class... _Args2> - void construct(pair<_T1, _T2>* __p, piecewise_construct_t, + _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, piecewise_construct_t, tuple<_Args1...> __x, tuple<_Args2...> __y) { typedef __outermost<outer_allocator_type> _OM; @@ -555,25 +558,25 @@ public: } template <class _T1, class _T2> - void construct(pair<_T1, _T2>* __p) + _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p) { construct(__p, piecewise_construct, tuple<>{}, tuple<>{}); } template <class _T1, class _T2, class _Up, class _Vp> - void construct(pair<_T1, _T2>* __p, _Up&& __x, _Vp&& __y) { + _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, _Up&& __x, _Vp&& __y) { construct(__p, piecewise_construct, _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__x)), _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__y))); } template <class _T1, class _T2, class _Up, class _Vp> - void construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) { + _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) { construct(__p, piecewise_construct, _VSTD::forward_as_tuple(__x.first), _VSTD::forward_as_tuple(__x.second)); } template <class _T1, class _T2, class _Up, class _Vp> - void construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) { + _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) { construct(__p, piecewise_construct, _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__x.first)), _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__x.second))); @@ -678,7 +681,7 @@ private: template <class...> friend class __scoped_allocator_storage; }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template<class _OuterAlloc, class... _InnerAllocs> scoped_allocator_adaptor(_OuterAlloc, _InnerAllocs...) -> scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>; @@ -703,6 +706,8 @@ operator==(const scoped_allocator_adaptor<_OuterA1, _InnerA0, _InnerAllocs...>& __a.inner_allocator() == __b.inner_allocator(); } +#if _LIBCPP_STD_VER <= 17 + template <class _OuterA1, class _OuterA2, class... _InnerAllocs> inline _LIBCPP_INLINE_VISIBILITY bool @@ -712,10 +717,14 @@ operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a, return !(__a == __b); } +#endif // _LIBCPP_STD_VER <= 17 + #endif // !defined(_LIBCPP_CXX03_LANG) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <atomic> # include <climits> diff --git a/libcxx/include/semaphore b/libcxx/include/semaphore index ddccb28dab47..971ca2f70adc 100644 --- a/libcxx/include/semaphore +++ b/libcxx/include/semaphore @@ -46,12 +46,15 @@ using binary_semaphore = counting_semaphore<1>; */ #include <__assert> // all public C++ headers provide the assertion handler +#include <__atomic/atomic_base.h> +#include <__atomic/atomic_sync.h> +#include <__atomic/memory_order.h> #include <__availability> #include <__chrono/time_point.h> #include <__config> #include <__thread/timed_backoff_policy.h> #include <__threading_support> -#include <atomic> +#include <cstddef> #include <limits> #include <version> @@ -78,6 +81,8 @@ functions. It avoids contention against users' own use of those facilities. */ +#define _LIBCPP_SEMAPHORE_MAX (numeric_limits<ptrdiff_t>::max()) + class __atomic_semaphore_base { __atomic_base<ptrdiff_t> __a_; @@ -90,9 +95,14 @@ public: _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void release(ptrdiff_t __update = 1) { - if(0 < __a_.fetch_add(__update, memory_order_release)) - ; - else if(__update > 1) + auto __old = __a_.fetch_add(__update, memory_order_release); + _LIBCPP_ASSERT_UNCATEGORIZED(__update <= _LIBCPP_SEMAPHORE_MAX - __old, "update is greater than the expected value"); + + if (__old > 0) + { + // Nothing to do + } + else if (__update > 1) __a_.notify_all(); else __a_.notify_one(); @@ -106,11 +116,11 @@ public: }; __cxx_atomic_wait(&__a_.__a_, __test_fn); } - template <class Rep, class Period> + template <class _Rep, class _Period> _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY - bool try_acquire_for(chrono::duration<Rep, Period> const& __rel_time) + bool try_acquire_for(chrono::duration<_Rep, _Period> const& __rel_time) { - if (__rel_time == chrono::duration<Rep, Period>::zero()) + if (__rel_time == chrono::duration<_Rep, _Period>::zero()) return try_acquire(); auto const __test_fn = [this]() { return try_acquire(); }; return std::__libcpp_thread_poll_with_backoff(__test_fn, __libcpp_timed_backoff_policy(), __rel_time); @@ -128,20 +138,30 @@ public: } }; -#define _LIBCPP_SEMAPHORE_MAX (numeric_limits<ptrdiff_t>::max()) - template<ptrdiff_t __least_max_value = _LIBCPP_SEMAPHORE_MAX> class counting_semaphore { __atomic_semaphore_base __semaphore_; public: + static_assert(__least_max_value >= 0, "The least maximum value must be a positive number"); + static constexpr ptrdiff_t max() noexcept { return __least_max_value; } _LIBCPP_INLINE_VISIBILITY - constexpr explicit counting_semaphore(ptrdiff_t __count) : __semaphore_(__count) { } + constexpr explicit counting_semaphore(ptrdiff_t __count) : __semaphore_(__count) + { + _LIBCPP_ASSERT_UNCATEGORIZED( + __count >= 0, + "counting_semaphore::counting_semaphore(ptrdiff_t): counting_semaphore cannot be " + "initialized with a negative value"); + _LIBCPP_ASSERT_UNCATEGORIZED( + __count <= max(), + "counting_semaphore::counting_semaphore(ptrdiff_t): counting_semaphore cannot be " + "initialized with a value greater than max()"); + } ~counting_semaphore() = default; counting_semaphore(const counting_semaphore&) = delete; @@ -150,6 +170,7 @@ public: _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY void release(ptrdiff_t __update = 1) { + _LIBCPP_ASSERT_UNCATEGORIZED(__update >= 0, "counting_semaphore:release called with a negative value"); __semaphore_.release(__update); } _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY @@ -157,9 +178,9 @@ public: { __semaphore_.acquire(); } - template<class Rep, class Period> + template<class _Rep, class _Period> _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY - bool try_acquire_for(chrono::duration<Rep, Period> const& __rel_time) + bool try_acquire_for(chrono::duration<_Rep, _Period> const& __rel_time) { return __semaphore_.try_acquire_for(chrono::duration_cast<chrono::nanoseconds>(__rel_time)); } @@ -168,15 +189,15 @@ public: { return __semaphore_.try_acquire(); } - template <class Clock, class Duration> + template <class _Clock, class _Duration> _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY - bool try_acquire_until(chrono::time_point<Clock, Duration> const& __abs_time) + bool try_acquire_until(chrono::time_point<_Clock, _Duration> const& __abs_time) { - auto const current = Clock::now(); - if (current >= __abs_time) + auto const __current = _Clock::now(); + if (__current >= __abs_time) return try_acquire(); else - return try_acquire_for(__abs_time - current); + return try_acquire_for(__abs_time - __current); } }; @@ -188,4 +209,8 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <atomic> +#endif + #endif //_LIBCPP_SEMAPHORE diff --git a/libcxx/include/set b/libcxx/include/set index 1154c4e9509c..e44f33e3d47b 100644 --- a/libcxx/include/set +++ b/libcxx/include/set @@ -56,6 +56,8 @@ public: template <class InputIterator> set(InputIterator first, InputIterator last, const value_compare& comp, const allocator_type& a); + template<container-compatible-range<value_type> R> + set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); // C++23 set(const set& s); set(set&& s) noexcept( @@ -70,6 +72,9 @@ public: template <class InputIterator> set(InputIterator first, InputIterator last, const allocator_type& a) : set(first, last, Compare(), a) {} // C++14 + template<container-compatible-range<value_type> R> + set(from_range_t, R&& rg, const Allocator& a)) + : set(from_range, std::forward<R>(rg), Compare(), a) { } // C++23 set(initializer_list<value_type> il, const allocator_type& a) : set(il, Compare(), a) {} // C++14 ~set(); @@ -114,6 +119,8 @@ public: iterator insert(const_iterator position, value_type&& v); template <class InputIterator> void insert(InputIterator first, InputIterator last); + template<container-compatible-range<value_type> R> + void insert_range(R&& rg); // C++23 void insert(initializer_list<value_type> il); node_type extract(const_iterator position); // C++17 @@ -190,6 +197,11 @@ set(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>; // C++17 +template<ranges::input_range R, class Compare = less<ranges::range_value_t<R>>, + class Allocator = allocator<ranges::range_value_t<R>>> + set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> set<ranges::range_value_t<R>, Compare, Allocator>; // C++23 + template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> set(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) -> set<Key, Compare, Allocator>; // C++17 @@ -199,6 +211,10 @@ set(InputIterator, InputIterator, Allocator) -> set<typename iterator_traits<InputIterator>::value_type, less<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17 +template<ranges::input_range R, class Allocator> + set(from_range_t, R&&, Allocator) + -> set<ranges::range_value_t<R>, less<ranges::range_value_t<R>>, Allocator>; // C++23 + template<class Key, class Allocator> set(initializer_list<Key>, Allocator) -> set<Key, less<Key>, Allocator>; // C++17 @@ -210,27 +226,31 @@ operator==(const set<Key, Compare, Allocator>& x, template <class Key, class Compare, class Allocator> bool operator< (const set<Key, Compare, Allocator>& x, - const set<Key, Compare, Allocator>& y); + const set<Key, Compare, Allocator>& y); // removed in C++20 template <class Key, class Compare, class Allocator> bool operator!=(const set<Key, Compare, Allocator>& x, - const set<Key, Compare, Allocator>& y); + const set<Key, Compare, Allocator>& y); // removed in C++20 template <class Key, class Compare, class Allocator> bool operator> (const set<Key, Compare, Allocator>& x, - const set<Key, Compare, Allocator>& y); + const set<Key, Compare, Allocator>& y); // removed in C++20 template <class Key, class Compare, class Allocator> bool operator>=(const set<Key, Compare, Allocator>& x, - const set<Key, Compare, Allocator>& y); + const set<Key, Compare, Allocator>& y); // removed in C++20 template <class Key, class Compare, class Allocator> bool operator<=(const set<Key, Compare, Allocator>& x, - const set<Key, Compare, Allocator>& y); + const set<Key, Compare, Allocator>& y); // removed in C++20 + +template<class Key, class Compare, class Allocator> + synth-three-way-result<Key> operator<=>(const set<Key, Compare, Allocator>& x, + const set<Key, Compare, Allocator>& y); // since C++20 // specialized algorithms: template <class Key, class Compare, class Allocator> @@ -280,6 +300,9 @@ public: template <class InputIterator> multiset(InputIterator first, InputIterator last, const value_compare& comp, const allocator_type& a); + template<container-compatible-range<value_type> R> + multiset(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); // C++23 multiset(const multiset& s); multiset(multiset&& s) noexcept( @@ -294,6 +317,9 @@ public: template <class InputIterator> multiset(InputIterator first, InputIterator last, const allocator_type& a) : set(first, last, Compare(), a) {} // C++14 + template<container-compatible-range<value_type> R> + multiset(from_range_t, R&& rg, const Allocator& a)) + : multiset(from_range, std::forward<R>(rg), Compare(), a) { } // C++23 multiset(initializer_list<value_type> il, const allocator_type& a) : set(il, Compare(), a) {} // C++14 ~multiset(); @@ -338,6 +364,8 @@ public: iterator insert(const_iterator position, value_type&& v); template <class InputIterator> void insert(InputIterator first, InputIterator last); + template<container-compatible-range<value_type> R> + void insert_range(R&& rg); // C++23 void insert(initializer_list<value_type> il); node_type extract(const_iterator position); // C++17 @@ -415,6 +443,11 @@ multiset(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> multiset<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>; // C++17 +template<ranges::input_range R, class Compare = less<ranges::range_value_t<R>>, + class Allocator = allocator<ranges::range_value_t<R>>> + multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> multiset<ranges::range_value_t<R>, Compare, Allocator>; + template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>> multiset(initializer_list<Key>, Compare = Compare(), Allocator = Allocator()) -> multiset<Key, Compare, Allocator>; // C++17 @@ -424,6 +457,10 @@ multiset(InputIterator, InputIterator, Allocator) -> multiset<typename iterator_traits<InputIterator>::value_type, less<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17 +template<ranges::input_range R, class Allocator> + multiset(from_range_t, R&&, Allocator) + -> multiset<ranges::range_value_t<R>, less<ranges::range_value_t<R>>, Allocator>; + template<class Key, class Allocator> multiset(initializer_list<Key>, Allocator) -> multiset<Key, less<Key>, Allocator>; // C++17 @@ -435,27 +472,31 @@ operator==(const multiset<Key, Compare, Allocator>& x, template <class Key, class Compare, class Allocator> bool operator< (const multiset<Key, Compare, Allocator>& x, - const multiset<Key, Compare, Allocator>& y); + const multiset<Key, Compare, Allocator>& y); // removed in C++20 template <class Key, class Compare, class Allocator> bool operator!=(const multiset<Key, Compare, Allocator>& x, - const multiset<Key, Compare, Allocator>& y); + const multiset<Key, Compare, Allocator>& y); // removed in C++20 template <class Key, class Compare, class Allocator> bool operator> (const multiset<Key, Compare, Allocator>& x, - const multiset<Key, Compare, Allocator>& y); + const multiset<Key, Compare, Allocator>& y); // removed in C++20 template <class Key, class Compare, class Allocator> bool operator>=(const multiset<Key, Compare, Allocator>& x, - const multiset<Key, Compare, Allocator>& y); + const multiset<Key, Compare, Allocator>& y); // removed in C++20 template <class Key, class Compare, class Allocator> bool operator<=(const multiset<Key, Compare, Allocator>& x, - const multiset<Key, Compare, Allocator>& y); + const multiset<Key, Compare, Allocator>& y); // removed in C++20 + +template<class Key, class Compare, class Allocator> + synth-three-way-result<Key> operator<=>(const multiset<Key, Compare, Allocator>& x, + const multiset<Key, Compare, Allocator>& y); // since C++20 // specialized algorithms: template <class Key, class Compare, class Allocator> @@ -473,16 +514,22 @@ erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); // C++20 #include <__algorithm/equal.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> #include <__config> #include <__functional/is_transparent.h> #include <__functional/operations.h> #include <__iterator/erase_if_container.h> #include <__iterator/iterator_traits.h> +#include <__iterator/ranges_iterator_traits.h> #include <__iterator/reverse_iterator.h> #include <__memory/allocator.h> #include <__memory_resource/polymorphic_allocator.h> #include <__node_handle> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> #include <__tree> #include <__type_traits/is_allocator.h> #include <__utility/forward.h> @@ -547,7 +594,7 @@ public: typedef _VSTD::reverse_iterator<iterator> reverse_iterator; typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef __set_node_handle<typename __base::__node, allocator_type> node_type; typedef __insert_return_type<iterator, node_type> insert_return_type; #endif @@ -593,13 +640,30 @@ public: insert(__f, __l); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + set(from_range_t, _Range&& __range, const key_compare& __comp = key_compare(), + const allocator_type& __a = allocator_type()) + : __tree_(__comp, __a) { + insert_range(std::forward<_Range>(__range)); + } +#endif + +#if _LIBCPP_STD_VER >= 14 template <class _InputIterator> _LIBCPP_INLINE_VISIBILITY set(_InputIterator __f, _InputIterator __l, const allocator_type& __a) : set(__f, __l, key_compare(), __a) {} #endif +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + set(from_range_t, _Range&& __range, const allocator_type& __a) + : set(from_range, std::forward<_Range>(__range), key_compare(), __a) {} +#endif + _LIBCPP_INLINE_VISIBILITY set(const set& __s) : __tree_(__s.__tree_) @@ -633,7 +697,7 @@ public: } #ifndef _LIBCPP_CXX03_LANG - set(set&& __s, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI set(set&& __s, const allocator_type& __a); _LIBCPP_INLINE_VISIBILITY set(initializer_list<value_type> __il, const value_compare& __comp = value_compare()) @@ -650,7 +714,7 @@ public: insert(__il.begin(), __il.end()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _LIBCPP_INLINE_VISIBILITY set(initializer_list<value_type> __il, const allocator_type& __a) : set(__il, key_compare(), __a) {} @@ -742,6 +806,17 @@ public: __tree_.__insert_unique(__e, *__f); } +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + void insert_range(_Range&& __range) { + const_iterator __end = cend(); + for (auto&& __element : __range) { + __tree_.__insert_unique(__end, std::forward<decltype(__element)>(__element)); + } + } +#endif + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY pair<iterator,bool> insert(value_type&& __v) @@ -767,11 +842,11 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__tree_.clear();} -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY insert_return_type insert(node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to set::insert()"); return __tree_.template __node_handle_insert_unique< node_type, insert_return_type>(_VSTD::move(__nh)); @@ -779,7 +854,7 @@ public: _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __hint, node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to set::insert()"); return __tree_.template __node_handle_insert_unique<node_type>( __hint, _VSTD::move(__nh)); @@ -798,7 +873,7 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(set<key_type, _Compare2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); } @@ -806,7 +881,7 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(set<key_type, _Compare2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); } @@ -814,7 +889,7 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(multiset<key_type, _Compare2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); } @@ -822,7 +897,7 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(multiset<key_type, _Compare2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_unique(__source.__tree_); } @@ -844,7 +919,7 @@ public: iterator find(const key_type& __k) {return __tree_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __tree_.find(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type @@ -858,21 +933,21 @@ public: _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __tree_.__count_unique(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,size_type>::type count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type contains(const _K2& __k) const { return find(__k) != end(); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) @@ -880,7 +955,7 @@ public: _LIBCPP_INLINE_VISIBILITY const_iterator lower_bound(const key_type& __k) const {return __tree_.lower_bound(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type @@ -898,7 +973,7 @@ public: _LIBCPP_INLINE_VISIBILITY const_iterator upper_bound(const key_type& __k) const {return __tree_.upper_bound(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type @@ -915,7 +990,7 @@ public: _LIBCPP_INLINE_VISIBILITY pair<const_iterator,const_iterator> equal_range(const key_type& __k) const {return __tree_.__equal_range_unique(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,pair<iterator,iterator>>::type @@ -931,12 +1006,21 @@ public: template<class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>, class _Allocator = allocator<__iter_value_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value, void>, class = enable_if_t<__is_allocator<_Allocator>::value, void>, class = enable_if_t<!__is_allocator<_Compare>::value, void>> set(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) -> set<__iter_value_type<_InputIterator>, _Compare, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, class _Compare = less<ranges::range_value_t<_Range>>, + class _Allocator = allocator<ranges::range_value_t<_Range>>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>, + class = enable_if_t<!__is_allocator<_Compare>::value, void>> +set(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) + -> set<ranges::range_value_t<_Range>, _Compare, _Allocator>; +#endif + template<class _Key, class _Compare = less<_Key>, class _Allocator = allocator<_Key>, class = enable_if_t<!__is_allocator<_Compare>::value, void>, @@ -945,12 +1029,19 @@ set(initializer_list<_Key>, _Compare = _Compare(), _Allocator = _Allocator()) -> set<_Key, _Compare, _Allocator>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value, void>, class = enable_if_t<__is_allocator<_Allocator>::value, void>> set(_InputIterator, _InputIterator, _Allocator) -> set<__iter_value_type<_InputIterator>, less<__iter_value_type<_InputIterator>>, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +set(from_range_t, _Range&&, _Allocator) + -> set<ranges::range_value_t<_Range>, less<ranges::range_value_t<_Range>>, _Allocator>; +#endif + template<class _Key, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value, void>> set(initializer_list<_Key>, _Allocator) @@ -982,6 +1073,8 @@ operator==(const set<_Key, _Compare, _Allocator>& __x, return __x.size() == __y.size() && _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template <class _Key, class _Compare, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY bool @@ -1027,6 +1120,17 @@ operator<=(const set<_Key, _Compare, _Allocator>& __x, return !(__y < __x); } +#else // _LIBCPP_STD_VER <= 17 + +template <class _Key, class _Allocator> +_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Key> +operator<=>(const set<_Key, _Allocator>& __x, const set<_Key, _Allocator>& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Key, _Key>); +} + +#endif // _LIBCPP_STD_VER <= 17 + // specialized algorithms: template <class _Key, class _Compare, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY @@ -1038,7 +1142,7 @@ swap(set<_Key, _Compare, _Allocator>& __x, __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Key, class _Compare, class _Allocator, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY typename set<_Key, _Compare, _Allocator>::size_type @@ -1084,7 +1188,7 @@ public: typedef _VSTD::reverse_iterator<iterator> reverse_iterator; typedef _VSTD::reverse_iterator<const_iterator> const_reverse_iterator; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef __set_node_handle<typename __base::__node, allocator_type> node_type; #endif @@ -1121,7 +1225,7 @@ public: insert(__f, __l); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _InputIterator> _LIBCPP_INLINE_VISIBILITY multiset(_InputIterator __f, _InputIterator __l, const allocator_type& __a) @@ -1137,6 +1241,21 @@ public: insert(__f, __l); } +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + multiset(from_range_t, _Range&& __range, const key_compare& __comp = key_compare(), + const allocator_type& __a = allocator_type()) + : __tree_(__comp, __a) { + insert_range(std::forward<_Range>(__range)); + } + + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + multiset(from_range_t, _Range&& __range, const allocator_type& __a) + : multiset(from_range, std::forward<_Range>(__range), key_compare(), __a) {} +#endif + _LIBCPP_INLINE_VISIBILITY multiset(const multiset& __s) : __tree_(__s.__tree_.value_comp(), @@ -1158,7 +1277,7 @@ public: _NOEXCEPT_(is_nothrow_move_constructible<__base>::value) : __tree_(_VSTD::move(__s.__tree_)) {} - multiset(multiset&& __s, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI multiset(multiset&& __s, const allocator_type& __a); #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY explicit multiset(const allocator_type& __a) @@ -1186,7 +1305,7 @@ public: insert(__il.begin(), __il.end()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _LIBCPP_INLINE_VISIBILITY multiset(initializer_list<value_type> __il, const allocator_type& __a) : multiset(__il, key_compare(), __a) {} @@ -1278,6 +1397,17 @@ public: __tree_.__insert_multi(__e, *__f); } +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + void insert_range(_Range&& __range) { + const_iterator __end = cend(); + for (auto&& __element : __range) { + __tree_.__insert_multi(__end, std::forward<decltype(__element)>(__element)); + } + } +#endif + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY iterator insert(value_type&& __v) @@ -1302,11 +1432,11 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__tree_.clear();} -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY iterator insert(node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to multiset::insert()"); return __tree_.template __node_handle_insert_multi<node_type>( _VSTD::move(__nh)); @@ -1314,7 +1444,7 @@ public: _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __hint, node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to multiset::insert()"); return __tree_.template __node_handle_insert_multi<node_type>( __hint, _VSTD::move(__nh)); @@ -1333,7 +1463,7 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(multiset<key_type, _Compare2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_multi(__source.__tree_); } @@ -1341,7 +1471,7 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(multiset<key_type, _Compare2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_multi(__source.__tree_); } @@ -1349,7 +1479,7 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(set<key_type, _Compare2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_multi(__source.__tree_); } @@ -1357,7 +1487,7 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(set<key_type, _Compare2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_UNCATEGORIZED(__source.get_allocator() == get_allocator(), "merging container with incompatible allocator"); __tree_.__node_handle_merge_multi(__source.__tree_); } @@ -1380,7 +1510,7 @@ public: iterator find(const key_type& __k) {return __tree_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __tree_.find(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type @@ -1394,21 +1524,21 @@ public: _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __tree_.__count_multi(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,size_type>::type count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value, bool>::type contains(const _K2& __k) const { return find(__k) != end(); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) @@ -1416,7 +1546,7 @@ public: _LIBCPP_INLINE_VISIBILITY const_iterator lower_bound(const key_type& __k) const {return __tree_.lower_bound(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type @@ -1434,7 +1564,7 @@ public: _LIBCPP_INLINE_VISIBILITY const_iterator upper_bound(const key_type& __k) const {return __tree_.upper_bound(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,iterator>::type @@ -1451,7 +1581,7 @@ public: _LIBCPP_INLINE_VISIBILITY pair<const_iterator,const_iterator> equal_range(const key_type& __k) const {return __tree_.__equal_range_multi(__k);} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <typename _K2> _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_transparent<_Compare, _K2>::value,pair<iterator,iterator>>::type @@ -1467,12 +1597,21 @@ public: template<class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>, class _Allocator = allocator<__iter_value_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value, void>, class = enable_if_t<__is_allocator<_Allocator>::value, void>, class = enable_if_t<!__is_allocator<_Compare>::value, void>> multiset(_InputIterator, _InputIterator, _Compare = _Compare(), _Allocator = _Allocator()) -> multiset<__iter_value_type<_InputIterator>, _Compare, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, class _Compare = less<ranges::range_value_t<_Range>>, + class _Allocator = allocator<ranges::range_value_t<_Range>>, + class = enable_if_t<__is_allocator<_Allocator>::value, void>, + class = enable_if_t<!__is_allocator<_Compare>::value, void>> +multiset(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) + -> multiset<ranges::range_value_t<_Range>, _Compare, _Allocator>; +#endif + template<class _Key, class _Compare = less<_Key>, class _Allocator = allocator<_Key>, class = enable_if_t<__is_allocator<_Allocator>::value, void>, @@ -1481,12 +1620,19 @@ multiset(initializer_list<_Key>, _Compare = _Compare(), _Allocator = _Allocator( -> multiset<_Key, _Compare, _Allocator>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value, void>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value, void>, class = enable_if_t<__is_allocator<_Allocator>::value, void>> multiset(_InputIterator, _InputIterator, _Allocator) -> multiset<__iter_value_type<_InputIterator>, less<__iter_value_type<_InputIterator>>, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value, void>> +multiset(from_range_t, _Range&&, _Allocator) + -> multiset<ranges::range_value_t<_Range>, less<ranges::range_value_t<_Range>>, _Allocator>; +#endif + template<class _Key, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value, void>> multiset(initializer_list<_Key>, _Allocator) @@ -1518,6 +1664,8 @@ operator==(const multiset<_Key, _Compare, _Allocator>& __x, return __x.size() == __y.size() && _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template <class _Key, class _Compare, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY bool @@ -1563,6 +1711,17 @@ operator<=(const multiset<_Key, _Compare, _Allocator>& __x, return !(__y < __x); } +#else // _LIBCPP_STD_VER <= 17 + +template <class _Key, class _Allocator> +_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Key> +operator<=>(const multiset<_Key, _Allocator>& __x, const multiset<_Key, _Allocator>& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Key, _Key>); +} + +#endif // _LIBCPP_STD_VER <= 17 + template <class _Key, class _Compare, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY void @@ -1573,7 +1732,7 @@ swap(multiset<_Key, _Compare, _Allocator>& __x, __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Key, class _Compare, class _Allocator, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY typename multiset<_Key, _Compare, _Allocator>::size_type @@ -1584,22 +1743,24 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template <class _KeyT, class _CompareT = std::less<_KeyT>> -using set = std::set<_KeyT, _CompareT, polymorphic_allocator<_KeyT>>; +using set _LIBCPP_AVAILABILITY_PMR = std::set<_KeyT, _CompareT, polymorphic_allocator<_KeyT>>; template <class _KeyT, class _CompareT = std::less<_KeyT>> -using multiset = std::multiset<_KeyT, _CompareT, polymorphic_allocator<_KeyT>>; +using multiset _LIBCPP_AVAILABILITY_PMR = std::multiset<_KeyT, _CompareT, polymorphic_allocator<_KeyT>>; } // namespace pmr _LIBCPP_END_NAMESPACE_STD #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> +# include <cstdlib> # include <functional> # include <iterator> +# include <type_traits> #endif #endif // _LIBCPP_SET diff --git a/libcxx/include/shared_mutex b/libcxx/include/shared_mutex index 6919898f66f4..350c841e11a0 100644 --- a/libcxx/include/shared_mutex +++ b/libcxx/include/shared_mutex @@ -124,386 +124,343 @@ template <class Mutex> #include <__assert> // all public C++ headers provide the assertion handler #include <__availability> +#include <__chrono/duration.h> +#include <__chrono/steady_clock.h> +#include <__chrono/time_point.h> +#include <__condition_variable/condition_variable.h> #include <__config> +#include <__memory/addressof.h> +#include <__mutex/mutex.h> +#include <__mutex/tag_types.h> +#include <__mutex/unique_lock.h> +#include <__system_error/system_error.h> +#include <__utility/swap.h> +#include <cerrno> #include <version> _LIBCPP_PUSH_MACROS #include <__undef_macros> +#if _LIBCPP_STD_VER >= 14 -#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_LIBRARY) +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif -#include <__mutex_base> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -#ifdef _LIBCPP_HAS_NO_THREADS -# error "<shared_mutex> is not supported since libc++ has been configured without support for threads." -#endif +# ifdef _LIBCPP_HAS_NO_THREADS +# error "<shared_mutex> is not supported since libc++ has been configured without support for threads." +# endif _LIBCPP_BEGIN_NAMESPACE_STD -struct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("shared_mutex")) -__shared_mutex_base -{ - mutex __mut_; - condition_variable __gate1_; - condition_variable __gate2_; - unsigned __state_; +struct _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_SHARED_MUTEX __shared_mutex_base { + mutex __mut_; + condition_variable __gate1_; + condition_variable __gate2_; + unsigned __state_; - static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1); - static const unsigned __n_readers_ = ~__write_entered_; + static const unsigned __write_entered_ = 1U << (sizeof(unsigned) * __CHAR_BIT__ - 1); + static const unsigned __n_readers_ = ~__write_entered_; - __shared_mutex_base(); - _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default; + __shared_mutex_base(); + _LIBCPP_HIDE_FROM_ABI ~__shared_mutex_base() = default; - __shared_mutex_base(const __shared_mutex_base&) = delete; - __shared_mutex_base& operator=(const __shared_mutex_base&) = delete; + __shared_mutex_base(const __shared_mutex_base&) = delete; + __shared_mutex_base& operator=(const __shared_mutex_base&) = delete; - // Exclusive ownership - void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); // blocking - bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); - void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); + // Exclusive ownership + void lock(); // blocking + bool try_lock(); + void unlock(); - // Shared ownership - void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_shared_capability()); // blocking - bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_shared_capability(true)); - void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_shared_capability()); + // Shared ownership + void lock_shared(); // blocking + bool try_lock_shared(); + void unlock_shared(); -// typedef implementation-defined native_handle_type; // See 30.2.3 -// native_handle_type native_handle(); // See 30.2.3 + // typedef implementation-defined native_handle_type; // See 30.2.3 + // native_handle_type native_handle(); // See 30.2.3 }; +# if _LIBCPP_STD_VER >= 17 +class _LIBCPP_EXPORTED_FROM_ABI + _LIBCPP_AVAILABILITY_SHARED_MUTEX _LIBCPP_THREAD_SAFETY_ANNOTATION(__capability__("shared_mutex")) shared_mutex { + __shared_mutex_base __base_; -#if _LIBCPP_STD_VER > 14 -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_mutex -{ - __shared_mutex_base __base_; public: - _LIBCPP_INLINE_VISIBILITY shared_mutex() : __base_() {} - _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default; - - shared_mutex(const shared_mutex&) = delete; - shared_mutex& operator=(const shared_mutex&) = delete; - - // Exclusive ownership - _LIBCPP_INLINE_VISIBILITY void lock() { return __base_.lock(); } - _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base_.try_lock(); } - _LIBCPP_INLINE_VISIBILITY void unlock() { return __base_.unlock(); } - - // Shared ownership - _LIBCPP_INLINE_VISIBILITY void lock_shared() { return __base_.lock_shared(); } - _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base_.try_lock_shared(); } - _LIBCPP_INLINE_VISIBILITY void unlock_shared() { return __base_.unlock_shared(); } - -// typedef __shared_mutex_base::native_handle_type native_handle_type; -// _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); } + _LIBCPP_HIDE_FROM_ABI shared_mutex() : __base_() {} + _LIBCPP_HIDE_FROM_ABI ~shared_mutex() = default; + + shared_mutex(const shared_mutex&) = delete; + shared_mutex& operator=(const shared_mutex&) = delete; + + // Exclusive ownership + _LIBCPP_HIDE_FROM_ABI void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_capability__()) { + return __base_.lock(); + } + _LIBCPP_HIDE_FROM_ABI bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) { + return __base_.try_lock(); + } + _LIBCPP_HIDE_FROM_ABI void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_capability__()) { + return __base_.unlock(); + } + + // Shared ownership + _LIBCPP_HIDE_FROM_ABI void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_shared_capability__()) { + return __base_.lock_shared(); + } + _LIBCPP_HIDE_FROM_ABI bool try_lock_shared() + _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) { + return __base_.try_lock_shared(); + } + _LIBCPP_HIDE_FROM_ABI void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__()) { + return __base_.unlock_shared(); + } + + // typedef __shared_mutex_base::native_handle_type native_handle_type; + // _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return __base::unlock_shared(); } }; -#endif +# endif +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_SHARED_MUTEX _LIBCPP_THREAD_SAFETY_ANNOTATION( + __capability__("shared_timed_mutex")) shared_timed_mutex { + __shared_mutex_base __base_; -class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_timed_mutex -{ - __shared_mutex_base __base_; public: - shared_timed_mutex(); - _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default; - - shared_timed_mutex(const shared_timed_mutex&) = delete; - shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; - - // Exclusive ownership - void lock(); - bool try_lock(); - template <class _Rep, class _Period> - _LIBCPP_INLINE_VISIBILITY - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) - { - return try_lock_until(chrono::steady_clock::now() + __rel_time); - } - template <class _Clock, class _Duration> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time); - void unlock(); - - // Shared ownership - void lock_shared(); - bool try_lock_shared(); - template <class _Rep, class _Period> - _LIBCPP_INLINE_VISIBILITY - bool - try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) - { - return try_lock_shared_until(chrono::steady_clock::now() + __rel_time); - } - template <class _Clock, class _Duration> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - bool - try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time); - void unlock_shared(); + shared_timed_mutex(); + _LIBCPP_HIDE_FROM_ABI ~shared_timed_mutex() = default; + + shared_timed_mutex(const shared_timed_mutex&) = delete; + shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; + + // Exclusive ownership + void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_capability__()); + bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)); + template <class _Rep, class _Period> + _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) + _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) { + return try_lock_until(chrono::steady_clock::now() + __rel_time); + } + template <class _Clock, class _Duration> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)); + void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_capability__()); + + // Shared ownership + void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_shared_capability__()); + bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)); + template <class _Rep, class _Period> + _LIBCPP_HIDE_FROM_ABI bool try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) + _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) { + return try_lock_shared_until(chrono::steady_clock::now() + __rel_time); + } + template <class _Clock, class _Duration> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool + try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)); + void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__()); }; template <class _Clock, class _Duration> -bool -shared_timed_mutex::try_lock_until( - const chrono::time_point<_Clock, _Duration>& __abs_time) -{ - unique_lock<mutex> __lk(__base_.__mut_); - if (__base_.__state_ & __base_.__write_entered_) - { - while (true) - { - cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time); - if ((__base_.__state_ & __base_.__write_entered_) == 0) - break; - if (__status == cv_status::timeout) - return false; - } +bool shared_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) { + unique_lock<mutex> __lk(__base_.__mut_); + if (__base_.__state_ & __base_.__write_entered_) { + while (true) { + cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time); + if ((__base_.__state_ & __base_.__write_entered_) == 0) + break; + if (__status == cv_status::timeout) + return false; } - __base_.__state_ |= __base_.__write_entered_; - if (__base_.__state_ & __base_.__n_readers_) - { - while (true) - { - cv_status __status = __base_.__gate2_.wait_until(__lk, __abs_time); - if ((__base_.__state_ & __base_.__n_readers_) == 0) - break; - if (__status == cv_status::timeout) - { - __base_.__state_ &= ~__base_.__write_entered_; - __base_.__gate1_.notify_all(); - return false; - } - } + } + __base_.__state_ |= __base_.__write_entered_; + if (__base_.__state_ & __base_.__n_readers_) { + while (true) { + cv_status __status = __base_.__gate2_.wait_until(__lk, __abs_time); + if ((__base_.__state_ & __base_.__n_readers_) == 0) + break; + if (__status == cv_status::timeout) { + __base_.__state_ &= ~__base_.__write_entered_; + __base_.__gate1_.notify_all(); + return false; + } } - return true; + } + return true; } template <class _Clock, class _Duration> -bool -shared_timed_mutex::try_lock_shared_until( - const chrono::time_point<_Clock, _Duration>& __abs_time) -{ - unique_lock<mutex> __lk(__base_.__mut_); - if ((__base_.__state_ & __base_.__write_entered_) || (__base_.__state_ & __base_.__n_readers_) == __base_.__n_readers_) - { - while (true) - { - cv_status status = __base_.__gate1_.wait_until(__lk, __abs_time); - if ((__base_.__state_ & __base_.__write_entered_) == 0 && - (__base_.__state_ & __base_.__n_readers_) < __base_.__n_readers_) - break; - if (status == cv_status::timeout) - return false; - } +bool shared_timed_mutex::try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) { + unique_lock<mutex> __lk(__base_.__mut_); + if ((__base_.__state_ & __base_.__write_entered_) || + (__base_.__state_ & __base_.__n_readers_) == __base_.__n_readers_) { + while (true) { + cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time); + if ((__base_.__state_ & __base_.__write_entered_) == 0 && + (__base_.__state_ & __base_.__n_readers_) < __base_.__n_readers_) + break; + if (__status == cv_status::timeout) + return false; } - unsigned __num_readers = (__base_.__state_ & __base_.__n_readers_) + 1; - __base_.__state_ &= ~__base_.__n_readers_; - __base_.__state_ |= __num_readers; - return true; + } + unsigned __num_readers = (__base_.__state_ & __base_.__n_readers_) + 1; + __base_.__state_ &= ~__base_.__n_readers_; + __base_.__state_ |= __num_readers; + return true; } template <class _Mutex> -class shared_lock -{ +class shared_lock { public: - typedef _Mutex mutex_type; + typedef _Mutex mutex_type; private: - mutex_type* __m_; - bool __owns_; + mutex_type* __m_; + bool __owns_; public: - _LIBCPP_INLINE_VISIBILITY - shared_lock() _NOEXCEPT - : __m_(nullptr), - __owns_(false) - {} - - _LIBCPP_INLINE_VISIBILITY - explicit shared_lock(mutex_type& __m) - : __m_(_VSTD::addressof(__m)), - __owns_(true) - {__m_->lock_shared();} - - _LIBCPP_INLINE_VISIBILITY - shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT - : __m_(_VSTD::addressof(__m)), - __owns_(false) - {} - - _LIBCPP_INLINE_VISIBILITY - shared_lock(mutex_type& __m, try_to_lock_t) - : __m_(_VSTD::addressof(__m)), - __owns_(__m.try_lock_shared()) - {} - - _LIBCPP_INLINE_VISIBILITY - shared_lock(mutex_type& __m, adopt_lock_t) - : __m_(_VSTD::addressof(__m)), - __owns_(true) - {} - - template <class _Clock, class _Duration> - _LIBCPP_INLINE_VISIBILITY - shared_lock(mutex_type& __m, - const chrono::time_point<_Clock, _Duration>& __abs_time) - : __m_(_VSTD::addressof(__m)), - __owns_(__m.try_lock_shared_until(__abs_time)) - {} - - template <class _Rep, class _Period> - _LIBCPP_INLINE_VISIBILITY - shared_lock(mutex_type& __m, - const chrono::duration<_Rep, _Period>& __rel_time) - : __m_(_VSTD::addressof(__m)), - __owns_(__m.try_lock_shared_for(__rel_time)) - {} - - _LIBCPP_INLINE_VISIBILITY - ~shared_lock() - { - if (__owns_) - __m_->unlock_shared(); - } + _LIBCPP_HIDE_FROM_ABI shared_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} - shared_lock(shared_lock const&) = delete; - shared_lock& operator=(shared_lock const&) = delete; + _LIBCPP_HIDE_FROM_ABI explicit shared_lock(mutex_type& __m) : __m_(_VSTD::addressof(__m)), __owns_(true) { + __m_->lock_shared(); + } - _LIBCPP_INLINE_VISIBILITY - shared_lock(shared_lock&& __u) _NOEXCEPT - : __m_(__u.__m_), - __owns_(__u.__owns_) - { - __u.__m_ = nullptr; - __u.__owns_ = false; - } - - _LIBCPP_INLINE_VISIBILITY - shared_lock& operator=(shared_lock&& __u) _NOEXCEPT - { - if (__owns_) - __m_->unlock_shared(); - __m_ = nullptr; - __owns_ = false; - __m_ = __u.__m_; - __owns_ = __u.__owns_; - __u.__m_ = nullptr; - __u.__owns_ = false; - return *this; - } + _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT + : __m_(_VSTD::addressof(__m)), + __owns_(false) {} - void lock(); - bool try_lock(); - template <class Rep, class Period> - bool try_lock_for(const chrono::duration<Rep, Period>& __rel_time); - template <class Clock, class Duration> - bool try_lock_until(const chrono::time_point<Clock, Duration>& __abs_time); - void unlock(); + _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, try_to_lock_t) + : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_shared()) {} - // Setters - _LIBCPP_INLINE_VISIBILITY - void swap(shared_lock& __u) _NOEXCEPT - { - _VSTD::swap(__m_, __u.__m_); - _VSTD::swap(__owns_, __u.__owns_); - } + _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, adopt_lock_t) : __m_(_VSTD::addressof(__m)), __owns_(true) {} - _LIBCPP_INLINE_VISIBILITY - mutex_type* release() _NOEXCEPT - { - mutex_type* __m = __m_; - __m_ = nullptr; - __owns_ = false; - return __m; - } + template <class _Clock, class _Duration> + _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __abs_time) + : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_shared_until(__abs_time)) {} - // Getters - _LIBCPP_INLINE_VISIBILITY - bool owns_lock() const _NOEXCEPT {return __owns_;} + template <class _Rep, class _Period> + _LIBCPP_HIDE_FROM_ABI shared_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __rel_time) + : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_shared_for(__rel_time)) {} - _LIBCPP_INLINE_VISIBILITY - explicit operator bool () const _NOEXCEPT {return __owns_;} + _LIBCPP_HIDE_FROM_ABI ~shared_lock() { + if (__owns_) + __m_->unlock_shared(); + } + + shared_lock(shared_lock const&) = delete; + shared_lock& operator=(shared_lock const&) = delete; + + _LIBCPP_HIDE_FROM_ABI shared_lock(shared_lock&& __u) _NOEXCEPT : __m_(__u.__m_), __owns_(__u.__owns_) { + __u.__m_ = nullptr; + __u.__owns_ = false; + } - _LIBCPP_INLINE_VISIBILITY - mutex_type* mutex() const _NOEXCEPT {return __m_;} + _LIBCPP_HIDE_FROM_ABI shared_lock& operator=(shared_lock&& __u) _NOEXCEPT { + if (__owns_) + __m_->unlock_shared(); + __m_ = nullptr; + __owns_ = false; + __m_ = __u.__m_; + __owns_ = __u.__owns_; + __u.__m_ = nullptr; + __u.__owns_ = false; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI void lock(); + _LIBCPP_HIDE_FROM_ABI bool try_lock(); + template <class _Rep, class _Period> + _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time); + template <class _Clock, class _Duration> + _LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time); + _LIBCPP_HIDE_FROM_ABI void unlock(); + + // Setters + _LIBCPP_HIDE_FROM_ABI void swap(shared_lock& __u) _NOEXCEPT { + _VSTD::swap(__m_, __u.__m_); + _VSTD::swap(__owns_, __u.__owns_); + } + + _LIBCPP_HIDE_FROM_ABI mutex_type* release() _NOEXCEPT { + mutex_type* __m = __m_; + __m_ = nullptr; + __owns_ = false; + return __m; + } + + // Getters + _LIBCPP_HIDE_FROM_ABI bool owns_lock() const _NOEXCEPT { return __owns_; } + + _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __owns_; } + + _LIBCPP_HIDE_FROM_ABI mutex_type* mutex() const _NOEXCEPT { return __m_; } }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(shared_lock); template <class _Mutex> -void -shared_lock<_Mutex>::lock() -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "shared_lock::lock: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "shared_lock::lock: already locked"); - __m_->lock_shared(); - __owns_ = true; +void shared_lock<_Mutex>::lock() { + if (__m_ == nullptr) + __throw_system_error(EPERM, "shared_lock::lock: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "shared_lock::lock: already locked"); + __m_->lock_shared(); + __owns_ = true; } template <class _Mutex> -bool -shared_lock<_Mutex>::try_lock() -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked"); - __owns_ = __m_->try_lock_shared(); - return __owns_; +bool shared_lock<_Mutex>::try_lock() { + if (__m_ == nullptr) + __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked"); + __owns_ = __m_->try_lock_shared(); + return __owns_; } template <class _Mutex> template <class _Rep, class _Period> -bool -shared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked"); - __owns_ = __m_->try_lock_shared_for(__d); - return __owns_; +bool shared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) { + if (__m_ == nullptr) + __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked"); + __owns_ = __m_->try_lock_shared_for(__d); + return __owns_; } template <class _Mutex> template <class _Clock, class _Duration> -bool -shared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) -{ - if (__m_ == nullptr) - __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex"); - if (__owns_) - __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked"); - __owns_ = __m_->try_lock_shared_until(__t); - return __owns_; +bool shared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { + if (__m_ == nullptr) + __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked"); + __owns_ = __m_->try_lock_shared_until(__t); + return __owns_; } template <class _Mutex> -void -shared_lock<_Mutex>::unlock() -{ - if (!__owns_) - __throw_system_error(EPERM, "shared_lock::unlock: not locked"); - __m_->unlock_shared(); - __owns_ = false; +void shared_lock<_Mutex>::unlock() { + if (!__owns_) + __throw_system_error(EPERM, "shared_lock::unlock: not locked"); + __m_->unlock_shared(); + __owns_ = false; } template <class _Mutex> -inline _LIBCPP_INLINE_VISIBILITY -void -swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT - {__x.swap(__y);} +inline _LIBCPP_HIDE_FROM_ABI void swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT { + __x.swap(__y); +} _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 11 +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_POP_MACROS +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <system_error> +#endif + #endif // _LIBCPP_SHARED_MUTEX diff --git a/libcxx/include/source_location b/libcxx/include/source_location index 4c4a09618ada..e9e852a6e461 100644 --- a/libcxx/include/source_location +++ b/libcxx/include/source_location @@ -35,7 +35,8 @@ namespace std { _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 20 && __has_builtin(__builtin_source_location) +#if _LIBCPP_STD_VER >= 20 && __has_builtin(__builtin_source_location) && \ + !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER <= 1403) class source_location { // The names source_location::__impl, _M_file_name, _M_function_name, _M_line, and _M_column @@ -78,7 +79,8 @@ public: } }; -#endif // _LIBCPP_STD_VER >= 20 && __has_builtin(__builtin_source_location) +#endif // _LIBCPP_STD_VER >= 20 && __has_builtin(__builtin_source_location) && !(defined(_LIBCPP_APPLE_CLANG_VER) && + // _LIBCPP_APPLE_CLANG_VER <= 1403) _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/span b/libcxx/include/span index 23af04f38839..b050dfe6e340 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -71,7 +71,6 @@ public: constexpr span(const span& other) noexcept = default; template <class OtherElementType, size_t OtherExtent> constexpr explicit(Extent != dynamic_extent) span(const span<OtherElementType, OtherExtent>& s) noexcept; - ~span() noexcept = default; constexpr span& operator=(const span& other) noexcept = default; // [span.sub], span subviews @@ -129,7 +128,6 @@ template<class R> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include <__debug> #include <__fwd/span.h> #include <__iterator/bounded_iter.h> #include <__iterator/concepts.h> @@ -141,11 +139,14 @@ template<class R> #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> #include <__ranges/size.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> +#include <__type_traits/type_identity.h> #include <__utility/forward.h> #include <array> // for array #include <cstddef> // for byte #include <limits> -#include <type_traits> // for remove_cv, etc #include <version> // standard-mandated includes @@ -166,7 +167,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp> struct __is_std_array : false_type {}; @@ -211,7 +212,7 @@ public: using const_pointer = const _Tp *; using reference = _Tp &; using const_reference = const _Tp &; -#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING +#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS using iterator = __bounded_iter<pointer>; #else using iterator = __wrap_iter<pointer>; @@ -232,16 +233,18 @@ public: constexpr explicit span(_It __first, size_type __count) : __data_{_VSTD::to_address(__first)} { (void)__count; - _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (iterator, len)"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Extent == __count, "size mismatch in span's constructor (iterator, len)"); } template <__span_compatible_iterator<element_type> _It, __span_compatible_sentinel_for<_It> _End> _LIBCPP_INLINE_VISIBILITY constexpr explicit span(_It __first, _End __last) : __data_{_VSTD::to_address(__first)} { - (void)__last; - _LIBCPP_ASSERT((__last - __first >= 0), "invalid range in span's constructor (iterator, sentinel)"); - _LIBCPP_ASSERT(__last - __first == _Extent, - "invalid range in span's constructor (iterator, sentinel): last - first != extent"); + // [span.cons]/10 + // Throws: When and what last - first throws. + [[maybe_unused]] auto __dist = __last - __first; + _LIBCPP_ASSERT_VALID_INPUT_RANGE(__dist >= 0, "invalid range in span's constructor (iterator, sentinel)"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __dist == _Extent, "invalid range in span's constructor (iterator, sentinel): last - first != extent"); } _LIBCPP_INLINE_VISIBILITY constexpr span(type_identity_t<element_type> (&__arr)[_Extent]) noexcept : __data_{__arr} {} @@ -258,7 +261,8 @@ public: template <__span_compatible_range<element_type> _Range> _LIBCPP_INLINE_VISIBILITY constexpr explicit span(_Range&& __r) : __data_{ranges::data(__r)} { - _LIBCPP_ASSERT(ranges::size(__r) == _Extent, "size mismatch in span's constructor (range)"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + ranges::size(__r) == _Extent, "size mismatch in span's constructor (range)"); } template <__span_array_convertible<element_type> _OtherElementType> @@ -269,10 +273,10 @@ public: template <__span_array_convertible<element_type> _OtherElementType> _LIBCPP_INLINE_VISIBILITY constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other) noexcept - : __data_{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); } - - -// ~span() noexcept = default; + : __data_{__other.data()} { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + _Extent == __other.size(), "size mismatch in span's constructor (other span)"); + } template <size_t _Count> _LIBCPP_INLINE_VISIBILITY @@ -293,14 +297,14 @@ public: _LIBCPP_INLINE_VISIBILITY constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept { - _LIBCPP_ASSERT(__count <= size(), "span<T, N>::first(count): count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::first(count): count out of range"); return {data(), __count}; } _LIBCPP_INLINE_VISIBILITY constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept { - _LIBCPP_ASSERT(__count <= size(), "span<T, N>::last(count): count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::last(count): count out of range"); return {data() + size() - __count, __count}; } @@ -321,11 +325,12 @@ public: constexpr span<element_type, dynamic_extent> subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept { - _LIBCPP_ASSERT(__offset <= size(), "span<T, N>::subspan(offset, count): offset out of range"); - _LIBCPP_ASSERT(__count <= size() || __count == dynamic_extent, "span<T, N>::subspan(offset, count): count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __offset <= size(), "span<T, N>::subspan(offset, count): offset out of range"); if (__count == dynamic_extent) return {data() + __offset, size() - __offset}; - _LIBCPP_ASSERT(__count <= size() - __offset, "span<T, N>::subspan(offset, count): offset + count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __count <= size() - __offset, "span<T, N>::subspan(offset, count): offset + count out of range"); return {data() + __offset, __count}; } @@ -335,19 +340,19 @@ public: _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept { - _LIBCPP_ASSERT(__idx < size(), "span<T, N>::operator[](index): index out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < size(), "span<T, N>::operator[](index): index out of range"); return __data_[__idx]; } _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept { - _LIBCPP_ASSERT(!empty(), "span<T, N>::front() on empty span"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::front() on empty span"); return __data_[0]; } _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept { - _LIBCPP_ASSERT(!empty(), "span<T, N>::back() on empty span"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::back() on empty span"); return __data_[size()-1]; } @@ -355,17 +360,17 @@ public: // [span.iter], span iterator support _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { -#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING +#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS return std::__make_bounded_iter(data(), data(), data() + size()); #else - return iterator(this, data()); + return iterator(data()); #endif } _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { -#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING +#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS return std::__make_bounded_iter(data() + size(), data(), data() + size()); #else - return iterator(this, data() + size()); + return iterator(data() + size()); #endif } _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } @@ -394,7 +399,7 @@ public: using const_pointer = const _Tp *; using reference = _Tp &; using const_reference = const _Tp &; -#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING +#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS using iterator = __bounded_iter<pointer>; #else using iterator = __wrap_iter<pointer>; @@ -417,7 +422,8 @@ public: template <__span_compatible_iterator<element_type> _It, __span_compatible_sentinel_for<_It> _End> _LIBCPP_INLINE_VISIBILITY constexpr span(_It __first, _End __last) : __data_(_VSTD::to_address(__first)), __size_(__last - __first) { - _LIBCPP_ASSERT(__last - __first >= 0, "invalid range in span's constructor (iterator, sentinel)"); + _LIBCPP_ASSERT_VALID_INPUT_RANGE( + __last - __first >= 0, "invalid range in span's constructor (iterator, sentinel)"); } template <size_t _Sz> @@ -442,13 +448,11 @@ public: constexpr span(const span<_OtherElementType, _OtherExtent>& __other) noexcept : __data_{__other.data()}, __size_{__other.size()} {} -// ~span() noexcept = default; - template <size_t _Count> _LIBCPP_INLINE_VISIBILITY constexpr span<element_type, _Count> first() const noexcept { - _LIBCPP_ASSERT(_Count <= size(), "span<T>::first<Count>(): Count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::first<Count>(): Count out of range"); return span<element_type, _Count>{data(), _Count}; } @@ -456,21 +460,21 @@ public: _LIBCPP_INLINE_VISIBILITY constexpr span<element_type, _Count> last() const noexcept { - _LIBCPP_ASSERT(_Count <= size(), "span<T>::last<Count>(): Count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::last<Count>(): Count out of range"); return span<element_type, _Count>{data() + size() - _Count, _Count}; } _LIBCPP_INLINE_VISIBILITY constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept { - _LIBCPP_ASSERT(__count <= size(), "span<T>::first(count): count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::first(count): count out of range"); return {data(), __count}; } _LIBCPP_INLINE_VISIBILITY constexpr span<element_type, dynamic_extent> last (size_type __count) const noexcept { - _LIBCPP_ASSERT(__count <= size(), "span<T>::last(count): count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::last(count): count out of range"); return {data() + size() - __count, __count}; } @@ -478,8 +482,10 @@ public: _LIBCPP_INLINE_VISIBILITY constexpr span<element_type, _Count> subspan() const noexcept { - _LIBCPP_ASSERT(_Offset <= size(), "span<T>::subspan<Offset, Count>(): Offset out of range"); - _LIBCPP_ASSERT(_Count == dynamic_extent || _Count <= size() - _Offset, "span<T>::subspan<Offset, Count>(): Offset + Count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + _Offset <= size(), "span<T>::subspan<Offset, Count>(): Offset out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count == dynamic_extent || _Count <= size() - _Offset, + "span<T>::subspan<Offset, Count>(): Offset + Count out of range"); return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; } @@ -487,11 +493,11 @@ public: _LIBCPP_INLINE_VISIBILITY subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept { - _LIBCPP_ASSERT(__offset <= size(), "span<T>::subspan(offset, count): offset out of range"); - _LIBCPP_ASSERT(__count <= size() || __count == dynamic_extent, "span<T>::subspan(offset, count): count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__offset <= size(), "span<T>::subspan(offset, count): offset out of range"); if (__count == dynamic_extent) return {data() + __offset, size() - __offset}; - _LIBCPP_ASSERT(__count <= size() - __offset, "span<T>::subspan(offset, count): offset + count out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __count <= size() - __offset, "span<T>::subspan(offset, count): offset + count out of range"); return {data() + __offset, __count}; } @@ -501,19 +507,19 @@ public: _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept { - _LIBCPP_ASSERT(__idx < size(), "span<T>::operator[](index): index out of range"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < size(), "span<T>::operator[](index): index out of range"); return __data_[__idx]; } _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept { - _LIBCPP_ASSERT(!empty(), "span<T>::front() on empty span"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::front() on empty span"); return __data_[0]; } _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept { - _LIBCPP_ASSERT(!empty(), "span<T>::back() on empty span"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::back() on empty span"); return __data_[size()-1]; } @@ -522,17 +528,17 @@ public: // [span.iter], span iterator support _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { -#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING +#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS return std::__make_bounded_iter(data(), data(), data() + size()); #else - return iterator(this, data()); + return iterator(data()); #endif } _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { -#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING +#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS return std::__make_bounded_iter(data() + size(), data(), data() + size()); #else - return iterator(this, data() + size()); + return iterator(data() + size()); #endif } _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } @@ -566,10 +572,10 @@ _LIBCPP_INLINE_VISIBILITY auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept { return __s.__as_writable_bytes(); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<contiguous_iterator _It, class _EndOrSize> span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template<class _Tp, size_t _Sz> span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>; @@ -583,7 +589,7 @@ template<class _Tp, size_t _Sz> template<ranges::contiguous_range _Range> span(_Range&&) -> span<remove_reference_t<ranges::range_reference_t<_Range>>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD @@ -593,6 +599,7 @@ _LIBCPP_POP_MACROS # include <concepts> # include <functional> # include <iterator> +# include <type_traits> #endif #endif // _LIBCPP_SPAN diff --git a/libcxx/include/sstream b/libcxx/include/sstream index 78cc28a50282..d7ad0213eb34 100644 --- a/libcxx/include/sstream +++ b/libcxx/include/sstream @@ -30,17 +30,41 @@ public: explicit basic_stringbuf(ios_base::openmode which = ios_base::in | ios_base::out); // before C++20 basic_stringbuf() : basic_stringbuf(ios_base::in | ios_base::out) {} // C++20 explicit basic_stringbuf(ios_base::openmode which); // C++20 - explicit basic_stringbuf(const basic_string<char_type, traits_type, allocator_type>& str, + explicit basic_stringbuf(const basic_string<char_type, traits_type, allocator_type>& s, ios_base::openmode which = ios_base::in | ios_base::out); + explicit basic_stringbuf(const allocator_type& a) + : basic_stringbuf(ios_base::in | ios_base::out, a) {} // C++20 + basic_stringbuf(ios_base::openmode which, const allocator_type& a); // C++20 + explicit basic_stringbuf(basic_string<char_type, traits_type, allocator_type>&& s, + ios_base::openmode which = ios_base::in | ios_base::out); // C++20 + template <class SAlloc> + basic_stringbuf(const basic_string<char_type, traits_type, SAlloc>& s, const allocator_type& a) + : basic_stringbuf(s, ios_base::in | ios_base::out, a) {} // C++20 + template <class SAlloc> + basic_stringbuf(const basic_string<char_type, traits_type, SAlloc>& s, + ios_base::openmode which, const allocator_type& a); // C++20 + template <class SAlloc> + explicit basic_stringbuf(const basic_string<char_type, traits_type, SAlloc>& s, + ios_base::openmode which = ios_base::in | ios_base::out); // C++20 basic_stringbuf(basic_stringbuf&& rhs); + basic_stringbuf(basic_stringbuf&& rhs, const allocator_type& a); // C++20 // [stringbuf.assign] Assign and swap: basic_stringbuf& operator=(basic_stringbuf&& rhs); - void swap(basic_stringbuf& rhs); + void swap(basic_stringbuf& rhs) noexcept(see below); // conditionally noexcept since C++20 // [stringbuf.members] Member functions: - basic_string<char_type, traits_type, allocator_type> str() const; + allocator_type get_allocator() const noexcept; // C++20 + basic_string<char_type, traits_type, allocator_type> str() const; // before C++20 + basic_string<char_type, traits_type, allocator_type> str() const &; // C++20 + template <class SAlloc> + basic_string<char_type, traits_type, SAlloc> str(const SAlloc& sa) const; // C++20 + basic_string<char_type, traits_type, allocator_type> str() &&; // C++20 + basic_string_view<char_type, traits_type> view() const noexcept; // C++20 void str(const basic_string<char_type, traits_type, allocator_type>& s); + template <class SAlloc> + void str(const basic_string<char_type, traits_type, SAlloc>& s); // C++20 + void str(basic_string<char_type, traits_type, allocator_type>&& s); // C++20 protected: // [stringbuf.virtuals] Overridden virtual functions: @@ -56,8 +80,8 @@ protected: // [stringbuf.assign] non member swap template <class charT, class traits, class Allocator> - void swap(basic_stringbuf<charT, traits, Allocator>& x, - basic_stringbuf<charT, traits, Allocator>& y); +void swap(basic_stringbuf<charT, traits, Allocator>& x, + basic_stringbuf<charT, traits, Allocator>& y); // conditionally noexcept since C++20 typedef basic_stringbuf<char> stringbuf; typedef basic_stringbuf<wchar_t> wstringbuf; @@ -76,12 +100,23 @@ public: typedef Allocator allocator_type; // [istringstream.cons] Constructors: - explicit basic_istringstream(ios_base::openmode which = ios_base::in); // before C++20 - basic_istringstream() : basic_istringstream(ios_base::in) {} // C++20 - explicit basic_istringstream(ios_base::openmode which); // C++20 - - explicit basic_istringstream(const basic_string<char_type, traits_type,allocator_type>& str, + explicit basic_istringstream(ios_base::openmode which = ios_base::in); // before C++20 + basic_istringstream() : basic_istringstream(ios_base::in) {} // C++20 + explicit basic_istringstream(ios_base::openmode which); // C++20 + explicit basic_istringstream(const basic_string<char_type, traits_type, allocator_type>& s, ios_base::openmode which = ios_base::in); + basic_istringstream(ios_base::openmode which, const allocator_type& a); // C++20 + explicit basic_istringstream(basic_string<char_type, traits_type, allocator_type>&& s, + ios_base::openmode which = ios_base::in); // C++20 + template <class SAlloc> + basic_istringstream(const basic_string<char_type, traits_type, SAlloc>& s, const allocator_type& a) + : basic_istringstream(s, ios_base::in, a) {} // C++20 + template <class SAlloc> + basic_istringstream(const basic_string<char_type, traits_type, SAlloc>& s, + ios_base::openmode which, const allocator_type& a); // C++20 + template <class SAlloc> + explicit basic_istringstream(const basic_string<char_type, traits_type, SAlloc>& s, + ios_base::openmode which = ios_base::in); // C++20 basic_istringstream(basic_istringstream&& rhs); // [istringstream.assign] Assign and swap: @@ -90,13 +125,21 @@ public: // [istringstream.members] Member functions: basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const; - basic_string<char_type, traits_type, allocator_type> str() const; + basic_string<char_type, traits_type, allocator_type> str() const; // before C++20 + basic_string<char_type, traits_type, allocator_type> str() const &; // C++20 + template <class SAlloc> + basic_string<char_type, traits_type, SAlloc> str(const SAlloc& sa) const; // C++20 + basic_string<char_type, traits_type, allocator_type> str() &&; // C++20 + basic_string_view<char_type, traits_type> view() const noexcept; // C++20 void str(const basic_string<char_type, traits_type, allocator_type>& s); + template <class SAlloc> + void str(const basic_string<char_type, traits_type, SAlloc>& s); // C++20 + void str(basic_string<char_type, traits_type, allocator_type>&& s); // C++20 }; template <class charT, class traits, class Allocator> - void swap(basic_istringstream<charT, traits, Allocator>& x, - basic_istringstream<charT, traits, Allocator>& y); +void swap(basic_istringstream<charT, traits, Allocator>& x, + basic_istringstream<charT, traits, Allocator>& y); typedef basic_istringstream<char> istringstream; typedef basic_istringstream<wchar_t> wistringstream; @@ -116,12 +159,23 @@ public: typedef Allocator allocator_type; // [ostringstream.cons] Constructors: - explicit basic_ostringstream(ios_base::openmode which = ios_base::out); // before C++20 - basic_ostringstream() : basic_ostringstream(ios_base::out) {} // C++20 - explicit basic_ostringstream(ios_base::openmode which); // C++20 - - explicit basic_ostringstream(const basic_string<char_type, traits_type, allocator_type>& str, + explicit basic_ostringstream(ios_base::openmode which = ios_base::out); // before C++20 + basic_ostringstream() : basic_ostringstream(ios_base::out) {} // C++20 + explicit basic_ostringstream(ios_base::openmode which); // C++20 + explicit basic_ostringstream(const basic_string<char_type, traits_type, allocator_type>& s, ios_base::openmode which = ios_base::out); + basic_ostringstream(ios_base::openmode which, const allocator_type& a); // C++20 + explicit basic_ostringstream(basic_string<char_type, traits_type, allocator_type>&& s, + ios_base::openmode which = ios_base::out); // C++20 + template <class SAlloc> + basic_ostringstream(const basic_string<char_type, traits_type, SAlloc>& s, const allocator_type& a) + : basic_ostringstream(s, ios_base::out, a) {} // C++20 + template <class SAlloc> + basic_ostringstream(const basic_string<char_type, traits_type, SAlloc>& s, + ios_base::openmode which, const allocator_type& a); // C++20 + template <class SAlloc> + explicit basic_ostringstream(const basic_string<char_type, traits_type, SAlloc>& s, + ios_base::openmode which = ios_base::out); // C++20 basic_ostringstream(basic_ostringstream&& rhs); // [ostringstream.assign] Assign and swap: @@ -130,13 +184,21 @@ public: // [ostringstream.members] Member functions: basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const; - basic_string<char_type, traits_type, allocator_type> str() const; + basic_string<char_type, traits_type, allocator_type> str() const; // before C++20 + basic_string<char_type, traits_type, allocator_type> str() const &; // C++20 + template <class SAlloc> + basic_string<char_type, traits_type, SAlloc> str(const SAlloc& sa) const; // C++20 + basic_string<char_type, traits_type, allocator_type> str() &&; // C++20 + basic_string_view<char_type, traits_type> view() const noexcept; // C++20 void str(const basic_string<char_type, traits_type, allocator_type>& s); + template <class SAlloc> + void str(const basic_string<char_type, traits_type, SAlloc>& s); // C++20 + void str(basic_string<char_type, traits_type, allocator_type>&& s); // C++20 }; template <class charT, class traits, class Allocator> - void swap(basic_ostringstream<charT, traits, Allocator>& x, - basic_ostringstream<charT, traits, Allocator>& y); +void swap(basic_ostringstream<charT, traits, Allocator>& x, + basic_ostringstream<charT, traits, Allocator>& y); typedef basic_ostringstream<char> ostringstream; typedef basic_ostringstream<wchar_t> wostringstream; @@ -159,9 +221,20 @@ public: explicit basic_stringstream(ios_base::openmode which = ios_base::out | ios_base::in); // before C++20 basic_stringstream() : basic_stringstream(ios_base::out | ios_base::in) {} // C++20 explicit basic_stringstream(ios_base::openmode which); // C++20 - - explicit basic_stringstream(const basic_string<char_type, traits_type, allocator_type>& str, - ios_base::openmode which = ios_base::out|ios_base::in); + explicit basic_stringstream(const basic_string<char_type, traits_type, allocator_type>& s, + ios_base::openmode which = ios_base::out | ios_base::in); + basic_stringstream(ios_base::openmode which, const allocator_type& a); // C++20 + explicit basic_stringstream(basic_string<char_type, traits_type, allocator_type>&& s, + ios_base::openmode which = ios_base::out | ios_base::in); // C++20 + template <class SAlloc> + basic_stringstream(const basic_string<char_type, traits_type, SAlloc>& s, const allocator_type& a) + : basic_stringstream(s, ios_base::out | ios_base::in, a) {} // C++20 + template <class SAlloc> + basic_stringstream(const basic_string<char_type, traits_type, SAlloc>& s, + ios_base::openmode which, const allocator_type& a); // C++20 + template <class SAlloc> + explicit basic_stringstream(const basic_string<char_type, traits_type, SAlloc>& s, + ios_base::openmode which = ios_base::out | ios_base::in); // C++20 basic_stringstream(basic_stringstream&& rhs); // [stringstream.assign] Assign and swap: @@ -170,13 +243,21 @@ public: // [stringstream.members] Member functions: basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const; - basic_string<char_type, traits_type, allocator_type> str() const; - void str(const basic_string<char_type, traits_type, allocator_type>& str); + basic_string<char_type, traits_type, allocator_type> str() const; // before C++20 + basic_string<char_type, traits_type, allocator_type> str() const &; // C++20 + template <class SAlloc> + basic_string<char_type, traits_type, SAlloc> str(const SAlloc& sa) const; // C++20 + basic_string<char_type, traits_type, allocator_type> str() &&; // C++20 + basic_string_view<char_type, traits_type> view() const noexcept; // C++20 + void str(const basic_string<char_type, traits_type, allocator_type>& s); + template <class SAlloc> + void str(const basic_string<char_type, traits_type, SAlloc>& s); // C++20 + void str(basic_string<char_type, traits_type, allocator_type>&& s); // C++20 }; template <class charT, class traits, class Allocator> - void swap(basic_stringstream<charT, traits, Allocator>& x, - basic_stringstream<charT, traits, Allocator>& y); +void swap(basic_stringstream<charT, traits, Allocator>& x, + basic_stringstream<charT, traits, Allocator>& y); typedef basic_stringstream<char> stringstream; typedef basic_stringstream<wchar_t> wstringstream; @@ -187,6 +268,7 @@ typedef basic_stringstream<wchar_t> wstringstream; #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__fwd/sstream.h> #include <__utility/swap.h> #include <istream> #include <ostream> @@ -201,6 +283,14 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> +// TODO(LLVM-19): Remove this once we drop support for Clang 16, +// which had this bug: https://github.com/llvm/llvm-project/issues/40363 +#ifdef _WIN32 +#define _LIBCPP_HIDE_FROM_ABI_SSTREAM _LIBCPP_ALWAYS_INLINE +#else +#define _LIBCPP_HIDE_FROM_ABI_SSTREAM _LIBCPP_HIDE_FROM_ABI +#endif + _LIBCPP_BEGIN_NAMESPACE_STD // Class template basic_stringbuf [stringbuf] @@ -224,6 +314,8 @@ private: string_type __str_; mutable char_type* __hm_; ios_base::openmode __mode_; + _LIBCPP_HIDE_FROM_ABI void __init_buf_ptrs(); + _LIBCPP_HIDE_FROM_ABI void __move_init(basic_stringbuf&& __rhs); public: // [stringbuf.cons] constructors: @@ -243,15 +335,106 @@ public: str(__s); } - basic_stringbuf(basic_stringbuf&& __rhs); +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI explicit basic_stringbuf(const allocator_type& __a) + : basic_stringbuf(ios_base::in | ios_base::out, __a) {} + + _LIBCPP_HIDE_FROM_ABI basic_stringbuf(ios_base::openmode __wch, const allocator_type& __a) + : __str_(__a), __hm_(nullptr), __mode_(__wch) {} + + _LIBCPP_HIDE_FROM_ABI explicit basic_stringbuf(string_type&& __s, + ios_base::openmode __wch = ios_base::in | ios_base::out) + : __str_(std::move(__s)), __hm_(nullptr), __mode_(__wch) { + __init_buf_ptrs(); + } + + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI + basic_stringbuf(const basic_string<char_type, traits_type, _SAlloc>& __s, const allocator_type& __a) + : basic_stringbuf(__s, ios_base::in | ios_base::out, __a) {} + + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI basic_stringbuf( + const basic_string<char_type, traits_type, _SAlloc>& __s, ios_base::openmode __wch, const allocator_type& __a) + : __str_(__s, __a), __hm_(nullptr), __mode_(__wch) { + __init_buf_ptrs(); + } + + template <class _SAlloc> + requires (!is_same_v<_SAlloc, allocator_type>) + _LIBCPP_HIDE_FROM_ABI explicit basic_stringbuf(const basic_string<char_type, traits_type, _SAlloc>& __s, + ios_base::openmode __wch = ios_base::in | ios_base::out) + : __str_(__s), __hm_(nullptr), __mode_(__wch) { + __init_buf_ptrs(); + } +#endif // _LIBCPP_STD_VER >= 20 + + basic_stringbuf(basic_stringbuf&& __rhs) : __mode_(__rhs.__mode_) { __move_init(std::move(__rhs)); } + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& __a) + : basic_stringbuf(__rhs.__mode_, __a) { + __move_init(std::move(__rhs)); + } +#endif // [stringbuf.assign] Assign and swap: basic_stringbuf& operator=(basic_stringbuf&& __rhs); - void swap(basic_stringbuf& __rhs); + void swap(basic_stringbuf& __rhs) +#if _LIBCPP_STD_VER >= 20 + noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value || + allocator_traits<allocator_type>::is_always_equal::value) +#endif + ; // [stringbuf.members] Member functions: + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const noexcept { return __str_.get_allocator(); } +#endif + +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY) string_type str() const; - void str(const string_type& __s); +#else + _LIBCPP_HIDE_FROM_ABI_SSTREAM string_type str() const & { return str(__str_.get_allocator()); } + + _LIBCPP_HIDE_FROM_ABI_SSTREAM string_type str() && { + const basic_string_view<_CharT, _Traits> __view = view(); + string_type __result(std::move(__str_), __view.data() - __str_.data(), __view.size()); + __str_.clear(); + __init_buf_ptrs(); + return __result; + } +#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY) + +#if _LIBCPP_STD_VER >= 20 + template <class _SAlloc> + requires __is_allocator<_SAlloc>::value + _LIBCPP_HIDE_FROM_ABI basic_string<char_type, traits_type, _SAlloc> str(const _SAlloc& __sa) const { + return basic_string<_CharT, _Traits, _SAlloc>(view(), __sa); + } + + _LIBCPP_HIDE_FROM_ABI basic_string_view<char_type, traits_type> view() const noexcept; +#endif + + void str(const string_type& __s) { + __str_ = __s; + __init_buf_ptrs(); + } + +#if _LIBCPP_STD_VER >= 20 + template <class _SAlloc> + requires (!is_same_v<_SAlloc, allocator_type>) + _LIBCPP_HIDE_FROM_ABI void str(const basic_string<char_type, traits_type, _SAlloc>& __s) { + __str_ = __s; + __init_buf_ptrs(); + } + + _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { + __str_ = std::move(__s); + __init_buf_ptrs(); + } +#endif // _LIBCPP_STD_VER >= 20 protected: // [stringbuf.virtuals] Overridden virtual functions: @@ -268,9 +451,7 @@ protected: }; template <class _CharT, class _Traits, class _Allocator> -basic_stringbuf<_CharT, _Traits, _Allocator>::basic_stringbuf(basic_stringbuf&& __rhs) - : __mode_(__rhs.__mode_) -{ +_LIBCPP_HIDE_FROM_ABI void basic_stringbuf<_CharT, _Traits, _Allocator>::__move_init(basic_stringbuf&& __rhs) { char_type* __p = const_cast<char_type*>(__rhs.__str_.data()); ptrdiff_t __binp = -1; ptrdiff_t __ninp = -1; @@ -359,6 +540,10 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::operator=(basic_stringbuf&& __rhs) template <class _CharT, class _Traits, class _Allocator> void basic_stringbuf<_CharT, _Traits, _Allocator>::swap(basic_stringbuf& __rhs) +#if _LIBCPP_STD_VER >= 20 + noexcept(allocator_traits<_Allocator>::propagate_on_container_swap::value || + allocator_traits<_Allocator>::is_always_equal::value) +#endif { char_type* __p = const_cast<char_type*>(__rhs.__str_.data()); ptrdiff_t __rbinp = -1; @@ -438,49 +623,42 @@ inline _LIBCPP_INLINE_VISIBILITY void swap(basic_stringbuf<_CharT, _Traits, _Allocator>& __x, basic_stringbuf<_CharT, _Traits, _Allocator>& __y) +#if _LIBCPP_STD_VER >= 20 + noexcept(noexcept(__x.swap(__y))) +#endif { __x.swap(__y); } +#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY) template <class _CharT, class _Traits, class _Allocator> basic_string<_CharT, _Traits, _Allocator> -basic_stringbuf<_CharT, _Traits, _Allocator>::str() const -{ - if (__mode_ & ios_base::out) - { +basic_stringbuf<_CharT, _Traits, _Allocator>::str() const { + if (__mode_ & ios_base::out) { if (__hm_ < this->pptr()) __hm_ = this->pptr(); return string_type(this->pbase(), __hm_, __str_.get_allocator()); - } - else if (__mode_ & ios_base::in) + } else if (__mode_ & ios_base::in) return string_type(this->eback(), this->egptr(), __str_.get_allocator()); return string_type(__str_.get_allocator()); } +#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_BUILDING_LIBRARY) template <class _CharT, class _Traits, class _Allocator> -void -basic_stringbuf<_CharT, _Traits, _Allocator>::str(const string_type& __s) -{ - __str_ = __s; +_LIBCPP_HIDE_FROM_ABI void basic_stringbuf<_CharT, _Traits, _Allocator>::__init_buf_ptrs() { __hm_ = nullptr; - if (__mode_ & ios_base::in) - { - __hm_ = const_cast<char_type*>(__str_.data()) + __str_.size(); - this->setg(const_cast<char_type*>(__str_.data()), - const_cast<char_type*>(__str_.data()), - __hm_); + char_type* __data = const_cast<char_type*>(__str_.data()); + typename string_type::size_type __sz = __str_.size(); + if (__mode_ & ios_base::in) { + __hm_ = __data + __sz; + this->setg(__data, __data, __hm_); } - if (__mode_ & ios_base::out) - { - typename string_type::size_type __sz = __str_.size(); - __hm_ = const_cast<char_type*>(__str_.data()) + __sz; + if (__mode_ & ios_base::out) { + __hm_ = __data + __sz; __str_.resize(__str_.capacity()); - this->setp(const_cast<char_type*>(__str_.data()), - const_cast<char_type*>(__str_.data()) + __str_.size()); - if (__mode_ & (ios_base::app | ios_base::ate)) - { - while (__sz > INT_MAX) - { + this->setp(__data, __data + __str_.size()); + if (__mode_ & (ios_base::app | ios_base::ate)) { + while (__sz > INT_MAX) { this->pbump(INT_MAX); __sz -= INT_MAX; } @@ -490,6 +668,20 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::str(const string_type& __s) } } +#if _LIBCPP_STD_VER >= 20 +template <class _CharT, class _Traits, class _Allocator> +_LIBCPP_HIDE_FROM_ABI basic_string_view<_CharT, _Traits> +basic_stringbuf<_CharT, _Traits, _Allocator>::view() const noexcept { + if (__mode_ & ios_base::out) { + if (__hm_ < this->pptr()) + __hm_ = this->pptr(); + return basic_string_view<_CharT, _Traits>(this->pbase(), __hm_); + } else if (__mode_ & ios_base::in) + return basic_string_view<_CharT, _Traits>(this->eback(), this->egptr()); + return basic_string_view<_CharT, _Traits>(); +} +#endif // _LIBCPP_STD_VER >= 20 + template <class _CharT, class _Traits, class _Allocator> typename basic_stringbuf<_CharT, _Traits, _Allocator>::int_type basic_stringbuf<_CharT, _Traits, _Allocator>::underflow() @@ -536,16 +728,16 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::overflow(int_type __c) { if (!traits_type::eq_int_type(__c, traits_type::eof())) { - ptrdiff_t __ninp = this->gptr() - this->eback(); + ptrdiff_t __ninp = this->gptr() - this->eback(); if (this->pptr() == this->epptr()) { if (!(__mode_ & ios_base::out)) return traits_type::eof(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS - ptrdiff_t __nout = this->pptr() - this->pbase(); +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + ptrdiff_t __nout = this->pptr() - this->pbase(); ptrdiff_t __hm = __hm_ - this->pbase(); __str_.push_back(char_type()); __str_.resize(__str_.capacity()); @@ -553,13 +745,13 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::overflow(int_type __c) this->setp(__p, __p + __str_.size()); this->__pbump(__nout); __hm_ = this->pbase() + __hm; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { return traits_type::eof(); } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } __hm_ = _VSTD::max(this->pptr() + 1, __hm_); if (__mode_ & ios_base::in) @@ -619,7 +811,7 @@ basic_stringbuf<_CharT, _Traits, _Allocator>::seekoff(off_type __off, if (__wch & ios_base::out) { this->setp(this->pbase(), this->epptr()); - this->pbump(__noff); + this->__pbump(__noff); } return pos_type(__noff); } @@ -660,6 +852,28 @@ public: , __sb_(__s, __wch | ios_base::in) { } +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI basic_istringstream(ios_base::openmode __wch, const _Allocator& __a) + : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__wch | ios_base::in, __a) {} + + _LIBCPP_HIDE_FROM_ABI explicit basic_istringstream(string_type&& __s, ios_base::openmode __wch = ios_base::in) + : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(std::move(__s), __wch | ios_base::in) {} + + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI basic_istringstream(const basic_string<_CharT, _Traits, _SAlloc>& __s, const _Allocator& __a) + : basic_istringstream(__s, ios_base::in, __a) {} + + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI basic_istringstream( + const basic_string<_CharT, _Traits, _SAlloc>& __s, ios_base::openmode __wch, const _Allocator& __a) + : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::in, __a) {} + + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI explicit basic_istringstream(const basic_string<_CharT, _Traits, _SAlloc>& __s, + ios_base::openmode __wch = ios_base::in) + : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::in) {} +#endif // _LIBCPP_STD_VER >= 20 + _LIBCPP_INLINE_VISIBILITY basic_istringstream(basic_istringstream&& __rhs) : basic_istream<_CharT, _Traits>(_VSTD::move(__rhs)) @@ -685,14 +899,33 @@ public: basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const { return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(&__sb_); } - _LIBCPP_INLINE_VISIBILITY - string_type str() const { - return __sb_.str(); + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI string_type str() const & { return __sb_.str(); } + + template <class _SAlloc> + requires __is_allocator<_SAlloc>::value + _LIBCPP_HIDE_FROM_ABI basic_string<char_type, traits_type, _SAlloc> str(const _SAlloc& __sa) const { + return __sb_.str(__sa); } - _LIBCPP_INLINE_VISIBILITY - void str(const string_type& __s) { + + _LIBCPP_HIDE_FROM_ABI string_type str() && { return std::move(__sb_).str(); } + + _LIBCPP_HIDE_FROM_ABI basic_string_view<char_type, traits_type> view() const noexcept { return __sb_.view(); } +#else // _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI string_type str() const { return __sb_.str(); } +#endif // _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI void str(const string_type& __s) { __sb_.str(__s); } + +#if _LIBCPP_STD_VER >= 20 + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI void str(const basic_string<char_type, traits_type, _SAlloc>& __s) { __sb_.str(__s); } + + _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { __sb_.str(std::move(__s)); } +#endif // _LIBCPP_STD_VER >= 20 }; template <class _CharT, class _Traits, class _Allocator> @@ -740,6 +973,29 @@ public: , __sb_(__s, __wch | ios_base::out) { } +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI basic_ostringstream(ios_base::openmode __wch, const _Allocator& __a) + : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__wch | ios_base::out, __a) {} + + _LIBCPP_HIDE_FROM_ABI explicit basic_ostringstream(string_type&& __s, ios_base::openmode __wch = ios_base::out) + : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(std::move(__s), __wch | ios_base::out) {} + + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI basic_ostringstream(const basic_string<_CharT, _Traits, _SAlloc>& __s, const _Allocator& __a) + : basic_ostringstream(__s, ios_base::out, __a) {} + + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI basic_ostringstream( + const basic_string<_CharT, _Traits, _SAlloc>& __s, ios_base::openmode __wch, const _Allocator& __a) + : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::out, __a) {} + + template <class _SAlloc> + requires (!is_same_v<_SAlloc, allocator_type>) + _LIBCPP_HIDE_FROM_ABI explicit basic_ostringstream(const basic_string<_CharT, _Traits, _SAlloc>& __s, + ios_base::openmode __wch = ios_base::out) + : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::out) {} +#endif // _LIBCPP_STD_VER >= 20 + _LIBCPP_INLINE_VISIBILITY basic_ostringstream(basic_ostringstream&& __rhs) : basic_ostream<_CharT, _Traits>(_VSTD::move(__rhs)) @@ -766,14 +1022,33 @@ public: basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const { return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(&__sb_); } - _LIBCPP_INLINE_VISIBILITY - string_type str() const { - return __sb_.str(); + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI string_type str() const & { return __sb_.str(); } + + template <class _SAlloc> + requires __is_allocator<_SAlloc>::value + _LIBCPP_HIDE_FROM_ABI basic_string<char_type, traits_type, _SAlloc> str(const _SAlloc& __sa) const { + return __sb_.str(__sa); } - _LIBCPP_INLINE_VISIBILITY - void str(const string_type& __s) { + + _LIBCPP_HIDE_FROM_ABI string_type str() && { return std::move(__sb_).str(); } + + _LIBCPP_HIDE_FROM_ABI basic_string_view<char_type, traits_type> view() const noexcept { return __sb_.view(); } +#else // _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI string_type str() const { return __sb_.str(); } +#endif // _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI void str(const string_type& __s) { __sb_.str(__s); } + +#if _LIBCPP_STD_VER >= 20 + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI void str(const basic_string<char_type, traits_type, _SAlloc>& __s) { __sb_.str(__s); } + + _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { __sb_.str(std::move(__s)); } +#endif // _LIBCPP_STD_VER >= 20 }; template <class _CharT, class _Traits, class _Allocator> @@ -821,6 +1096,29 @@ public: , __sb_(__s, __wch) { } +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI basic_stringstream(ios_base::openmode __wch, const _Allocator& __a) + : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__wch, __a) {} + + _LIBCPP_HIDE_FROM_ABI explicit basic_stringstream(string_type&& __s, ios_base::openmode __wch = ios_base::out | ios_base::in) + : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(std::move(__s), __wch) {} + + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI basic_stringstream(const basic_string<_CharT, _Traits, _SAlloc>& __s, const _Allocator& __a) + : basic_stringstream(__s, ios_base::out | ios_base::in, __a) {} + + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI basic_stringstream( + const basic_string<_CharT, _Traits, _SAlloc>& __s, ios_base::openmode __wch, const _Allocator& __a) + : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch, __a) {} + + template <class _SAlloc> + requires (!is_same_v<_SAlloc, allocator_type>) + _LIBCPP_HIDE_FROM_ABI explicit basic_stringstream(const basic_string<_CharT, _Traits, _SAlloc>& __s, + ios_base::openmode __wch = ios_base::out | ios_base::in) + : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch) {} +#endif // _LIBCPP_STD_VER >= 20 + _LIBCPP_INLINE_VISIBILITY basic_stringstream(basic_stringstream&& __rhs) : basic_iostream<_CharT, _Traits>(_VSTD::move(__rhs)) @@ -846,14 +1144,33 @@ public: basic_stringbuf<char_type, traits_type, allocator_type>* rdbuf() const { return const_cast<basic_stringbuf<char_type, traits_type, allocator_type>*>(&__sb_); } - _LIBCPP_INLINE_VISIBILITY - string_type str() const { - return __sb_.str(); + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI string_type str() const & { return __sb_.str(); } + + template <class _SAlloc> + requires __is_allocator<_SAlloc>::value + _LIBCPP_HIDE_FROM_ABI basic_string<char_type, traits_type, _SAlloc> str(const _SAlloc& __sa) const { + return __sb_.str(__sa); } - _LIBCPP_INLINE_VISIBILITY - void str(const string_type& __s) { + + _LIBCPP_HIDE_FROM_ABI string_type str() && { return std::move(__sb_).str(); } + + _LIBCPP_HIDE_FROM_ABI basic_string_view<char_type, traits_type> view() const noexcept { return __sb_.view(); } +#else // _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI string_type str() const { return __sb_.str(); } +#endif // _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI void str(const string_type& __s) { __sb_.str(__s); } + +#if _LIBCPP_STD_VER >= 20 + template <class _SAlloc> + _LIBCPP_HIDE_FROM_ABI void str(const basic_string<char_type, traits_type, _SAlloc>& __s) { __sb_.str(__s); } + + _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { __sb_.str(std::move(__s)); } +#endif // _LIBCPP_STD_VER >= 20 }; template <class _CharT, class _Traits, class _Allocator> diff --git a/libcxx/include/stack b/libcxx/include/stack index d653d1bc7e49..437f57d76bd5 100644 --- a/libcxx/include/stack +++ b/libcxx/include/stack @@ -42,6 +42,7 @@ public: explicit stack(const container_type& c); explicit stack(container_type&& c); template <class InputIterator> stack(InputIterator first, InputIterator last); // since C++23 + template<container-compatible-range<T> R> stack(from_range_t, R&& rg); // since C++23 template <class Alloc> explicit stack(const Alloc& a); template <class Alloc> stack(const container_type& c, const Alloc& a); template <class Alloc> stack(container_type&& c, const Alloc& a); @@ -49,6 +50,8 @@ public: template <class Alloc> stack(stack&& c, const Alloc& a); template<class InputIterator, class Alloc> stack(InputIterator first, InputIterator last, const Alloc&); // since C++23 + template<container-compatible-range<T> R, class Alloc> + stack(from_range_t, R&& rg, const Alloc&); // since C++23 bool empty() const; size_type size() const; @@ -57,6 +60,8 @@ public: void push(const value_type& x); void push(value_type&& x); + template<container-compatible-range<T> R> + void push_range(R&& rg); // C++23 template <class... Args> reference emplace(Args&&... args); // reference in C++17 void pop(); @@ -69,6 +74,9 @@ template<class Container> template<class InputIterator> stack(InputIterator, InputIterator) -> stack<iter-value-type<InputIterator>>; // since C++23 +template<ranges::input_range R> + stack(from_range_t, R&&) -> stack<ranges::range_value_t<R>>; // since C++23 + template<class Container, class Allocator> stack(Container, Allocator) -> stack<typename Container::value_type, Container>; // C++17 @@ -77,6 +85,10 @@ template<class InputIterator, class Allocator> -> stack<iter-value-type<InputIterator>, deque<iter-value-type<InputIterator>, Allocator>>; // since C++23 +template<ranges::input_range R, class Allocator> + stack(from_range_t, R&&, Allocator) + -> stack<ranges::range_value_t<R>, deque<ranges::range_value_t<R>, Allocator>>; // since C++23 + template <class T, class Container> bool operator==(const stack<T, Container>& x, const stack<T, Container>& y); template <class T, class Container> @@ -89,6 +101,9 @@ template <class T, class Container> bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y); template <class T, class Container> bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y); +template<class T, three_way_comparable Container> + compare_three_way_result_t<Container> + operator<=>(const stack<T, Container>& x, const stack<T, Container>& y); // since C++20 template <class T, class Container> void swap(stack<T, Container>& x, stack<T, Container>& y) @@ -98,13 +113,19 @@ template <class T, class Container> */ +#include <__algorithm/ranges_copy.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> #include <__memory/uses_allocator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> +#include <__type_traits/is_same.h> #include <__utility/forward.h> #include <deque> -#include <type_traits> #include <version> // standard-mandated includes @@ -204,18 +225,30 @@ public: : c(_VSTD::move(__s.c), __a) {} #endif // _LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _InputIterator, - class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>> + class = __enable_if_t<__has_input_iterator_category<_InputIterator>::value>> _LIBCPP_HIDE_FROM_ABI stack(_InputIterator __first, _InputIterator __last) : c(__first, __last) {} + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + stack(from_range_t, _Range&& __range) : c(from_range, std::forward<_Range>(__range)) {} + template <class _InputIterator, class _Alloc, - class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = __enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = __enable_if_t<uses_allocator<container_type, _Alloc>::value>> _LIBCPP_HIDE_FROM_ABI stack(_InputIterator __first, _InputIterator __last, const _Alloc& __alloc) : c(__first, __last, __alloc) {} + + template <_ContainerCompatibleRange<_Tp> _Range, + class _Alloc, + class = __enable_if_t<uses_allocator<container_type, _Alloc>::value>> + _LIBCPP_HIDE_FROM_ABI + stack(from_range_t, _Range&& __range, const _Alloc& __alloc) + : c(from_range, std::forward<_Range>(__range), __alloc) {} + #endif _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY @@ -233,9 +266,23 @@ public: _LIBCPP_INLINE_VISIBILITY void push(value_type&& __v) {c.push_back(_VSTD::move(__v));} +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + void push_range(_Range&& __range) { + if constexpr (requires (container_type& __c) { + __c.append_range(std::forward<_Range>(__range)); + }) { + c.append_range(std::forward<_Range>(__range)); + } else { + ranges::copy(std::forward<_Range>(__range), std::back_inserter(c)); + } + } +#endif + template <class... _Args> _LIBCPP_INLINE_VISIBILITY -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 decltype(auto) emplace(_Args&&... __args) { return c.emplace_back(_VSTD::forward<_Args>(__args)...);} #else @@ -257,18 +304,18 @@ public: _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI const _Container& __get_container() const { return c; } - template <class T1, class _C1> + template <class _T1, class _OtherContainer> friend bool - operator==(const stack<T1, _C1>& __x, const stack<T1, _C1>& __y); + operator==(const stack<_T1, _OtherContainer>& __x, const stack<_T1, _OtherContainer>& __y); - template <class T1, class _C1> + template <class _T1, class _OtherContainer> friend bool - operator< (const stack<T1, _C1>& __x, const stack<T1, _C1>& __y); + operator< (const stack<_T1, _OtherContainer>& __x, const stack<_T1, _OtherContainer>& __y); }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template<class _Container, class = enable_if_t<!__is_allocator<_Container>::value> > @@ -284,18 +331,28 @@ stack(_Container, _Alloc) -> stack<typename _Container::value_type, _Container>; #endif -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template<class _InputIterator, - class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>> + class = __enable_if_t<__has_input_iterator_category<_InputIterator>::value>> stack(_InputIterator, _InputIterator) -> stack<__iter_value_type<_InputIterator>>; +template <ranges::input_range _Range> +stack(from_range_t, _Range&&) -> stack<ranges::range_value_t<_Range>>; + template<class _InputIterator, class _Alloc, - class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = __enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = __enable_if_t<__is_allocator<_Alloc>::value>> stack(_InputIterator, _InputIterator, _Alloc) -> stack<__iter_value_type<_InputIterator>, deque<__iter_value_type<_InputIterator>, _Alloc>>; + +template <ranges::input_range _Range, + class _Alloc, + class = __enable_if_t<__is_allocator<_Alloc>::value>> +stack(from_range_t, _Range&&, _Alloc) + -> stack<ranges::range_value_t<_Range>, deque<ranges::range_value_t<_Range>, _Alloc>>; + #endif template <class _Tp, class _Container> @@ -346,6 +403,17 @@ operator<=(const stack<_Tp, _Container>& __x, const stack<_Tp, _Container>& __y) return !(__y < __x); } +#if _LIBCPP_STD_VER >= 20 + +template <class _Tp, three_way_comparable _Container> +_LIBCPP_HIDE_FROM_ABI compare_three_way_result_t<_Container> +operator<=>(const stack<_Tp, _Container>& __x, const stack<_Tp, _Container>& __y) { + // clang 16 bug: declaring `friend operator<=>` causes "use of overloaded operator '*' is ambiguous" errors + return __x.__get_container() <=> __y.__get_container(); +} + +#endif + template <class _Tp, class _Container> inline _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_swappable<_Container>::value, void> @@ -366,6 +434,7 @@ _LIBCPP_END_NAMESPACE_STD #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> # include <functional> +# include <type_traits> #endif #endif // _LIBCPP_STACK diff --git a/libcxx/include/stdatomic.h b/libcxx/include/stdatomic.h index ff2a5682f5bb..9c002e52918e 100644 --- a/libcxx/include/stdatomic.h +++ b/libcxx/include/stdatomic.h @@ -121,7 +121,7 @@ using std::atomic_signal_fence // see below # pragma GCC system_header #endif -#if defined(__cplusplus) && _LIBCPP_STD_VER > 20 +#if defined(__cplusplus) && _LIBCPP_STD_VER >= 23 #include <atomic> #include <version> @@ -230,6 +230,6 @@ using std::atomic_thread_fence _LIBCPP_USING_IF_EXISTS; # include_next <stdatomic.h> # endif -#endif // defined(__cplusplus) && _LIBCPP_STD_VER > 20 +#endif // defined(__cplusplus) && _LIBCPP_STD_VER >= 23 #endif // _LIBCPP_STDATOMIC_H diff --git a/libcxx/include/stdexcept b/libcxx/include/stdexcept index 68de6ced174a..5428535a1022 100644 --- a/libcxx/include/stdexcept +++ b/libcxx/include/stdexcept @@ -43,8 +43,8 @@ public: #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include <cstdlib> -#include <exception> +#include <__exception/exception.h> +#include <__verbose_abort> #include <iosfwd> // for string forward decl #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -65,7 +65,7 @@ public: __libcpp_refstring& operator=(const __libcpp_refstring& __s) _NOEXCEPT; ~__libcpp_refstring(); - const char* c_str() const _NOEXCEPT {return __imp_;} + _LIBCPP_HIDE_FROM_ABI const char* c_str() const _NOEXCEPT {return __imp_;} }; #endif // !_LIBCPP_ABI_VCRUNTIME @@ -74,7 +74,7 @@ _LIBCPP_END_NAMESPACE_STD namespace std // purposefully not using versioning namespace { -class _LIBCPP_EXCEPTION_ABI logic_error +class _LIBCPP_EXPORTED_FROM_ABI logic_error : public exception { #ifndef _LIBCPP_ABI_VCRUNTIME @@ -97,7 +97,7 @@ public: #endif }; -class _LIBCPP_EXCEPTION_ABI runtime_error +class _LIBCPP_EXPORTED_FROM_ABI runtime_error : public exception { #ifndef _LIBCPP_ABI_VCRUNTIME @@ -120,7 +120,7 @@ public: #endif // _LIBCPP_ABI_VCRUNTIME }; -class _LIBCPP_EXCEPTION_ABI domain_error +class _LIBCPP_EXPORTED_FROM_ABI domain_error : public logic_error { public: @@ -128,12 +128,12 @@ public: _LIBCPP_INLINE_VISIBILITY explicit domain_error(const char* __s) : logic_error(__s) {} #ifndef _LIBCPP_ABI_VCRUNTIME - domain_error(const domain_error&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI domain_error(const domain_error&) _NOEXCEPT = default; ~domain_error() _NOEXCEPT override; #endif }; -class _LIBCPP_EXCEPTION_ABI invalid_argument +class _LIBCPP_EXPORTED_FROM_ABI invalid_argument : public logic_error { public: @@ -141,24 +141,24 @@ public: _LIBCPP_INLINE_VISIBILITY explicit invalid_argument(const char* __s) : logic_error(__s) {} #ifndef _LIBCPP_ABI_VCRUNTIME - invalid_argument(const invalid_argument&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI invalid_argument(const invalid_argument&) _NOEXCEPT = default; ~invalid_argument() _NOEXCEPT override; #endif }; -class _LIBCPP_EXCEPTION_ABI length_error +class _LIBCPP_EXPORTED_FROM_ABI length_error : public logic_error { public: _LIBCPP_INLINE_VISIBILITY explicit length_error(const string& __s) : logic_error(__s) {} _LIBCPP_INLINE_VISIBILITY explicit length_error(const char* __s) : logic_error(__s) {} #ifndef _LIBCPP_ABI_VCRUNTIME - length_error(const length_error&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI length_error(const length_error&) _NOEXCEPT = default; ~length_error() _NOEXCEPT override; #endif }; -class _LIBCPP_EXCEPTION_ABI out_of_range +class _LIBCPP_EXPORTED_FROM_ABI out_of_range : public logic_error { public: @@ -166,12 +166,12 @@ public: _LIBCPP_INLINE_VISIBILITY explicit out_of_range(const char* __s) : logic_error(__s) {} #ifndef _LIBCPP_ABI_VCRUNTIME - out_of_range(const out_of_range&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI out_of_range(const out_of_range&) _NOEXCEPT = default; ~out_of_range() _NOEXCEPT override; #endif }; -class _LIBCPP_EXCEPTION_ABI range_error +class _LIBCPP_EXPORTED_FROM_ABI range_error : public runtime_error { public: @@ -179,12 +179,12 @@ public: _LIBCPP_INLINE_VISIBILITY explicit range_error(const char* __s) : runtime_error(__s) {} #ifndef _LIBCPP_ABI_VCRUNTIME - range_error(const range_error&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI range_error(const range_error&) _NOEXCEPT = default; ~range_error() _NOEXCEPT override; #endif }; -class _LIBCPP_EXCEPTION_ABI overflow_error +class _LIBCPP_EXPORTED_FROM_ABI overflow_error : public runtime_error { public: @@ -192,12 +192,12 @@ public: _LIBCPP_INLINE_VISIBILITY explicit overflow_error(const char* __s) : runtime_error(__s) {} #ifndef _LIBCPP_ABI_VCRUNTIME - overflow_error(const overflow_error&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI overflow_error(const overflow_error&) _NOEXCEPT = default; ~overflow_error() _NOEXCEPT override; #endif }; -class _LIBCPP_EXCEPTION_ABI underflow_error +class _LIBCPP_EXPORTED_FROM_ABI underflow_error : public runtime_error { public: @@ -205,7 +205,7 @@ public: _LIBCPP_INLINE_VISIBILITY explicit underflow_error(const char* __s) : runtime_error(__s) {} #ifndef _LIBCPP_ABI_VCRUNTIME - underflow_error(const underflow_error&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI underflow_error(const underflow_error&) _NOEXCEPT = default; ~underflow_error() _NOEXCEPT override; #endif }; @@ -215,96 +215,93 @@ public: _LIBCPP_BEGIN_NAMESPACE_STD // in the dylib -_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_runtime_error(const char*); +_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_runtime_error(const char*); _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_logic_error(const char*__msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw logic_error(__msg); #else - ((void)__msg); - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("logic_error was thrown in -fno-exceptions mode with message \"%s\"", __msg); #endif } _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_domain_error(const char*__msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw domain_error(__msg); #else - ((void)__msg); - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("domain_error was thrown in -fno-exceptions mode with message \"%s\"", __msg); #endif } _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_invalid_argument(const char*__msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw invalid_argument(__msg); #else - ((void)__msg); - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("invalid_argument was thrown in -fno-exceptions mode with message \"%s\"", __msg); #endif } _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_length_error(const char*__msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw length_error(__msg); #else - ((void)__msg); - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("length_error was thrown in -fno-exceptions mode with message \"%s\"", __msg); #endif } _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_out_of_range(const char*__msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw out_of_range(__msg); #else - ((void)__msg); - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("out_of_range was thrown in -fno-exceptions mode with message \"%s\"", __msg); #endif } _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_range_error(const char*__msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw range_error(__msg); #else - ((void)__msg); - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("range_error was thrown in -fno-exceptions mode with message \"%s\"", __msg); #endif } _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_overflow_error(const char*__msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw overflow_error(__msg); #else - ((void)__msg); - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("overflow_error was thrown in -fno-exceptions mode with message \"%s\"", __msg); #endif } _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_underflow_error(const char*__msg) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw underflow_error(__msg); #else - ((void)__msg); - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("underflow_error was thrown in -fno-exceptions mode with message \"%s\"", __msg); #endif } _LIBCPP_END_NAMESPACE_STD +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstdlib> +# include <exception> +#endif + #endif // _LIBCPP_STDEXCEPT diff --git a/libcxx/include/stdlib.h b/libcxx/include/stdlib.h index 4dd3a9c14ab0..614e3730c2f6 100644 --- a/libcxx/include/stdlib.h +++ b/libcxx/include/stdlib.h @@ -109,16 +109,15 @@ extern "C++" { #endif // MSVCRT already has the correct prototype in <stdlib.h> if __cplusplus is defined -#if !defined(_LIBCPP_MSVCRT) && !defined(__sun__) +#if !defined(_LIBCPP_MSVCRT) _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY long abs(long __x) _NOEXCEPT { return __builtin_labs(__x); } _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY long long abs(long long __x) _NOEXCEPT { return __builtin_llabs(__x); } -#endif // !defined(_LIBCPP_MSVCRT) && !defined(__sun__) +#endif // !defined(_LIBCPP_MSVCRT) -#if !defined(__sun__) _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY float abs(float __lcpp_x) _NOEXCEPT { return __builtin_fabsf(__lcpp_x); // Use builtins to prevent needing math.h } @@ -131,7 +130,6 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY long double abs(long double __lcpp_x) _NOEXCEPT { return __builtin_fabsl(__lcpp_x); } -#endif // !defined(__sun__) // div @@ -146,7 +144,7 @@ abs(long double __lcpp_x) _NOEXCEPT { #endif // MSVCRT already has the correct prototype in <stdlib.h> if __cplusplus is defined -#if !defined(_LIBCPP_MSVCRT) && !defined(__sun__) +#if !defined(_LIBCPP_MSVCRT) inline _LIBCPP_INLINE_VISIBILITY ldiv_t div(long __x, long __y) _NOEXCEPT { return ::ldiv(__x, __y); } @@ -156,7 +154,7 @@ inline _LIBCPP_INLINE_VISIBILITY lldiv_t div(long long __x, return ::lldiv(__x, __y); } #endif -#endif // _LIBCPP_MSVCRT / __sun__ +#endif // _LIBCPP_MSVCRT } // extern "C++" #endif // __cplusplus diff --git a/libcxx/include/stop_token b/libcxx/include/stop_token new file mode 100644 index 000000000000..dd43ac298b9a --- /dev/null +++ b/libcxx/include/stop_token @@ -0,0 +1,49 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_STOP_TOKEN +#define _LIBCPP_STOP_TOKEN + +/* + +namespace std { + // [stoptoken], class stop_token + class stop_token; + + // [stopsource], class stop_source + class stop_source; + + // no-shared-stop-state indicator + struct nostopstate_t { + explicit nostopstate_t() = default; + }; + inline constexpr nostopstate_t nostopstate{}; + + // [stopcallback], class template stop_callback + template<class Callback> + class stop_callback; + +*/ + +#include <__assert> // all public C++ headers provide the assertion handler +#include <__config> +#include <__stop_token/stop_callback.h> +#include <__stop_token/stop_source.h> +#include <__stop_token/stop_token.h> +#include <version> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#ifdef _LIBCPP_HAS_NO_THREADS +# error "<stop_token> is not supported since libc++ has been configured without support for threads." +#endif + +#endif // _LIBCPP_STOP_TOKEN diff --git a/libcxx/include/streambuf b/libcxx/include/streambuf index d473df103475..095ac7d3ad83 100644 --- a/libcxx/include/streambuf +++ b/libcxx/include/streambuf @@ -109,6 +109,7 @@ protected: #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__fwd/streambuf.h> #include <cstdint> #include <ios> #include <iosfwd> @@ -489,11 +490,9 @@ basic_streambuf<_CharT, _Traits>::overflow(int_type) } extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<char>; -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ios<char>; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<wchar_t>; -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ios<wchar_t>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/string b/libcxx/include/string index 9f5838d42583..4b9627369816 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -119,11 +119,13 @@ public: explicit basic_string(const T& t, const Allocator& a = Allocator()); // C++17, constexpr since C++20 basic_string(const value_type* s, const allocator_type& a = allocator_type()); // constexpr since C++20 basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); // constexpr since C++20 - basic_string(nullptr_t) = delete; // C++2b + basic_string(nullptr_t) = delete; // C++23 basic_string(size_type n, value_type c, const allocator_type& a = allocator_type()); // constexpr since C++20 template<class InputIterator> basic_string(InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()); // constexpr since C++20 + template<container-compatible-range<charT> R> + constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); // since C++23 basic_string(initializer_list<value_type>, const Allocator& = Allocator()); // constexpr since C++20 basic_string(const basic_string&, const Allocator&); // constexpr since C++20 basic_string(basic_string&&, const Allocator&); // constexpr since C++20 @@ -140,7 +142,7 @@ public: allocator_type::propagate_on_container_move_assignment::value || allocator_type::is_always_equal::value ); // C++17, constexpr since C++20 basic_string& operator=(const value_type* s); // constexpr since C++20 - basic_string& operator=(nullptr_t) = delete; // C++2b + basic_string& operator=(nullptr_t) = delete; // C++23 basic_string& operator=(value_type c); // constexpr since C++20 basic_string& operator=(initializer_list<value_type>); // constexpr since C++20 @@ -200,6 +202,8 @@ public: basic_string& append(size_type n, value_type c); // constexpr since C++20 template<class InputIterator> basic_string& append(InputIterator first, InputIterator last); // constexpr since C++20 + template<container-compatible-range<charT> R> + constexpr basic_string& append_range(R&& rg); // C++23 basic_string& append(initializer_list<value_type>); // constexpr since C++20 void push_back(value_type c); // constexpr since C++20 @@ -221,6 +225,8 @@ public: basic_string& assign(size_type n, value_type c); // constexpr since C++20 template<class InputIterator> basic_string& assign(InputIterator first, InputIterator last); // constexpr since C++20 + template<container-compatible-range<charT> R> + constexpr basic_string& assign_range(R&& rg); // C++23 basic_string& assign(initializer_list<value_type>); // constexpr since C++20 basic_string& insert(size_type pos1, const basic_string& str); // constexpr since C++20 @@ -237,6 +243,8 @@ public: iterator insert(const_iterator p, size_type n, value_type c); // constexpr since C++20 template<class InputIterator> iterator insert(const_iterator p, InputIterator first, InputIterator last); // constexpr since C++20 + template<container-compatible-range<charT> R> + constexpr iterator insert_range(const_iterator p, R&& rg); // C++23 iterator insert(const_iterator p, initializer_list<value_type>); // constexpr since C++20 basic_string& erase(size_type pos = 0, size_type n = npos); // constexpr since C++20 @@ -262,6 +270,8 @@ public: basic_string& replace(const_iterator i1, const_iterator i2, size_type n, value_type c); // constexpr since C++20 template<class InputIterator> basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); // constexpr since C++20 + template<container-compatible-range<charT> R> + constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); // C++23 basic_string& replace(const_iterator i1, const_iterator i2, initializer_list<value_type>); // constexpr since C++20 size_type copy(value_type* s, size_type n, size_type pos = 0) const; // constexpr since C++20 @@ -342,9 +352,9 @@ public: constexpr bool ends_with(charT c) const noexcept; // C++20 constexpr bool ends_with(const charT* s) const; // C++20 - constexpr bool contains(basic_string_view<charT, traits> sv) const noexcept; // C++2b - constexpr bool contains(charT c) const noexcept; // C++2b - constexpr bool contains(const charT* s) const; // C++2b + constexpr bool contains(basic_string_view<charT, traits> sv) const noexcept; // C++23 + constexpr bool contains(charT c) const noexcept; // C++23 + constexpr bool contains(const charT* s) const; // C++23 }; template<class InputIterator, @@ -354,6 +364,26 @@ basic_string(InputIterator, InputIterator, Allocator = Allocator()) char_traits<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17 +template<ranges::input_range R, + class Allocator = allocator<ranges::range_value_t<R>>> + basic_string(from_range_t, R&&, Allocator = Allocator()) + -> basic_string<ranges::range_value_t<R>, char_traits<ranges::range_value_t<R>>, + Allocator>; // C++23 + +template<class charT, + class traits, + class Allocator = allocator<charT>> + explicit basic_string(basic_string_view<charT, traits>, const Allocator& = Allocator()) + -> basic_string<charT, traits, Allocator>; // C++17 + +template<class charT, + class traits, + class Allocator = allocator<charT>> + basic_string(basic_string_view<charT, traits>, + typename see below::size_type, typename see below::size_type, + const Allocator& = Allocator()) + -> basic_string<charT, traits, Allocator>; // C++17 + template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, @@ -524,11 +554,11 @@ template <> struct hash<u16string>; template <> struct hash<u32string>; template <> struct hash<wstring>; -basic_string<char> operator "" s( const char *str, size_t len ); // C++14, constexpr since C++20 -basic_string<wchar_t> operator "" s( const wchar_t *str, size_t len ); // C++14, constexpr since C++20 -constexpr basic_string<char8_t> operator "" s( const char8_t *str, size_t len ); // C++20 -basic_string<char16_t> operator "" s( const char16_t *str, size_t len ); // C++14, constexpr since C++20 -basic_string<char32_t> operator "" s( const char32_t *str, size_t len ); // C++14, constexpr since C++20 +basic_string<char> operator""s( const char *str, size_t len ); // C++14, constexpr since C++20 +basic_string<wchar_t> operator""s( const wchar_t *str, size_t len ); // C++14, constexpr since C++20 +constexpr basic_string<char8_t> operator""s( const char8_t *str, size_t len ); // C++20 +basic_string<char16_t> operator""s( const char16_t *str, size_t len ); // C++14, constexpr since C++20 +basic_string<char32_t> operator""s( const char32_t *str, size_t len ); // C++14, constexpr since C++20 } // std @@ -540,7 +570,6 @@ basic_string<char32_t> operator "" s( const char32_t *str, size_t len ); #include <__algorithm/remove_if.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include <__debug> #include <__format/enable_insertable.h> #include <__functional/hash.h> #include <__functional/unary_function.h> @@ -550,6 +579,7 @@ basic_string<char32_t> operator "" s( const char32_t *str, size_t len ); #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> #include <__iterator/wrap_iter.h> +#include <__memory/addressof.h> #include <__memory/allocate_at_least.h> #include <__memory/allocator.h> #include <__memory/allocator_traits.h> @@ -558,23 +588,38 @@ basic_string<char32_t> operator "" s( const char32_t *str, size_t len ); #include <__memory/pointer_traits.h> #include <__memory/swap_allocator.h> #include <__memory_resource/polymorphic_allocator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> +#include <__ranges/size.h> #include <__string/char_traits.h> #include <__string/extern_template_lists.h> #include <__type_traits/is_allocator.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_standard_layout.h> +#include <__type_traits/is_trivial.h> #include <__type_traits/noexcept_move_assign_container.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/void_t.h> #include <__utility/auto_cast.h> +#include <__utility/declval.h> +#include <__utility/forward.h> +#include <__utility/is_pointer_in_range.h> #include <__utility/move.h> #include <__utility/swap.h> #include <__utility/unreachable.h> #include <climits> #include <cstdint> #include <cstdio> // EOF -#include <cstdlib> #include <cstring> #include <limits> #include <stdexcept> #include <string_view> -#include <type_traits> #include <version> #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -632,7 +677,8 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, _CharT __y); -extern template _LIBCPP_FUNC_VIS string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); +extern template _LIBCPP_EXPORTED_FROM_ABI string operator+ + <char, char_traits<char>, allocator<char> >(char const*, string const&); template <class _Iter> struct __string_is_trivial_iterator : public false_type {}; @@ -652,6 +698,7 @@ struct __can_be_converted_to_string_view : public _BoolConstant< > {}; struct __uninitialized_size_tag {}; +struct __init_with_sentinel_tag {}; template<class _CharT, class _Traits, class _Allocator> class basic_string @@ -810,15 +857,21 @@ private: __set_long_pointer(__allocation); __set_long_size(__size); } - std::__debug_db_insert_c(this); + } + + template <class _Iter, class _Sent> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + basic_string(__init_with_sentinel_tag, _Iter __first, _Sent __last, const allocator_type& __a) + : __r_(__default_init_tag(), __a) { + __init_with_sentinel(std::move(__first), std::move(__last)); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator __make_iterator(pointer __p) { - return iterator(this, __p); + return iterator(__p); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_iterator __make_const_iterator(const_pointer __p) const { - return const_iterator(this, __p); + return const_iterator(__p); } public: @@ -827,7 +880,6 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) : __r_(__default_init_tag(), __default_init_tag()) { - std::__debug_db_insert_c(this); __default_init(); } @@ -838,12 +890,24 @@ public: _NOEXCEPT #endif : __r_(__default_init_tag(), __a) { - std::__debug_db_insert_c(this); __default_init(); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str); - _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str, const allocator_type& __a); + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str) + : __r_(__default_init_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc())) { + if (!__str.__is_long()) + __r_.first() = __str.__r_.first(); + else + __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str, const allocator_type& __a) + : __r_(__default_init_tag(), __a) { + if (!__str.__is_long()) + __r_.first() = __str.__r_.first(); + else + __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), __str.__get_long_size()); + } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str) @@ -854,9 +918,6 @@ public: # endif : __r_(std::move(__str.__r_)) { __str.__default_init(); - std::__debug_db_insert_c(this); - if (__is_long()) - std::__debug_db_swap(this, &__str); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(basic_string&& __str, const allocator_type& __a) @@ -869,49 +930,47 @@ public: __r_.first() = __str.__r_.first(); __str.__default_init(); } - std::__debug_db_insert_c(this); - if (__is_long()) - std::__debug_db_swap(this, &__str); } #endif // _LIBCPP_CXX03_LANG - template <class = __enable_if_t<__is_allocator<_Allocator>::value, nullptr_t> > + template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s) : __r_(__default_init_tag(), __default_init_tag()) { - _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "basic_string(const char*) detected nullptr"); __init(__s, traits_type::length(__s)); - std::__debug_db_insert_c(this); } - template <class = __enable_if_t<__is_allocator<_Allocator>::value, nullptr_t> > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, const _Allocator& __a); + template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, const _Allocator& __a) + : __r_(__default_init_tag(), __a) { + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "basic_string(const char*, allocator) detected nullptr"); + __init(__s, traits_type::length(__s)); + } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 basic_string(nullptr_t) = delete; #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n) : __r_(__default_init_tag(), __default_init_tag()) { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr"); __init(__s, __n); - std::__debug_db_insert_c(this); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _CharT* __s, size_type __n, const _Allocator& __a) : __r_(__default_init_tag(), __a) { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, + "basic_string(const char*, n, allocator) detected nullptr"); __init(__s, __n); - std::__debug_db_insert_c(this); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c) : __r_(__default_init_tag(), __default_init_tag()) { __init(__n, __c); - std::__debug_db_insert_c(this); } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr basic_string(basic_string&& __str, size_type __pos, const _Allocator& __alloc = _Allocator()) : basic_string(std::move(__str), __pos, npos, __alloc) {} @@ -934,18 +993,23 @@ public: // Perform a copy because the allocators are not compatible. __init(__str.data() + __pos, __len); } - - std::__debug_db_insert_c(this); - if (__is_long()) - std::__debug_db_swap(this, &__str); } #endif - template <class = __enable_if_t<__is_allocator<_Allocator>::value, nullptr_t> > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c, const _Allocator& __a); + template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(size_type __n, _CharT __c, const _Allocator& __a) + : __r_(__default_init_tag(), __a) { + __init(__n, __c); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 - basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Allocator& __a = _Allocator()); + basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Allocator& __a = _Allocator()) + : __r_(__default_init_tag(), __a) { + size_type __str_sz = __str.size(); + if (__pos > __str_sz) + __throw_out_of_range(); + __init(__str.data() + __pos, std::min(__n, __str_sz - __pos)); + } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a = _Allocator()) @@ -954,65 +1018,91 @@ public: if (__pos > __str_sz) __throw_out_of_range(); __init(__str.data() + __pos, __str_sz - __pos); - std::__debug_db_insert_c(this); } template <class _Tp, - class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && - !__is_same_uncvref<_Tp, basic_string>::value> > + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string>::value, + int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type()); + basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type()) + : __r_(__default_init_tag(), __a) { + __self_view __sv0 = __t; + __self_view __sv = __sv0.substr(__pos, __n); + __init(__sv.data(), __sv.size()); + } template <class _Tp, - class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && - !__is_same_uncvref<_Tp, basic_string>::value> > - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string( - const _Tp& __t); + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string>::value, + int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t) + : __r_(__default_init_tag(), __default_init_tag()) { + __self_view __sv = __t; + __init(__sv.data(), __sv.size()); + } template <class _Tp, - class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && - !__is_same_uncvref<_Tp, basic_string>::value> > + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string>::value, + int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string( - const _Tp& __t, const allocator_type& __a); + const _Tp& __t, const allocator_type& __a) + : __r_(__default_init_tag(), __a) { + __self_view __sv = __t; + __init(__sv.data(), __sv.size()); + } - template <class _InputIterator, class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value> > + template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(_InputIterator __first, _InputIterator __last) : __r_(__default_init_tag(), __default_init_tag()) { __init(__first, __last); - std::__debug_db_insert_c(this); } - template <class _InputIterator, class = __enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value> > + template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : __r_(__default_init_tag(), __a) { __init(__first, __last); - std::__debug_db_insert_c(this); } +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_CharT> _Range> + _LIBCPP_HIDE_FROM_ABI constexpr + basic_string(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type()) + : __r_(__default_init_tag(), __a) { + if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + __init_with_size(ranges::begin(__range), ranges::end(__range), ranges::distance(__range)); + } else { + __init_with_sentinel(ranges::begin(__range), ranges::end(__range)); + } + } +#endif + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il) : __r_(__default_init_tag(), __default_init_tag()) { __init(__il.begin(), __il.end()); - std::__debug_db_insert_c(this); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(initializer_list<_CharT> __il, const _Allocator& __a) : __r_(__default_init_tag(), __a) { __init(__il.begin(), __il.end()); - std::__debug_db_insert_c(this); } #endif // _LIBCPP_CXX03_LANG - inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string(); + inline _LIBCPP_CONSTEXPR_SINCE_CXX20 ~basic_string() { + if (__is_long()) + __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); + } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const basic_string& __str); - template <class _Tp, class = __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && - !__is_same_uncvref<_Tp, basic_string>::value> > + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const _Tp& __t) { __self_view __sv = __t; return assign(__sv); @@ -1030,7 +1120,7 @@ public: #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(const value_type* __s) {return assign(__s);} -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 basic_string& operator=(nullptr_t) = delete; #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator=(value_type __c); @@ -1097,7 +1187,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 void reserve(size_type __requested_capacity); -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _Op> _LIBCPP_HIDE_FROM_ABI constexpr void resize_and_overwrite(size_type __n, _Op __op) { @@ -1116,12 +1206,12 @@ public: bool empty() const _NOEXCEPT {return size() == 0;} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __pos) const _NOEXCEPT { - _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds"); return *(data() + __pos); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __pos) _NOEXCEPT { - _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds"); return *(__get_pointer() + __pos); } @@ -1132,14 +1222,11 @@ public: return append(__str); } - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value - && !__is_same_uncvref<_Tp, basic_string >::value, - basic_string& - > + template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string >::value, + int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const _Tp& __t) { __self_view __sv = __t; return append(__sv); } @@ -1162,25 +1249,27 @@ public: return append(__str.data(), __str.size()); } - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value - && !__is_same_uncvref<_Tp, basic_string>::value, - basic_string& - > - append(const _Tp& __t) { __self_view __sv = __t; return append(__sv.data(), __sv.size()); } + template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string>::value, + int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + append(const _Tp& __t) { + __self_view __sv = __t; + return append(__sv.data(), __sv.size()); + } + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const basic_string& __str, size_type __pos, size_type __n=npos); - template <class _Tp> + template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string>::value, + int> = 0> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value - && !__is_same_uncvref<_Tp, basic_string>::value, - basic_string& - > - append(const _Tp& __t, size_type __pos, size_type __n=npos); + + basic_string& + append(const _Tp& __t, size_type __pos, size_type __n = npos); + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(size_type __n, value_type __c); @@ -1188,29 +1277,27 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __append_default_init(size_type __n); - template<class _InputIterator> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - __enable_if_t - < - __is_exactly_cpp17_input_iterator<_InputIterator>::value, - basic_string& - > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(_InputIterator __first, _InputIterator __last) { - const basic_string __temp(__first, __last, __alloc()); - append(__temp.data(), __temp.size()); - return *this; + const basic_string __temp(__first, __last, __alloc()); + append(__temp.data(), __temp.size()); + return *this; } - template<class _ForwardIterator> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - __enable_if_t - < - __is_cpp17_forward_iterator<_ForwardIterator>::value, - basic_string& - > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + + template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(_ForwardIterator __first, _ForwardIterator __last); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_CharT> _Range> + _LIBCPP_HIDE_FROM_ABI + constexpr basic_string& append_range(_Range&& __range) { + insert_range(end(), std::forward<_Range>(__range)); + return *this; + } +#endif + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(initializer_list<value_type> __il) {return append(__il.begin(), __il.size());} @@ -1220,33 +1307,32 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back(); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() _NOEXCEPT { - _LIBCPP_ASSERT(!empty(), "string::front(): string is empty"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty"); return *__get_pointer(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const _NOEXCEPT { - _LIBCPP_ASSERT(!empty(), "string::front(): string is empty"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty"); return *data(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() _NOEXCEPT { - _LIBCPP_ASSERT(!empty(), "string::back(): string is empty"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty"); return *(__get_pointer() + size() - 1); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const _NOEXCEPT { - _LIBCPP_ASSERT(!empty(), "string::back(): string is empty"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty"); return *(data() + size() - 1); } - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - basic_string& - > - assign(const _Tp & __t) { __self_view __sv = __t; return assign(__sv.data(), __sv.size()); } + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + assign(const _Tp& __t) { + __self_view __sv = __t; + return assign(__sv.data(), __sv.size()); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const basic_string& __str) { return *this = __str; } #ifndef _LIBCPP_CXX03_LANG @@ -1256,34 +1342,42 @@ public: {*this = std::move(__str); return *this;} #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const basic_string& __str, size_type __pos, size_type __n=npos); - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value - && !__is_same_uncvref<_Tp, basic_string>::value, - basic_string& - > - assign(const _Tp & __t, size_type __pos, size_type __n=npos); + + template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string>::value, + int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + assign(const _Tp& __t, size_type __pos, size_type __n = npos); + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(size_type __n, value_type __c); - template<class _InputIterator> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __is_exactly_cpp17_input_iterator<_InputIterator>::value, - basic_string& - > - assign(_InputIterator __first, _InputIterator __last); - template<class _ForwardIterator> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __is_cpp17_forward_iterator<_ForwardIterator>::value, - basic_string& - > - assign(_ForwardIterator __first, _ForwardIterator __last); + template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + assign(_InputIterator __first, _InputIterator __last); + + template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + assign(_ForwardIterator __first, _ForwardIterator __last); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_CharT> _Range> + _LIBCPP_HIDE_FROM_ABI + constexpr basic_string& assign_range(_Range&& __range) { + if constexpr (__string_is_trivial_iterator<ranges::iterator_t<_Range>>::value && + (ranges::forward_range<_Range> || ranges::sized_range<_Range>)) { + size_type __n = static_cast<size_type>(ranges::distance(__range)); + __assign_trivial(ranges::begin(__range), ranges::end(__range), __n); + + } else { + __assign_with_sentinel(ranges::begin(__range), ranges::end(__range)); + } + + return *this; + } +#endif + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(initializer_list<value_type> __il) {return assign(__il.begin(), __il.size());} @@ -1294,56 +1388,57 @@ public: return insert(__pos1, __str.data(), __str.size()); } - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - basic_string& - > - insert(size_type __pos1, const _Tp& __t) - { __self_view __sv = __t; return insert(__pos1, __sv.data(), __sv.size()); } + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + insert(size_type __pos1, const _Tp& __t) { + __self_view __sv = __t; + return insert(__pos1, __sv.data(), __sv.size()); + } - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, - basic_string& - > - insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n=npos); - _LIBCPP_CONSTEXPR_SINCE_CXX20 - basic_string& insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n=npos); - _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s, size_type __n); - _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s); - _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, size_type __n, value_type __c); - _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, value_type __c); + template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string>::value, + int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n = npos); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n = npos); + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s, size_type __n); + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, const value_type* __s); + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos, size_type __n, value_type __c); + _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, value_type __c); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_CharT> _Range> + _LIBCPP_HIDE_FROM_ABI + constexpr iterator insert_range(const_iterator __position, _Range&& __range) { + if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + return __insert_with_size(__position, ranges::begin(__range), ranges::end(__range), __n); + + } else { + basic_string __temp(from_range, std::forward<_Range>(__range), __alloc()); + return insert(__position, __temp.data(), __temp.data() + __temp.size()); + } + } +#endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, size_type __n, value_type __c) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, - "string::insert(iterator, n, value) called with an iterator not referring to this string"); difference_type __p = __pos - begin(); insert(static_cast<size_type>(__p), __n, __c); return begin() + __p; } - template<class _InputIterator> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __is_exactly_cpp17_input_iterator<_InputIterator>::value, - iterator - > - insert(const_iterator __pos, _InputIterator __first, _InputIterator __last); - template<class _ForwardIterator> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __is_cpp17_forward_iterator<_ForwardIterator>::value, - iterator - > - insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last); + template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator + insert(const_iterator __pos, _InputIterator __first, _InputIterator __last); + + template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator + insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last); + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __pos, initializer_list<value_type> __il) @@ -1361,28 +1456,27 @@ public: return replace(__pos1, __n1, __str.data(), __str.size()); } - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - basic_string& - > - replace(size_type __pos1, size_type __n1, const _Tp& __t) { __self_view __sv = __t; return replace(__pos1, __n1, __sv.data(), __sv.size()); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 - basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2=npos); - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, - basic_string& - > - replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2=npos); - _LIBCPP_CONSTEXPR_SINCE_CXX20 - basic_string& replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2); - _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s); - _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c); + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + replace(size_type __pos1, size_type __n1, const _Tp& __t) { + __self_view __sv = __t; + return replace(__pos1, __n1, __sv.data(), __sv.size()); + } + + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos); + + template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string>::value, + int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos); + + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2); + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s); + _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const basic_string& __str) { @@ -1390,14 +1484,12 @@ public: static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __str.data(), __str.size()); } - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - basic_string& - > - replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) { __self_view __sv = __t; return replace(__i1 - begin(), __i2 - __i1, __sv); } + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) { + __self_view __sv = __t; + return replace(__i1 - begin(), __i2 - __i1, __sv); + } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n) { @@ -1414,14 +1506,19 @@ public: return replace(static_cast<size_type>(__i1 - begin()), static_cast<size_type>(__i2 - __i1), __n, __c); } - template<class _InputIterator> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __is_cpp17_input_iterator<_InputIterator>::value, - basic_string& - > - replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2); + template <class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_CharT> _Range> + _LIBCPP_HIDE_FROM_ABI + constexpr basic_string& replace_with_range(const_iterator __i1, const_iterator __i2, _Range&& __range) { + basic_string __temp(from_range, std::forward<_Range>(__range), __alloc()); + return replace(__i1, __i2, __temp); + } +#endif + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, initializer_list<value_type> __il) @@ -1460,7 +1557,7 @@ public: const value_type* c_str() const _NOEXCEPT {return data();} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const value_type* data() const _NOEXCEPT {return std::__to_address(__get_pointer());} -#if _LIBCPP_STD_VER > 14 || defined(_LIBCPP_BUILDING_LIBRARY) +#if _LIBCPP_STD_VER >= 17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 value_type* data() _NOEXCEPT {return std::__to_address(__get_pointer());} #endif @@ -1471,16 +1568,11 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - size_type - > - find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; - _LIBCPP_CONSTEXPR_SINCE_CXX20 - size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; + + _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(value_type __c, size_type __pos = 0) const _NOEXCEPT; @@ -1488,14 +1580,10 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - size_type - > - rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; + _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -1505,14 +1593,10 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - size_type - > - find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; + _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -1523,14 +1607,10 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - size_type - > - find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; + _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -1541,14 +1621,10 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - size_type - > - find_first_not_of(const _Tp &__t, size_type __pos = 0) const _NOEXCEPT; + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + find_first_not_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT; + _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -1559,14 +1635,10 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - size_type - > - find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT; + _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -1577,23 +1649,13 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const basic_string& __str) const _NOEXCEPT; - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - int - > - compare(const _Tp &__t) const _NOEXCEPT; + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int + compare(const _Tp& __t) const _NOEXCEPT; - template <class _Tp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - int - > - compare(size_type __pos1, size_type __n1, const _Tp& __t) const; + template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> = 0> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int + compare(size_type __pos1, size_type __n1, const _Tp& __t) const; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const basic_string& __str) const; @@ -1601,20 +1663,19 @@ public: int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos) const; - template <class _Tp> - inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, - int - > - compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2=npos) const; + template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string>::value, + int> = 0> + inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int + compare(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos) const; + _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const value_type* __s) const _NOEXCEPT; _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const value_type* __s) const; _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 constexpr _LIBCPP_HIDE_FROM_ABI bool starts_with(__self_view __sv) const noexcept { return __self_view(data(), size()).starts_with(__sv); } @@ -1640,7 +1701,7 @@ public: { return ends_with(__self_view(__s)); } #endif -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 constexpr _LIBCPP_HIDE_FROM_ABI bool contains(__self_view __sv) const noexcept { return __self_view(data(), size()).contains(__sv); } @@ -1658,15 +1719,6 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __clear_and_shrink() _NOEXCEPT; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - bool __dereferenceable(const const_iterator* __i) const; - bool __decrementable(const const_iterator* __i) const; - bool __addable(const const_iterator* __i, ptrdiff_t __n) const; - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - private: template<class _Alloc> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -1683,7 +1735,7 @@ private: } static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __begin_lifetime(pointer __begin, size_type __n) { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 if (__libcpp_is_constant_evaluated()) { for (size_type __i = 0; __i != __n; ++__i) std::construct_at(std::addressof(__begin[__i])); @@ -1691,7 +1743,7 @@ private: #else (void)__begin; (void)__n; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __default_init() { @@ -1716,9 +1768,17 @@ private: return !__libcpp_is_constant_evaluated() && (__sz < __min_cap); } - template <class _ForwardIterator> + template <class _Iterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __assign_trivial(_Iterator __first, _Sentinel __last, size_type __n); + + template <class _Iterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __assign_with_sentinel(_Iterator __first, _Sentinel __last); + + template <class _ForwardIterator, class _Sentinel> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 - iterator __insert_from_safe_copy(size_type __n, size_type __ip, _ForwardIterator __first, _ForwardIterator __last) { + iterator __insert_from_safe_copy(size_type __n, size_type __ip, _ForwardIterator __first, _Sentinel __last) { size_type __sz = size(); size_type __cap = capacity(); value_type* __p; @@ -1731,7 +1791,7 @@ private: } else { - __grow_by(__cap, __sz + __n - __cap, __sz, __ip, 0, __n); + __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __ip, 0, __n); __p = std::__to_address(__get_long_pointer()); } __sz += __n; @@ -1743,19 +1803,25 @@ private: return begin() + __ip; } + template<class _Iterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 + iterator __insert_with_size(const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 allocator_type& __alloc() _NOEXCEPT { return __r_.second(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const allocator_type& __alloc() const _NOEXCEPT { return __r_.second(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_short_size(size_type __s) _NOEXCEPT { - _LIBCPP_ASSERT(__s < __min_cap, "__s should never be greater than or equal to the short string capacity"); + _LIBCPP_ASSERT_INTERNAL( + __s < __min_cap, "__s should never be greater than or equal to the short string capacity"); __r_.first().__s.__size_ = __s; __r_.first().__s.__is_long_ = false; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __get_short_size() const _NOEXCEPT { - _LIBCPP_ASSERT(!__r_.first().__s.__is_long_, "String has to be short when trying to get the short size"); + _LIBCPP_ASSERT_INTERNAL( + !__r_.first().__s.__is_long_, "String has to be short when trying to get the short size"); return __r_.first().__s.__size_; } @@ -1839,25 +1905,29 @@ private: // to only inline the fast path code directly in the ctor. _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init_copy_ctor_external(const value_type* __s, size_type __sz); - template <class _InputIterator> - inline _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __is_exactly_cpp17_input_iterator<_InputIterator>::value - > - __init(_InputIterator __first, _InputIterator __last); + template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> = 0> + inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(_InputIterator __first, _InputIterator __last); - template <class _ForwardIterator> - inline _LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __is_cpp17_forward_iterator<_ForwardIterator>::value - > - __init(_ForwardIterator __first, _ForwardIterator __last); + template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0> + inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void __init(_ForwardIterator __first, _ForwardIterator __last); + + template <class _InputIterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + void __init_with_sentinel(_InputIterator __first, _Sentinel __last); + template <class _InputIterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + void __init_with_size(_InputIterator __first, _Sentinel __last, size_type __sz); _LIBCPP_CONSTEXPR_SINCE_CXX20 +#if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1 + _LIBCPP_HIDE_FROM_ABI +#endif + _LIBCPP_DEPRECATED_("use __grow_by_without_replace") void __grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add = 0); + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __grow_by_without_replace(size_type __old_cap, size_type __delta_cap, size_type __old_sz, + size_type __n_copy, size_type __n_del, size_type __n_add = 0); _LIBCPP_CONSTEXPR_SINCE_CXX20 void __grow_by_and_replace(size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, @@ -1918,7 +1988,7 @@ private: _NOEXCEPT_(__alloc_traits::is_always_equal::value); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign(basic_string& __str, true_type) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _NOEXCEPT; #else _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value); @@ -1962,21 +2032,13 @@ private: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __null_terminate_at(value_type* __p, size_type __newsz) { __set_size(__newsz); - __invalidate_iterators_past(__newsz); traits_type::assign(__p[__newsz], value_type()); return *this; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __invalidate_iterators_past(size_type); - - template<class _Tp> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - bool __addr_in_range(_Tp&& __t) const { - // assume that the ranges overlap, because we can't check during constant evaluation - if (__libcpp_is_constant_evaluated()) - return true; - const volatile void *__p = std::addressof(__t); - return data() <= __p && __p <= data() + size(); + template <class _Tp> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __addr_in_range(const _Tp& __v) const { + return std::__is_pointer_in_range(data(), data() + size() + 1, std::addressof(__v)); } _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI @@ -2017,7 +2079,7 @@ private: template<class _InputIterator, class _CharT = __iter_value_type<_InputIterator>, class _Allocator = allocator<_CharT>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Allocator>::value> > basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator()) @@ -2041,35 +2103,14 @@ basic_string(basic_string_view<_CharT, _Traits>, _Sz, _Sz, const _Allocator& = _ -> basic_string<_CharT, _Traits, _Allocator>; #endif -template <class _CharT, class _Traits, class _Allocator> -inline _LIBCPP_CONSTEXPR_SINCE_CXX20 -void -basic_string<_CharT, _Traits, _Allocator>::__invalidate_iterators_past(size_type __pos) -{ -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - if (!__libcpp_is_constant_evaluated()) { - __c_node* __c = __get_db()->__find_c_and_lock(this); - if (__c) - { - const_pointer __new_last = __get_pointer() + __pos; - for (__i_node** __p = __c->end_; __p != __c->beg_; ) - { - --__p; - const_iterator* __i = static_cast<const_iterator*>((*__p)->__i_); - if (__i->base() > __new_last) - { - (*__p)->__c_ = nullptr; - if (--__c->end_ != __p) - std::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); - } - } -#else - (void)__pos; -#endif // _LIBCPP_ENABLE_DEBUG_MODE -} +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, + class _Allocator = allocator<ranges::range_value_t<_Range>>, + class = enable_if_t<__is_allocator<_Allocator>::value> + > +basic_string(from_range_t, _Range&&, _Allocator = _Allocator()) + -> basic_string<ranges::range_value_t<_Range>, char_traits<ranges::range_value_t<_Range>>, _Allocator>; +#endif template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -2129,44 +2170,6 @@ basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_ty } template <class _CharT, class _Traits, class _Allocator> -template <class> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const _Allocator& __a) - : __r_(__default_init_tag(), __a) -{ - _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*, allocator) detected nullptr"); - __init(__s, traits_type::length(__s)); - std::__debug_db_insert_c(this); -} - -template <class _CharT, class _Traits, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str) - : __r_(__default_init_tag(), __alloc_traits::select_on_container_copy_construction(__str.__alloc())) -{ - if (!__str.__is_long()) - __r_.first() = __str.__r_.first(); - else - __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), - __str.__get_long_size()); - std::__debug_db_insert_c(this); -} - -template <class _CharT, class _Traits, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -basic_string<_CharT, _Traits, _Allocator>::basic_string( - const basic_string& __str, const allocator_type& __a) - : __r_(__default_init_tag(), __a) -{ - if (!__str.__is_long()) - __r_.first() = __str.__r_.first(); - else - __init_copy_ctor_external(std::__to_address(__str.__get_long_pointer()), - __str.__get_long_size()); - std::__debug_db_insert_c(this); -} - -template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external( const value_type* __s, size_type __sz) { @@ -2220,81 +2223,26 @@ basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c) } template <class _CharT, class _Traits, class _Allocator> -template <class> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c, const _Allocator& __a) - : __r_(__default_init_tag(), __a) -{ - __init(__n, __c); - std::__debug_db_insert_c(this); -} - -template <class _CharT, class _Traits, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __str, - size_type __pos, size_type __n, - const _Allocator& __a) - : __r_(__default_init_tag(), __a) -{ - size_type __str_sz = __str.size(); - if (__pos > __str_sz) - __throw_out_of_range(); - __init(__str.data() + __pos, std::min(__n, __str_sz - __pos)); - std::__debug_db_insert_c(this); -} - -template <class _CharT, class _Traits, class _Allocator> -template <class _Tp, class> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -basic_string<_CharT, _Traits, _Allocator>::basic_string( - const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a) - : __r_(__default_init_tag(), __a) -{ - __self_view __sv0 = __t; - __self_view __sv = __sv0.substr(__pos, __n); - __init(__sv.data(), __sv.size()); - std::__debug_db_insert_c(this); -} - -template <class _CharT, class _Traits, class _Allocator> -template <class _Tp, class> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -basic_string<_CharT, _Traits, _Allocator>::basic_string(const _Tp & __t) - : __r_(__default_init_tag(), __default_init_tag()) -{ - __self_view __sv = __t; - __init(__sv.data(), __sv.size()); - std::__debug_db_insert_c(this); -} - -template <class _CharT, class _Traits, class _Allocator> -template <class _Tp, class> +template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 -basic_string<_CharT, _Traits, _Allocator>::basic_string(const _Tp & __t, const _Allocator& __a) - : __r_(__default_init_tag(), __a) +void basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last) { - __self_view __sv = __t; - __init(__sv.data(), __sv.size()); - std::__debug_db_insert_c(this); + __init_with_sentinel(std::move(__first), std::move(__last)); } template <class _CharT, class _Traits, class _Allocator> -template <class _InputIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __is_exactly_cpp17_input_iterator<_InputIterator>::value -> -basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _InputIterator __last) -{ +template <class _InputIterator, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void basic_string<_CharT, _Traits, _Allocator>::__init_with_sentinel(_InputIterator __first, _Sentinel __last) { __default_init(); -#ifndef _LIBCPP_NO_EXCEPTIONS + +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __first != __last; ++__first) push_back(*__first); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -2302,28 +2250,35 @@ basic_string<_CharT, _Traits, _Allocator>::__init(_InputIterator __first, _Input __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template <class _CharT, class _Traits, class _Allocator> -template <class _ForwardIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __is_cpp17_forward_iterator<_ForwardIterator>::value -> +template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _ForwardIterator __last) { + size_type __sz = static_cast<size_type>(std::distance(__first, __last)); + __init_with_size(__first, __last, __sz); +} + +template <class _CharT, class _Traits, class _Allocator> +template <class _InputIterator, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void basic_string<_CharT, _Traits, _Allocator>::__init_with_size( + _InputIterator __first, _Sentinel __last, size_type __sz) { if (__libcpp_is_constant_evaluated()) __r_.first() = __rep(); - size_type __sz = static_cast<size_type>(std::distance(__first, __last)); + if (__sz > max_size()) __throw_length_error(); + pointer __p; if (__fits_in_sso(__sz)) { __set_short_size(__sz); __p = __get_short_pointer(); + } else { @@ -2335,14 +2290,14 @@ basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _For __set_long_size(__sz); } -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (; __first != __last; ++__first, (void) ++__p) traits_type::assign(*__p, *__first); traits_type::assign(*__p, value_type()); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { @@ -2350,16 +2305,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(_ForwardIterator __first, _For __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -template <class _CharT, class _Traits, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -basic_string<_CharT, _Traits, _Allocator>::~basic_string() -{ - std::__debug_db_erase_c(this); - if (__is_long()) - __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } template <class _CharT, class _Traits, class _Allocator> @@ -2379,7 +2325,6 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); - std::__debug_db_invalidate_all(this); if (__n_copy != 0) traits_type::copy(std::__to_address(__p), std::__to_address(__old_p), __n_copy); @@ -2398,9 +2343,16 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace traits_type::assign(__p[__old_sz], value_type()); } +// __grow_by is deprecated because it does not set the size. It may not update the size when the size is changed, and it +// may also not set the size at all when the string was short initially. This leads to unpredictable size value. It is +// not removed or changed to avoid breaking the ABI. template <class _CharT, class _Traits, class _Allocator> void _LIBCPP_CONSTEXPR_SINCE_CXX20 +#if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1 + _LIBCPP_HIDE_FROM_ABI +#endif + _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_type __delta_cap, size_type __old_sz, size_type __n_copy, size_type __n_del, size_type __n_add) { @@ -2414,7 +2366,6 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_t auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1); pointer __p = __allocation.ptr; __begin_lifetime(__p, __allocation.count); - std::__debug_db_invalidate_all(this); if (__n_copy != 0) traits_type::copy(std::__to_address(__p), std::__to_address(__old_p), __n_copy); @@ -2429,6 +2380,21 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_t __set_long_cap(__allocation.count); } +template <class _CharT, class _Traits, class _Allocator> +void _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI +basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace( + size_type __old_cap, + size_type __delta_cap, + size_type __old_sz, + size_type __n_copy, + size_type __n_del, + size_type __n_add) { + _LIBCPP_SUPPRESS_DEPRECATED_PUSH + __grow_by(__old_cap, __delta_cap, __old_sz, __n_copy, __n_del, __n_add); + _LIBCPP_SUPPRESS_DEPRECATED_POP + __set_long_size(__old_sz - __n_del + __n_add); +} + // assign template <class _CharT, class _Traits, class _Allocator> @@ -2443,7 +2409,6 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias( __is_short ? __set_short_size(__n) : __set_long_size(__n); traits_type::copy(std::__to_address(__p), __s, __n); traits_type::assign(__p[__n], value_type()); - __invalidate_iterators_past(__n); } else { size_type __sz = __is_short ? __get_short_size() : __get_long_size(); __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s); @@ -2473,7 +2438,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n) { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::assign received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string::assign received nullptr"); return (__builtin_constant_p(__n) && __fits_in_sso(__n)) ? __assign_short(__s, __n) : __assign_external(__s, __n); @@ -2488,7 +2453,7 @@ basic_string<_CharT, _Traits, _Allocator>::assign(size_type __n, value_type __c) if (__cap < __n) { size_type __sz = size(); - __grow_by(__cap, __n - __cap, __sz, 0, __sz); + __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); } value_type* __p = std::__to_address(__get_pointer()); traits_type::assign(__p, __n, __c); @@ -2513,7 +2478,6 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(value_type __c) } traits_type::assign(*__p, __c); traits_type::assign(*++__p, value_type()); - __invalidate_iterators_past(1); return *this; } @@ -2522,7 +2486,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) { - if (this != &__str) { + if (this != std::addressof(__str)) { __copy_assign_alloc(__str); if (!__is_long()) { if (!__str.__is_long()) { @@ -2555,7 +2519,7 @@ template <class _CharT, class _Traits, class _Allocator> inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _NOEXCEPT #else _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) @@ -2584,55 +2548,62 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr #endif template <class _CharT, class _Traits, class _Allocator> -template<class _InputIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __is_exactly_cpp17_input_iterator<_InputIterator>::value, - basic_string<_CharT, _Traits, _Allocator>& -> +template<class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { - const basic_string __temp(__first, __last, __alloc()); - assign(__temp.data(), __temp.size()); - return *this; + __assign_with_sentinel(__first, __last); + return *this; } template <class _CharT, class _Traits, class _Allocator> -template<class _ForwardIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __is_cpp17_forward_iterator<_ForwardIterator>::value, - basic_string<_CharT, _Traits, _Allocator>& -> +template <class _InputIterator, class _Sentinel> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 +void +basic_string<_CharT, _Traits, _Allocator>::__assign_with_sentinel(_InputIterator __first, _Sentinel __last) { + const basic_string __temp(__init_with_sentinel_tag(), std::move(__first), std::move(__last), __alloc()); + assign(__temp.data(), __temp.size()); +} + +template <class _CharT, class _Traits, class _Allocator> +template<class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) { - size_type __cap = capacity(); - size_type __n = __string_is_trivial_iterator<_ForwardIterator>::value ? - static_cast<size_type>(std::distance(__first, __last)) : 0; + if (__string_is_trivial_iterator<_ForwardIterator>::value) { + size_type __n = static_cast<size_type>(std::distance(__first, __last)); + __assign_trivial(__first, __last, __n); + } else { + __assign_with_sentinel(__first, __last); + } - if (__string_is_trivial_iterator<_ForwardIterator>::value && - (__cap >= __n || !__addr_in_range(*__first))) - { - if (__cap < __n) - { - size_type __sz = size(); - __grow_by(__cap, __n - __cap, __sz, 0, __sz); - } - pointer __p = __get_pointer(); - for (; __first != __last; ++__p, (void) ++__first) - traits_type::assign(*__p, *__first); - traits_type::assign(*__p, value_type()); - __set_size(__n); - __invalidate_iterators_past(__n); - } - else - { - const basic_string __temp(__first, __last, __alloc()); - assign(__temp.data(), __temp.size()); + return *this; +} + +template <class _CharT, class _Traits, class _Allocator> +template <class _Iterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI +void +basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _Sentinel __last, size_type __n) { + _LIBCPP_ASSERT_INTERNAL( + __string_is_trivial_iterator<_Iterator>::value, "The iterator type given to `__assign_trivial` must be trivial"); + + size_type __cap = capacity(); + if (__cap < __n) { + // Unlike `append` functions, if the input range points into the string itself, there is no case that the input + // range could get invalidated by reallocation: + // 1. If the input range is a subset of the string itself, its size cannot exceed the capacity of the string, + // thus no reallocation would happen. + // 2. In the exotic case where the input range is the byte representation of the string itself, the string + // object itself stays valid even if reallocation happens. + size_type __sz = size(); + __grow_by_without_replace(__cap, __n - __cap, __sz, 0, __sz); } - return *this; + pointer __p = __get_pointer(); + for (; __first != __last; ++__p, (void) ++__first) + traits_type::assign(*__p, *__first); + traits_type::assign(*__p, value_type()); + __set_size(__n); } template <class _CharT, class _Traits, class _Allocator> @@ -2647,16 +2618,12 @@ basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, siz } template <class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value - && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, - basic_string<_CharT, _Traits, _Allocator>& -> -basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp & __t, size_type __pos, size_type __n) -{ +template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, + int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp& __t, size_type __pos, size_type __n) { __self_view __sv = __t; size_type __sz = __sv.size(); if (__pos > __sz) @@ -2664,7 +2631,6 @@ basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp & __t, size_type __p return assign(__sv.data() + __pos, std::min(__n, __sz - __pos)); } - template <class _CharT, class _Traits, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& @@ -2677,7 +2643,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s) { - _LIBCPP_ASSERT(__s != nullptr, "string::assign received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::assign received nullptr"); return __builtin_constant_p(*__s) ? (__fits_in_sso(traits_type::length(__s)) ? __assign_short(__s, traits_type::length(__s)) @@ -2691,7 +2657,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_type __n) { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::append received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string::append received nullptr"); size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz >= __n) @@ -2720,7 +2686,7 @@ basic_string<_CharT, _Traits, _Allocator>::append(size_type __n, value_type __c) size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz < __n) - __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); + __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); pointer __p = __get_pointer(); traits_type::assign(std::__to_address(__p) + __sz, __n, __c); __sz += __n; @@ -2739,7 +2705,7 @@ basic_string<_CharT, _Traits, _Allocator>::__append_default_init(size_type __n) size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz < __n) - __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); + __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); pointer __p = __get_pointer(); __sz += __n; __set_size(__sz); @@ -2767,7 +2733,7 @@ basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c) } if (__sz == __cap) { - __grow_by(__cap, 1, __sz, __sz, 0); + __grow_by_without_replace(__cap, 1, __sz, __sz, 0); __is_short = false; // the string is always long after __grow_by } pointer __p = __get_pointer(); @@ -2786,13 +2752,8 @@ basic_string<_CharT, _Traits, _Allocator>::push_back(value_type __c) } template <class _CharT, class _Traits, class _Allocator> -template<class _ForwardIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __is_cpp17_forward_iterator<_ForwardIterator>::value, - basic_string<_CharT, _Traits, _Allocator>& -> +template<class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append( _ForwardIterator __first, _ForwardIterator __last) { @@ -2805,7 +2766,7 @@ basic_string<_CharT, _Traits, _Allocator>::append( !__addr_in_range(*__first)) { if (__cap - __sz < __n) - __grow_by(__cap, __sz + __n - __cap, __sz, __sz, 0); + __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); pointer __p = __get_pointer() + __sz; for (; __first != __last; ++__p, (void) ++__first) traits_type::assign(*__p, *__first); @@ -2833,15 +2794,12 @@ basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, siz } template <class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 - __enable_if_t - < - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, - basic_string<_CharT, _Traits, _Allocator>& - > -basic_string<_CharT, _Traits, _Allocator>::append(const _Tp & __t, size_type __pos, size_type __n) -{ +template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, + int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::append(const _Tp& __t, size_type __pos, size_type __n) { __self_view __sv = __t; size_type __sz = __sv.size(); if (__pos > __sz) @@ -2854,7 +2812,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s) { - _LIBCPP_ASSERT(__s != nullptr, "string::append received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::append received nullptr"); return append(__s, traits_type::length(__s)); } @@ -2865,7 +2823,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s, size_type __n) { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::insert received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string::insert received nullptr"); size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); @@ -2921,7 +2879,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n } else { - __grow_by(__cap, __sz + __n - __cap, __sz, __pos, 0, __n); + __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n); __p = std::__to_address(__get_long_pointer()); } traits_type::assign(__p + __pos, __n, __c); @@ -2933,47 +2891,40 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n } template <class _CharT, class _Traits, class _Allocator> -template<class _InputIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __is_exactly_cpp17_input_iterator<_InputIterator>::value, - typename basic_string<_CharT, _Traits, _Allocator>::iterator -> +template<class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, - "string::insert(iterator, range) called with an iterator not" - " referring to this string"); const basic_string __temp(__first, __last, __alloc()); return insert(__pos, __temp.data(), __temp.data() + __temp.size()); } template <class _CharT, class _Traits, class _Allocator> -template<class _ForwardIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __is_cpp17_forward_iterator<_ForwardIterator>::value, - typename basic_string<_CharT, _Traits, _Allocator>::iterator -> +template<class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, - "string::insert(iterator, range) called with an iterator not referring to this string"); + auto __n = static_cast<size_type>(std::distance(__first, __last)); + return __insert_with_size(__pos, __first, __last, __n); +} +template <class _CharT, class _Traits, class _Allocator> +template<class _Iterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 +typename basic_string<_CharT, _Traits, _Allocator>::iterator +basic_string<_CharT, _Traits, _Allocator>::__insert_with_size( + const_iterator __pos, _Iterator __first, _Sentinel __last, size_type __n) { size_type __ip = static_cast<size_type>(__pos - begin()); - size_type __n = static_cast<size_type>(std::distance(__first, __last)); if (__n == 0) return begin() + __ip; - if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first)) + if (__string_is_trivial_iterator<_Iterator>::value && !__addr_in_range(*__first)) { return __insert_from_safe_copy(__n, __ip, __first, __last); } else { - const basic_string __temp(__first, __last, __alloc()); + const basic_string __temp(__init_with_sentinel_tag(), __first, __last, __alloc()); return __insert_from_safe_copy(__n, __ip, __temp.begin(), __temp.end()); } } @@ -2991,16 +2942,12 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const basic_ } template <class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, - basic_string<_CharT, _Traits, _Allocator>& -> -basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t, - size_type __pos2, size_type __n) -{ +template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, + int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n) { __self_view __sv = __t; size_type __str_sz = __sv.size(); if (__pos2 > __str_sz) @@ -3013,7 +2960,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s) { - _LIBCPP_ASSERT(__s != nullptr, "string::insert received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::insert received nullptr"); return insert(__pos, __s, traits_type::length(__s)); } @@ -3022,17 +2969,13 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, value_type __c) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, - "string::insert(iterator, character) called with an iterator not" - " referring to this string"); - size_type __ip = static_cast<size_type>(__pos - begin()); size_type __sz = size(); size_type __cap = capacity(); value_type* __p; if (__cap == __sz) { - __grow_by(__cap, 1, __sz, __ip, 0, 1); + __grow_by_without_replace(__cap, 1, __sz, __ip, 0, 1); __p = std::__to_address(__get_long_pointer()); } else @@ -3056,7 +2999,7 @@ basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK { - _LIBCPP_ASSERT(__n2 == 0 || __s != nullptr, "string::replace received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n2 == 0 || __s != nullptr, "string::replace received nullptr"); size_type __sz = size(); if (__pos > __sz) __throw_out_of_range(); @@ -3064,10 +3007,6 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __ size_type __cap = capacity(); if (__cap - __sz + __n1 >= __n2) { - if (__libcpp_is_constant_evaluated()) { - __grow_by_and_replace(__cap, 0, __sz, __pos, __n1, __n2, __s); - return *this; - } value_type* __p = std::__to_address(__get_pointer()); if (__n1 != __n2) { @@ -3080,7 +3019,7 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __ traits_type::move(__p + __pos + __n2, __p + __pos + __n1, __n_move); return __null_terminate_at(__p, __sz + (__n2 - __n1)); } - if (__p + __pos < __s && __s < __p + __sz) + if (std::__is_pointer_in_range(__p + __pos + 1, __p + __sz, __s)) { if (__p + __pos + __n1 <= __s) __s += __n2 - __n1; @@ -3127,7 +3066,7 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __ } else { - __grow_by(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2); + __grow_by_without_replace(__cap, __sz - __n1 + __n2 - __cap, __sz, __pos, __n1, __n2); __p = std::__to_address(__get_long_pointer()); } traits_type::assign(__p + __pos, __n2, __c); @@ -3135,13 +3074,8 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __ } template <class _CharT, class _Traits, class _Allocator> -template<class _InputIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __is_cpp17_input_iterator<_InputIterator>::value, - basic_string<_CharT, _Traits, _Allocator>& -> +template<class _InputIterator, __enable_if_t<__has_input_iterator_category<_InputIterator>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2) { @@ -3162,16 +3096,13 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type _ } template <class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, - basic_string<_CharT, _Traits, _Allocator>& -> -basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos1, size_type __n1, const _Tp& __t, - size_type __pos2, size_type __n2) -{ +template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, + int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& +basic_string<_CharT, _Traits, _Allocator>::replace( + size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) { __self_view __sv = __t; size_type __str_sz = __sv.size(); if (__pos2 > __str_sz) @@ -3184,7 +3115,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s) { - _LIBCPP_ASSERT(__s != nullptr, "string::replace received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::replace received nullptr"); return replace(__pos, __n1, __s, traits_type::length(__s)); } @@ -3230,11 +3161,8 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, - "string::erase(iterator) called with an iterator not" - " referring to this string"); - - _LIBCPP_ASSERT(__pos != end(), "string::erase(iterator) called with a non-dereferenceable iterator"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __pos != end(), "string::erase(iterator) called with a non-dereferenceable iterator"); iterator __b = begin(); size_type __r = static_cast<size_type>(__pos - __b); erase(__r, 1); @@ -3246,11 +3174,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this, - "string::erase(iterator, iterator) called with an iterator not" - " referring to this string"); - - _LIBCPP_ASSERT(__first <= __last, "string::erase(first, last) called with invalid range"); + _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "string::erase(first, last) called with invalid range"); iterator __b = begin(); size_type __r = static_cast<size_type>(__first - __b); erase(__r, static_cast<size_type>(__last - __first)); @@ -3262,7 +3186,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pop_back() { - _LIBCPP_ASSERT(!empty(), "string::pop_back(): string is already empty"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty"); __erase_to_end(size() - 1); } @@ -3271,7 +3195,6 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT { - std::__debug_db_invalidate_all(this); if (__is_long()) { traits_type::assign(*__get_long_pointer(), value_type()); @@ -3365,23 +3288,23 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target } else { - #ifndef _LIBCPP_NO_EXCEPTIONS + #ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { - #endif // _LIBCPP_NO_EXCEPTIONS + #endif // _LIBCPP_HAS_NO_EXCEPTIONS auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1); __new_data = __allocation.ptr; __target_capacity = __allocation.count - 1; - #ifndef _LIBCPP_NO_EXCEPTIONS + #ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { return; } - #else // _LIBCPP_NO_EXCEPTIONS + #else // _LIBCPP_HAS_NO_EXCEPTIONS if (__new_data == nullptr) return; - #endif // _LIBCPP_NO_EXCEPTIONS + #endif // _LIBCPP_HAS_NO_EXCEPTIONS } __begin_lifetime(__new_data, __target_capacity + 1); __now_long = true; @@ -3400,7 +3323,6 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target } else __set_short_size(__sz); - std::__debug_db_invalidate_all(this); } template <class _CharT, class _Traits, class _Allocator> @@ -3447,13 +3369,7 @@ basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str) __is_nothrow_swappable<allocator_type>::value) #endif { - if (!__is_long()) - std::__debug_db_invalidate_all(this); - if (!__str.__is_long()) - std::__debug_db_invalidate_all(&__str); - std::__debug_db_swap(this, &__str); - - _LIBCPP_ASSERT( + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value || __alloc() == __str.__alloc(), "swapping non-equal allocators"); @@ -3479,7 +3395,7 @@ basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string::find(): received nullptr"); return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3495,13 +3411,8 @@ basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str, } template<class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - typename basic_string<_CharT, _Traits, _Allocator>::size_type -> +template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const _Tp &__t, size_type __pos) const _NOEXCEPT { @@ -3516,7 +3427,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string::find(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::find(): received nullptr"); return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3540,7 +3451,7 @@ basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::rfind(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string::rfind(): received nullptr"); return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3556,13 +3467,8 @@ basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str, } template<class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - typename basic_string<_CharT, _Traits, _Allocator>::size_type -> +template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t, size_type __pos) const _NOEXCEPT { @@ -3577,7 +3483,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string::rfind(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::rfind(): received nullptr"); return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3601,7 +3507,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string::find_first_of(): received nullptr"); return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3617,13 +3523,8 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __s } template<class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - typename basic_string<_CharT, _Traits, _Allocator>::size_type -> +template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { @@ -3638,7 +3539,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string::find_first_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::find_first_of(): received nullptr"); return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3661,7 +3562,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string::find_last_of(): received nullptr"); return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3677,13 +3578,8 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __st } template<class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - typename basic_string<_CharT, _Traits, _Allocator>::size_type -> +template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { @@ -3698,7 +3594,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string::find_last_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::find_last_of(): received nullptr"); return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3721,7 +3617,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* _ size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3737,13 +3633,8 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const basic_string& } template<class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - typename basic_string<_CharT, _Traits, _Allocator>::size_type -> +template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { @@ -3758,7 +3649,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string::find_first_not_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3782,7 +3673,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __ size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -3798,13 +3689,8 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const basic_string& } template<class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - typename basic_string<_CharT, _Traits, _Allocator>::size_type -> +template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t, size_type __pos) const _NOEXCEPT { @@ -3819,7 +3705,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string::find_last_not_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -3837,13 +3723,8 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c, // compare template <class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - int -> +template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const _NOEXCEPT { __self_view __sv = __t; @@ -3876,7 +3757,7 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, const value_type* __s, size_type __n2) const { - _LIBCPP_ASSERT(__n2 == 0 || __s != nullptr, "string::compare(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n2 == 0 || __s != nullptr, "string::compare(): received nullptr"); size_type __sz = size(); if (__pos1 > __sz || __n2 == npos) __throw_out_of_range(); @@ -3893,13 +3774,8 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, } template <class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, - int -> +template <class _Tp, __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const _Tp& __t) const @@ -3919,20 +3795,12 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, } template <class _CharT, class _Traits, class _Allocator> -template <class _Tp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 -__enable_if_t -< - __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value - && !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, - int -> -basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, - size_type __n1, - const _Tp& __t, - size_type __pos2, - size_type __n2) const -{ +template <class _Tp, + __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && + !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, + int> > +_LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare( + size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) const { __self_view __sv = __t; return __self_view(*this).substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); } @@ -3954,7 +3822,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const value_type* __s) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string::compare(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::compare(): received nullptr"); return compare(0, npos, __s, traits_type::length(__s)); } @@ -3965,7 +3833,7 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const value_type* __s) const { - _LIBCPP_ASSERT(__s != nullptr, "string::compare(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string::compare(): received nullptr"); return compare(__pos1, __n1, __s, traits_type::length(__s)); } @@ -3982,7 +3850,7 @@ basic_string<_CharT, _Traits, _Allocator>::__invariants() const return false; if (data() == nullptr) return false; - if (data()[size()] != value_type()) + if (!_Traits::eq(data()[size()], value_type())) return false; return true; } @@ -4010,7 +3878,7 @@ bool operator==(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs); #else size_t __lhs_sz = __lhs.size(); @@ -4047,7 +3915,7 @@ operator==(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs) _NOEXCEPT { typedef basic_string<_CharT, _Traits, _Allocator> _String; - _LIBCPP_ASSERT(__lhs != nullptr, "operator==(char*, basic_string): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__lhs != nullptr, "operator==(char*, basic_string): received nullptr"); size_t __lhs_len = _Traits::length(__lhs); if (__lhs_len != __rhs.size()) return false; return __rhs.compare(0, _String::npos, __lhs, __lhs_len) == 0; @@ -4060,18 +3928,18 @@ bool operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs, const _CharT* __rhs) _NOEXCEPT { -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 return basic_string_view<_CharT, _Traits>(__lhs) == basic_string_view<_CharT, _Traits>(__rhs); #else typedef basic_string<_CharT, _Traits, _Allocator> _String; - _LIBCPP_ASSERT(__rhs != nullptr, "operator==(basic_string, char*): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__rhs != nullptr, "operator==(basic_string, char*): received nullptr"); size_t __rhs_len = _Traits::length(__rhs); if (__rhs_len != __lhs.size()) return false; return __lhs.compare(0, _String::npos, __rhs, __rhs_len) == 0; #endif } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _CharT, class _Traits, class _Allocator> _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>( @@ -4086,7 +3954,7 @@ operator<=>(const basic_string<_CharT, _Traits, _Allocator>& __lhs, const _CharT return basic_string_view<_CharT, _Traits>(__lhs) <=> basic_string_view<_CharT, _Traits>(__rhs); } -#else // _LIBCPP_STD_VER > 17 +#else // _LIBCPP_STD_VER >= 20 template<class _CharT, class _Traits, class _Allocator> inline _LIBCPP_HIDE_FROM_ABI @@ -4230,7 +4098,7 @@ operator>=(const _CharT* __lhs, { return !(__lhs < __rhs); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 // operator + @@ -4397,46 +4265,46 @@ swap(basic_string<_CharT, _Traits, _Allocator>& __lhs, __lhs.swap(__rhs); } -_LIBCPP_FUNC_VIS int stoi (const string& __str, size_t* __idx = nullptr, int __base = 10); -_LIBCPP_FUNC_VIS long stol (const string& __str, size_t* __idx = nullptr, int __base = 10); -_LIBCPP_FUNC_VIS unsigned long stoul (const string& __str, size_t* __idx = nullptr, int __base = 10); -_LIBCPP_FUNC_VIS long long stoll (const string& __str, size_t* __idx = nullptr, int __base = 10); -_LIBCPP_FUNC_VIS unsigned long long stoull(const string& __str, size_t* __idx = nullptr, int __base = 10); +_LIBCPP_EXPORTED_FROM_ABI int stoi (const string& __str, size_t* __idx = nullptr, int __base = 10); +_LIBCPP_EXPORTED_FROM_ABI long stol (const string& __str, size_t* __idx = nullptr, int __base = 10); +_LIBCPP_EXPORTED_FROM_ABI unsigned long stoul (const string& __str, size_t* __idx = nullptr, int __base = 10); +_LIBCPP_EXPORTED_FROM_ABI long long stoll (const string& __str, size_t* __idx = nullptr, int __base = 10); +_LIBCPP_EXPORTED_FROM_ABI unsigned long long stoull(const string& __str, size_t* __idx = nullptr, int __base = 10); -_LIBCPP_FUNC_VIS float stof (const string& __str, size_t* __idx = nullptr); -_LIBCPP_FUNC_VIS double stod (const string& __str, size_t* __idx = nullptr); -_LIBCPP_FUNC_VIS long double stold(const string& __str, size_t* __idx = nullptr); +_LIBCPP_EXPORTED_FROM_ABI float stof (const string& __str, size_t* __idx = nullptr); +_LIBCPP_EXPORTED_FROM_ABI double stod (const string& __str, size_t* __idx = nullptr); +_LIBCPP_EXPORTED_FROM_ABI long double stold(const string& __str, size_t* __idx = nullptr); -_LIBCPP_FUNC_VIS string to_string(int __val); -_LIBCPP_FUNC_VIS string to_string(unsigned __val); -_LIBCPP_FUNC_VIS string to_string(long __val); -_LIBCPP_FUNC_VIS string to_string(unsigned long __val); -_LIBCPP_FUNC_VIS string to_string(long long __val); -_LIBCPP_FUNC_VIS string to_string(unsigned long long __val); -_LIBCPP_FUNC_VIS string to_string(float __val); -_LIBCPP_FUNC_VIS string to_string(double __val); -_LIBCPP_FUNC_VIS string to_string(long double __val); +_LIBCPP_EXPORTED_FROM_ABI string to_string(int __val); +_LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned __val); +_LIBCPP_EXPORTED_FROM_ABI string to_string(long __val); +_LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned long __val); +_LIBCPP_EXPORTED_FROM_ABI string to_string(long long __val); +_LIBCPP_EXPORTED_FROM_ABI string to_string(unsigned long long __val); +_LIBCPP_EXPORTED_FROM_ABI string to_string(float __val); +_LIBCPP_EXPORTED_FROM_ABI string to_string(double __val); +_LIBCPP_EXPORTED_FROM_ABI string to_string(long double __val); #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -_LIBCPP_FUNC_VIS int stoi (const wstring& __str, size_t* __idx = nullptr, int __base = 10); -_LIBCPP_FUNC_VIS long stol (const wstring& __str, size_t* __idx = nullptr, int __base = 10); -_LIBCPP_FUNC_VIS unsigned long stoul (const wstring& __str, size_t* __idx = nullptr, int __base = 10); -_LIBCPP_FUNC_VIS long long stoll (const wstring& __str, size_t* __idx = nullptr, int __base = 10); -_LIBCPP_FUNC_VIS unsigned long long stoull(const wstring& __str, size_t* __idx = nullptr, int __base = 10); - -_LIBCPP_FUNC_VIS float stof (const wstring& __str, size_t* __idx = nullptr); -_LIBCPP_FUNC_VIS double stod (const wstring& __str, size_t* __idx = nullptr); -_LIBCPP_FUNC_VIS long double stold(const wstring& __str, size_t* __idx = nullptr); - -_LIBCPP_FUNC_VIS wstring to_wstring(int __val); -_LIBCPP_FUNC_VIS wstring to_wstring(unsigned __val); -_LIBCPP_FUNC_VIS wstring to_wstring(long __val); -_LIBCPP_FUNC_VIS wstring to_wstring(unsigned long __val); -_LIBCPP_FUNC_VIS wstring to_wstring(long long __val); -_LIBCPP_FUNC_VIS wstring to_wstring(unsigned long long __val); -_LIBCPP_FUNC_VIS wstring to_wstring(float __val); -_LIBCPP_FUNC_VIS wstring to_wstring(double __val); -_LIBCPP_FUNC_VIS wstring to_wstring(long double __val); +_LIBCPP_EXPORTED_FROM_ABI int stoi (const wstring& __str, size_t* __idx = nullptr, int __base = 10); +_LIBCPP_EXPORTED_FROM_ABI long stol (const wstring& __str, size_t* __idx = nullptr, int __base = 10); +_LIBCPP_EXPORTED_FROM_ABI unsigned long stoul (const wstring& __str, size_t* __idx = nullptr, int __base = 10); +_LIBCPP_EXPORTED_FROM_ABI long long stoll (const wstring& __str, size_t* __idx = nullptr, int __base = 10); +_LIBCPP_EXPORTED_FROM_ABI unsigned long long stoull(const wstring& __str, size_t* __idx = nullptr, int __base = 10); + +_LIBCPP_EXPORTED_FROM_ABI float stof (const wstring& __str, size_t* __idx = nullptr); +_LIBCPP_EXPORTED_FROM_ABI double stod (const wstring& __str, size_t* __idx = nullptr); +_LIBCPP_EXPORTED_FROM_ABI long double stold(const wstring& __str, size_t* __idx = nullptr); + +_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(int __val); +_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned __val); +_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long __val); +_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned long __val); +_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long long __val); +_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(unsigned long long __val); +_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(float __val); +_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(double __val); +_LIBCPP_EXPORTED_FROM_ABI wstring to_wstring(long double __val); #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS template<class _CharT, class _Traits, class _Allocator> @@ -4445,11 +4313,11 @@ const typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::npos; template <class _CharT, class _Allocator> -struct __string_hash : public __unary_function<basic_string<_CharT, char_traits<_CharT>, _Allocator>, size_t> -{ - size_t - operator()(const basic_string<_CharT, char_traits<_CharT>, _Allocator>& __val) const _NOEXCEPT - { return std::__do_string_hash(__val.data(), __val.data() + __val.size()); } +struct __string_hash : public __unary_function<basic_string<_CharT, char_traits<_CharT>, _Allocator>, size_t> { + _LIBCPP_HIDE_FROM_ABI size_t + operator()(const basic_string<_CharT, char_traits<_CharT>, _Allocator>& __val) const _NOEXCEPT { + return std::__do_string_hash(__val.data(), __val.data() + __val.size()); + } }; template <class _Allocator> @@ -4504,7 +4372,7 @@ basic_istream<_CharT, _Traits>& getline(basic_istream<_CharT, _Traits>&& __is, basic_string<_CharT, _Traits, _Allocator>& __str); -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _CharT, class _Traits, class _Allocator, class _Up> inline _LIBCPP_HIDE_FROM_ABI typename basic_string<_CharT, _Traits, _Allocator>::size_type @@ -4526,57 +4394,21 @@ inline _LIBCPP_HIDE_FROM_ABI } #endif -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - -template<class _CharT, class _Traits, class _Allocator> -bool -basic_string<_CharT, _Traits, _Allocator>::__dereferenceable(const const_iterator* __i) const -{ - return data() <= std::__to_address(__i->base()) && - std::__to_address(__i->base()) < data() + size(); -} - -template<class _CharT, class _Traits, class _Allocator> -bool -basic_string<_CharT, _Traits, _Allocator>::__decrementable(const const_iterator* __i) const -{ - return data() < std::__to_address(__i->base()) && - std::__to_address(__i->base()) <= data() + size(); -} - -template<class _CharT, class _Traits, class _Allocator> -bool -basic_string<_CharT, _Traits, _Allocator>::__addable(const const_iterator* __i, ptrdiff_t __n) const -{ - const value_type* __p = std::__to_address(__i->base()) + __n; - return data() <= __p && __p <= data() + size(); -} - -template<class _CharT, class _Traits, class _Allocator> -bool -basic_string<_CharT, _Traits, _Allocator>::__subscriptable(const const_iterator* __i, ptrdiff_t __n) const -{ - const value_type* __p = std::__to_address(__i->base()) + __n; - return data() <= __p && __p < data() + size(); -} - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 // Literal suffixes for basic_string [basic.string.literals] inline namespace literals { inline namespace string_literals { inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - basic_string<char> operator "" s( const char *__str, size_t __len ) + basic_string<char> operator""s( const char *__str, size_t __len ) { return basic_string<char> (__str, __len); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - basic_string<wchar_t> operator "" s( const wchar_t *__str, size_t __len ) + basic_string<wchar_t> operator""s( const wchar_t *__str, size_t __len ) { return basic_string<wchar_t> (__str, __len); } @@ -4584,27 +4416,27 @@ inline namespace literals #ifndef _LIBCPP_HAS_NO_CHAR8_T inline _LIBCPP_HIDE_FROM_ABI constexpr - basic_string<char8_t> operator "" s(const char8_t *__str, size_t __len) + basic_string<char8_t> operator""s(const char8_t *__str, size_t __len) { return basic_string<char8_t> (__str, __len); } #endif inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - basic_string<char16_t> operator "" s( const char16_t *__str, size_t __len ) + basic_string<char16_t> operator""s( const char16_t *__str, size_t __len ) { return basic_string<char16_t> (__str, __len); } inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 - basic_string<char32_t> operator "" s( const char32_t *__str, size_t __len ) + basic_string<char32_t> operator""s( const char32_t *__str, size_t __len ) { return basic_string<char32_t> (__str, __len); } } // namespace string_literals } // namespace literals -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <> inline constexpr bool __format::__enable_insertable<std::basic_string<char>> = true; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS @@ -4622,12 +4454,12 @@ _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <algorithm> # include <concepts> -# include <functional> +# include <cstdlib> # include <iterator> # include <new> +# include <type_traits> # include <typeinfo> # include <utility> -# include <vector> #endif #endif // _LIBCPP_STRING diff --git a/libcxx/include/string.h b/libcxx/include/string.h index 3ec877bad310..673d90316d00 100644 --- a/libcxx/include/string.h +++ b/libcxx/include/string.h @@ -64,8 +64,7 @@ size_t strlen(const char* s); // MSVCRT, GNU libc and its derivates may already have the correct prototype in // <string.h>. This macro can be defined by users if their C library provides // the right signature. -#if defined(__CORRECT_ISO_CPP_STRING_H_PROTO) || defined(_LIBCPP_MSVCRT) || \ - defined(__sun__) || defined(_STRING_H_CPLUSPLUS_98_CONFORMANCE_) +#if defined(__CORRECT_ISO_CPP_STRING_H_PROTO) || defined(_LIBCPP_MSVCRT) || defined(_STRING_H_CPLUSPLUS_98_CONFORMANCE_) #define _LIBCPP_STRING_H_HAS_CONST_OVERLOADS #endif diff --git a/libcxx/include/string_view b/libcxx/include/string_view index ea98e38de871..3149fe250578 100644 --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -90,7 +90,7 @@ namespace std { basic_string_view& operator=(const basic_string_view&) noexcept = default; template<class Allocator> constexpr basic_string_view(const charT* str); - basic_string_view(nullptr_t) = delete; // C++2b + basic_string_view(nullptr_t) = delete; // C++23 constexpr basic_string_view(const charT* str, size_type len); template <class It, class End> constexpr basic_string_view(It begin, End end); // C++20 @@ -168,9 +168,9 @@ namespace std { constexpr bool ends_with(charT c) const noexcept; // C++20 constexpr bool ends_with(const charT* s) const; // C++20 - constexpr bool contains(basic_string_view s) const noexcept; // C++2b - constexpr bool contains(charT c) const noexcept; // C++2b - constexpr bool contains(const charT* s) const; // C++2b + constexpr bool contains(basic_string_view s) const noexcept; // C++23 + constexpr bool contains(charT c) const noexcept; // C++23 + constexpr bool contains(const charT* s) const; // C++23 private: const_pointer data_; // exposition only @@ -191,11 +191,11 @@ namespace std { template <> struct hash<u32string_view>; template <> struct hash<wstring_view>; - constexpr basic_string_view<char> operator "" sv(const char *str, size_t len) noexcept; - constexpr basic_string_view<wchar_t> operator "" sv(const wchar_t *str, size_t len) noexcept; - constexpr basic_string_view<char8_t> operator "" sv(const char8_t *str, size_t len) noexcept; // C++20 - constexpr basic_string_view<char16_t> operator "" sv(const char16_t *str, size_t len) noexcept; - constexpr basic_string_view<char32_t> operator "" sv(const char32_t *str, size_t len) noexcept; + constexpr basic_string_view<char> operator""sv(const char *str, size_t len) noexcept; + constexpr basic_string_view<wchar_t> operator""sv(const wchar_t *str, size_t len) noexcept; + constexpr basic_string_view<char8_t> operator""sv(const char8_t *str, size_t len) noexcept; // C++20 + constexpr basic_string_view<char16_t> operator""sv(const char16_t *str, size_t len) noexcept; + constexpr basic_string_view<char32_t> operator""sv(const char32_t *str, size_t len) noexcept; } // namespace std @@ -208,8 +208,9 @@ namespace std { #include <__functional/hash.h> #include <__functional/unary_function.h> #include <__fwd/string_view.h> +#include <__iterator/bounded_iter.h> #include <__iterator/concepts.h> -#include <__iterator/readable_traits.h> +#include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> #include <__memory/pointer_traits.h> #include <__ranges/concepts.h> @@ -218,10 +219,18 @@ namespace std { #include <__ranges/enable_view.h> #include <__ranges/size.h> #include <__string/char_traits.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_same.h> +#include <__type_traits/is_standard_layout.h> +#include <__type_traits/is_trivial.h> +#include <__type_traits/remove_cvref.h> +#include <__type_traits/remove_reference.h> +#include <__type_traits/type_identity.h> +#include <cstddef> #include <iosfwd> #include <limits> #include <stdexcept> -#include <type_traits> #include <version> // standard-mandated includes @@ -252,7 +261,9 @@ template <class _Traits> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR inline size_t __char_traits_length_checked(const typename _Traits::char_type* __s) _NOEXCEPT { // This needs to be a single statement for C++11 constexpr - return _LIBCPP_ASSERT(__s != nullptr, "null pointer passed to non-null argument of char_traits<...>::length"), _Traits::length(__s); + return _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, + "null pointer passed to non-null argument of char_traits<...>::length"), + _Traits::length(__s); } template<class _CharT, class _Traits> @@ -265,7 +276,11 @@ public: using const_pointer = const _CharT*; using reference = _CharT&; using const_reference = const _CharT&; +#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS + using const_iterator = __bounded_iter<const_pointer>; +#else using const_iterator = const_pointer; // See [string.view.iterators] +#endif using iterator = const_iterator; using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>; using reverse_iterator = const_reverse_iterator; @@ -293,22 +308,27 @@ public: basic_string_view(const _CharT* __s, size_type __len) _NOEXCEPT : __data_(__s), __size_(__len) { -#if _LIBCPP_STD_VER > 11 - _LIBCPP_ASSERT(__len == 0 || __s != nullptr, "string_view::string_view(_CharT *, size_t): received nullptr"); +#if _LIBCPP_STD_VER >= 14 + _LIBCPP_ASSERT_UNCATEGORIZED( + __len <= static_cast<size_type>(numeric_limits<difference_type>::max()), + "string_view::string_view(_CharT *, size_t): length does not fit in difference_type"); + _LIBCPP_ASSERT_UNCATEGORIZED(__len == 0 || __s != nullptr, + "string_view::string_view(_CharT *, size_t): received nullptr"); #endif } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <contiguous_iterator _It, sized_sentinel_for<_It> _End> requires (is_same_v<iter_value_t<_It>, _CharT> && !is_convertible_v<_End, size_type>) constexpr _LIBCPP_HIDE_FROM_ABI basic_string_view(_It __begin, _End __end) : __data_(_VSTD::to_address(__begin)), __size_(__end - __begin) { - _LIBCPP_ASSERT((__end - __begin) >= 0, "std::string_view::string_view(iterator, sentinel) received invalid range"); + _LIBCPP_ASSERT_VALID_INPUT_RANGE((__end - __begin) >= 0, + "std::string_view::string_view(iterator, sentinel) received invalid range"); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _Range> requires ( !is_same_v<remove_cvref_t<_Range>, basic_string_view> && @@ -318,20 +338,17 @@ public: !is_convertible_v<_Range, const _CharT*> && (!requires(remove_cvref_t<_Range>& __d) { __d.operator _VSTD::basic_string_view<_CharT, _Traits>(); - }) && - (!requires { - typename remove_reference_t<_Range>::traits_type; - } || is_same_v<typename remove_reference_t<_Range>::traits_type, _Traits>) + }) ) constexpr explicit _LIBCPP_HIDE_FROM_ABI basic_string_view(_Range&& __r) : __data_(ranges::data(__r)), __size_(ranges::size(__r)) {} -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY basic_string_view(const _CharT* __s) : __data_(__s), __size_(_VSTD::__char_traits_length_checked<_Traits>(__s)) {} -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 basic_string_view(nullptr_t) = delete; #endif @@ -343,10 +360,22 @@ public: const_iterator end() const _NOEXCEPT { return cend(); } _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY - const_iterator cbegin() const _NOEXCEPT { return __data_; } + const_iterator cbegin() const _NOEXCEPT { +#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS + return std::__make_bounded_iter(data(), data(), data() + size()); +#else + return __data_; +#endif + } _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY - const_iterator cend() const _NOEXCEPT { return __data_ + __size_; } + const_iterator cend() const _NOEXCEPT { +#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS + return std::__make_bounded_iter(data() + size(), data(), data() + size()); +#else + return __data_ + __size_; +#endif + } _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_INLINE_VISIBILITY const_reverse_iterator rbegin() const _NOEXCEPT { return const_reverse_iterator(cend()); } @@ -376,7 +405,7 @@ public: // [string.view.access], element access _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __pos) const _NOEXCEPT { - return _LIBCPP_ASSERT(__pos < size(), "string_view[] index out of bounds"), __data_[__pos]; + return _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos < size(), "string_view[] index out of bounds"), __data_[__pos]; } _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY @@ -390,13 +419,14 @@ public: _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY const_reference front() const _NOEXCEPT { - return _LIBCPP_ASSERT(!empty(), "string_view::front(): string is empty"), __data_[0]; + return _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string_view::front(): string is empty"), __data_[0]; } _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY const_reference back() const _NOEXCEPT { - return _LIBCPP_ASSERT(!empty(), "string_view::back(): string is empty"), __data_[__size_-1]; + return _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string_view::back(): string is empty"), + __data_[__size_ - 1]; } _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY @@ -406,7 +436,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY void remove_prefix(size_type __n) _NOEXCEPT { - _LIBCPP_ASSERT(__n <= size(), "remove_prefix() can't remove more than size()"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n <= size(), "remove_prefix() can't remove more than size()"); __data_ += __n; __size_ -= __n; } @@ -414,7 +444,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY void remove_suffix(size_type __n) _NOEXCEPT { - _LIBCPP_ASSERT(__n <= size(), "remove_suffix() can't remove more than size()"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n <= size(), "remove_suffix() can't remove more than size()"); __size_ -= __n; } @@ -492,7 +522,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find(basic_string_view __s, size_type __pos = 0) const _NOEXCEPT { - _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s.size() == 0 || __s.data() != nullptr, "string_view::find(): received nullptr"); return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } @@ -507,7 +537,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string_view::find(): received nullptr"); return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -515,7 +545,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find(const _CharT* __s, size_type __pos = 0) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string_view::find(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string_view::find(): received nullptr"); return std::__str_find<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -524,7 +554,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type rfind(basic_string_view __s, size_type __pos = npos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s.size() == 0 || __s.data() != nullptr, "string_view::find(): received nullptr"); return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } @@ -539,7 +569,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::rfind(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string_view::rfind(): received nullptr"); return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -547,7 +577,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type rfind(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string_view::rfind(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string_view::rfind(): received nullptr"); return std::__str_rfind<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -556,7 +586,8 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_first_of(basic_string_view __s, size_type __pos = 0) const _NOEXCEPT { - _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_first_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s.size() == 0 || __s.data() != nullptr, + "string_view::find_first_of(): received nullptr"); return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } @@ -568,7 +599,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string_view::find_first_of(): received nullptr"); return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -576,7 +607,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_first_of(const _CharT* __s, size_type __pos=0) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string_view::find_first_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string_view::find_first_of(): received nullptr"); return std::__str_find_first_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -585,7 +616,8 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_last_of(basic_string_view __s, size_type __pos=npos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_last_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s.size() == 0 || __s.data() != nullptr, + "string_view::find_last_of(): received nullptr"); return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } @@ -597,7 +629,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string_view::find_last_of(): received nullptr"); return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -605,7 +637,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_last_of(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string_view::find_last_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string_view::find_last_of(): received nullptr"); return std::__str_find_last_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -614,7 +646,8 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(basic_string_view __s, size_type __pos=0) const _NOEXCEPT { - _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_first_not_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s.size() == 0 || __s.data() != nullptr, + "string_view::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } @@ -629,7 +662,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_first_not_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string_view::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -637,7 +670,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(const _CharT* __s, size_type __pos=0) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string_view::find_first_not_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string_view::find_first_not_of(): received nullptr"); return std::__str_find_first_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } @@ -646,7 +679,8 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(basic_string_view __s, size_type __pos=npos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s.size() == 0 || __s.data() != nullptr, "string_view::find_last_not_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s.size() == 0 || __s.data() != nullptr, + "string_view::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s.data(), __pos, __s.size()); } @@ -661,7 +695,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string_view::find_last_not_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__n == 0 || __s != nullptr, "string_view::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, __n); } @@ -669,12 +703,12 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(const _CharT* __s, size_type __pos=npos) const _NOEXCEPT { - _LIBCPP_ASSERT(__s != nullptr, "string_view::find_last_not_of(): received nullptr"); + _LIBCPP_ASSERT_UNCATEGORIZED(__s != nullptr, "string_view::find_last_not_of(): received nullptr"); return std::__str_find_last_not_of<value_type, size_type, traits_type, npos> (data(), size(), __s, __pos, traits_type::length(__s)); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 constexpr _LIBCPP_INLINE_VISIBILITY bool starts_with(basic_string_view __s) const noexcept { return size() >= __s.size() && compare(0, __s.size(), __s) == 0; } @@ -700,7 +734,7 @@ public: { return ends_with(basic_string_view(__s)); } #endif -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 constexpr _LIBCPP_INLINE_VISIBILITY bool contains(basic_string_view __sv) const noexcept { return find(__sv) != npos; } @@ -720,23 +754,23 @@ private: }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_string_view); -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _CharT, class _Traits> inline constexpr bool ranges::enable_view<basic_string_view<_CharT, _Traits>> = true; template <class _CharT, class _Traits> inline constexpr bool ranges::enable_borrowed_range<basic_string_view<_CharT, _Traits> > = true; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 // [string.view.deduct] -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <contiguous_iterator _It, sized_sentinel_for<_It> _End> basic_string_view(_It, _End) -> basic_string_view<iter_value_t<_It>>; -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <ranges::contiguous_range _Range> basic_string_view(_Range) -> basic_string_view<ranges::range_value_t<_Range>>; #endif @@ -773,11 +807,11 @@ bool operator==(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs, if (__lhs.size() != __rhs.size()) return false; return __lhs.compare(__rhs) == 0; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 // operator <=> -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _CharT, class _Traits> _LIBCPP_HIDE_FROM_ABI constexpr auto @@ -807,7 +841,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>( } } -#else // _LIBCPP_STD_VER > 17 +#else // _LIBCPP_STD_VER >= 20 // operator != template<class _CharT, class _Traits> @@ -940,7 +974,7 @@ bool operator>=(__type_identity_t<basic_string_view<_CharT, _Traits> > __lhs, return __lhs.compare(__rhs) >= 0; } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 template<class _CharT, class _Traits> _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& @@ -976,20 +1010,20 @@ template <> struct hash<basic_string_view<wchar_t, char_traits<wchar_t> > > : __string_view_hash<wchar_t> {}; #endif -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 inline namespace literals { inline namespace string_view_literals { inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - basic_string_view<char> operator "" sv(const char *__str, size_t __len) _NOEXCEPT + basic_string_view<char> operator""sv(const char *__str, size_t __len) _NOEXCEPT { return basic_string_view<char> (__str, __len); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - basic_string_view<wchar_t> operator "" sv(const wchar_t *__str, size_t __len) _NOEXCEPT + basic_string_view<wchar_t> operator""sv(const wchar_t *__str, size_t __len) _NOEXCEPT { return basic_string_view<wchar_t> (__str, __len); } @@ -997,20 +1031,20 @@ inline namespace literals #ifndef _LIBCPP_HAS_NO_CHAR8_T inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - basic_string_view<char8_t> operator "" sv(const char8_t *__str, size_t __len) _NOEXCEPT + basic_string_view<char8_t> operator""sv(const char8_t *__str, size_t __len) _NOEXCEPT { return basic_string_view<char8_t> (__str, __len); } #endif inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - basic_string_view<char16_t> operator "" sv(const char16_t *__str, size_t __len) _NOEXCEPT + basic_string_view<char16_t> operator""sv(const char16_t *__str, size_t __len) _NOEXCEPT { return basic_string_view<char16_t> (__str, __len); } inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR - basic_string_view<char32_t> operator "" sv(const char32_t *__str, size_t __len) _NOEXCEPT + basic_string_view<char32_t> operator""sv(const char32_t *__str, size_t __len) _NOEXCEPT { return basic_string_view<char32_t> (__str, __len); } @@ -1024,8 +1058,9 @@ _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <algorithm> # include <concepts> -# include <functional> +# include <cstdlib> # include <iterator> +# include <type_traits> #endif #endif // _LIBCPP_STRING_VIEW diff --git a/libcxx/include/strstream b/libcxx/include/strstream index 9382473f68f5..35d655b8261a 100644 --- a/libcxx/include/strstream +++ b/libcxx/include/strstream @@ -141,12 +141,12 @@ private: _LIBCPP_BEGIN_NAMESPACE_STD -class _LIBCPP_TYPE_VIS strstreambuf +class _LIBCPP_DEPRECATED _LIBCPP_EXPORTED_FROM_ABI strstreambuf : public streambuf { public: #ifndef _LIBCPP_CXX03_LANG - strstreambuf() : strstreambuf(0) {} + _LIBCPP_HIDE_FROM_ABI strstreambuf() : strstreambuf(0) {} explicit strstreambuf(streamsize __alsize); #else explicit strstreambuf(streamsize __alsize = 0); @@ -237,7 +237,7 @@ strstreambuf::operator=(strstreambuf&& __rhs) #endif // _LIBCPP_CXX03_LANG -class _LIBCPP_TYPE_VIS istrstream +class _LIBCPP_DEPRECATED _LIBCPP_EXPORTED_FROM_ABI istrstream : public istream { public: @@ -256,8 +256,8 @@ public: #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY - istrstream(istrstream&& __rhs) - : istream(_VSTD::move(__rhs)), + istrstream(istrstream&& __rhs) // extension + : istream(_VSTD::move(static_cast<istream&>(__rhs))), __sb_(_VSTD::move(__rhs.__sb_)) { istream::set_rdbuf(&__sb_); @@ -290,7 +290,7 @@ private: strstreambuf __sb_; }; -class _LIBCPP_TYPE_VIS ostrstream +class _LIBCPP_DEPRECATED _LIBCPP_EXPORTED_FROM_ABI ostrstream : public ostream { public: @@ -305,8 +305,8 @@ public: #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY - ostrstream(ostrstream&& __rhs) - : ostream(_VSTD::move(__rhs)), + ostrstream(ostrstream&& __rhs) // extension + : ostream(_VSTD::move(static_cast<ostream&>(__rhs))), __sb_(_VSTD::move(__rhs.__sb_)) { ostream::set_rdbuf(&__sb_); @@ -343,7 +343,7 @@ private: strstreambuf __sb_; // exposition only }; -class _LIBCPP_TYPE_VIS strstream +class _LIBCPP_DEPRECATED _LIBCPP_EXPORTED_FROM_ABI strstream : public iostream { public: @@ -365,8 +365,8 @@ public: #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY - strstream(strstream&& __rhs) - : iostream(_VSTD::move(__rhs)), + strstream(strstream&& __rhs) // extension + : iostream(_VSTD::move(static_cast<iostream&>(__rhs))), __sb_(_VSTD::move(__rhs.__sb_)) { iostream::set_rdbuf(&__sb_); diff --git a/libcxx/include/system_error b/libcxx/include/system_error index 98919927bc04..a60c98492aac 100644 --- a/libcxx/include/system_error +++ b/libcxx/include/system_error @@ -146,13 +146,11 @@ template <> struct hash<std::error_condition>; #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include <__errc> -#include <__functional/hash.h> -#include <__functional/unary_function.h> -#include <__memory/addressof.h> -#include <stdexcept> -#include <string> -#include <type_traits> +#include <__system_error/errc.h> +#include <__system_error/error_category.h> +#include <__system_error/error_code.h> +#include <__system_error/error_condition.h> +#include <__system_error/system_error.h> #include <version> // standard-mandated includes @@ -164,385 +162,11 @@ template <> struct hash<std::error_condition>; # pragma GCC system_header #endif -_LIBCPP_BEGIN_NAMESPACE_STD - -// is_error_code_enum - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_error_code_enum - : public false_type {}; - -#if _LIBCPP_STD_VER > 14 -template <class _Tp> -inline constexpr bool is_error_code_enum_v = is_error_code_enum<_Tp>::value; -#endif - -// is_error_condition_enum - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum - : public false_type {}; - -#if _LIBCPP_STD_VER > 14 -template <class _Tp> -inline constexpr bool is_error_condition_enum_v = is_error_condition_enum<_Tp>::value; -#endif - -template <> -struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum<errc> - : true_type { }; - -#ifdef _LIBCPP_CXX03_LANG -template <> -struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum<errc::__lx> - : true_type { }; -#endif - -class _LIBCPP_TYPE_VIS error_condition; -class _LIBCPP_TYPE_VIS error_code; - -// class error_category - -class _LIBCPP_HIDDEN __do_message; - -class _LIBCPP_TYPE_VIS error_category -{ -public: - virtual ~error_category() _NOEXCEPT; - -#if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS) - error_category() noexcept; -#else - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR_SINCE_CXX14 error_category() _NOEXCEPT = default; +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstdint> +# include <cstring> +# include <limits> +# include <type_traits> #endif - error_category(const error_category&) = delete; - error_category& operator=(const error_category&) = delete; - - virtual const char* name() const _NOEXCEPT = 0; - virtual error_condition default_error_condition(int __ev) const _NOEXCEPT; - virtual bool equivalent(int __code, const error_condition& __condition) const _NOEXCEPT; - virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT; - virtual string message(int __ev) const = 0; - - _LIBCPP_INLINE_VISIBILITY - bool operator==(const error_category& __rhs) const _NOEXCEPT {return this == &__rhs;} - -#if _LIBCPP_STD_VER > 17 - - _LIBCPP_HIDE_FROM_ABI - strong_ordering operator<=>(const error_category& __rhs) const noexcept {return compare_three_way()(this, std::addressof(__rhs));} - -#else // _LIBCPP_STD_VER > 17 - - _LIBCPP_INLINE_VISIBILITY - bool operator!=(const error_category& __rhs) const _NOEXCEPT {return !(*this == __rhs);} - - _LIBCPP_INLINE_VISIBILITY - bool operator< (const error_category& __rhs) const _NOEXCEPT {return this < &__rhs;} - -#endif // _LIBCPP_STD_VER > 17 - - friend class _LIBCPP_HIDDEN __do_message; -}; - -class _LIBCPP_HIDDEN __do_message - : public error_category -{ -public: - string message(int __ev) const override; -}; - -_LIBCPP_FUNC_VIS const error_category& generic_category() _NOEXCEPT; -_LIBCPP_FUNC_VIS const error_category& system_category() _NOEXCEPT; - -namespace __adl_only { - // Those cause ADL to trigger but they are not viable candidates, - // so they are never actually selected. - void make_error_condition() = delete; - void make_error_code() = delete; -} // namespace __adl_only - -class _LIBCPP_TYPE_VIS error_condition -{ - int __val_; - const error_category* __cat_; -public: - _LIBCPP_INLINE_VISIBILITY - error_condition() _NOEXCEPT : __val_(0), __cat_(&generic_category()) {} - - _LIBCPP_INLINE_VISIBILITY - error_condition(int __val, const error_category& __cat) _NOEXCEPT - : __val_(__val), __cat_(&__cat) {} - - template <class _Ep> - _LIBCPP_INLINE_VISIBILITY - error_condition(_Ep __e, - typename enable_if<is_error_condition_enum<_Ep>::value>::type* = nullptr - ) _NOEXCEPT - { - using __adl_only::make_error_condition; - *this = make_error_condition(__e); - } - - _LIBCPP_INLINE_VISIBILITY - void assign(int __val, const error_category& __cat) _NOEXCEPT - { - __val_ = __val; - __cat_ = &__cat; - } - - template <class _Ep> - _LIBCPP_INLINE_VISIBILITY - typename enable_if - < - is_error_condition_enum<_Ep>::value, - error_condition& - >::type - operator=(_Ep __e) _NOEXCEPT - { - using __adl_only::make_error_condition; - *this = make_error_condition(__e); - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - void clear() _NOEXCEPT - { - __val_ = 0; - __cat_ = &generic_category(); - } - - _LIBCPP_INLINE_VISIBILITY - int value() const _NOEXCEPT {return __val_;} - - _LIBCPP_INLINE_VISIBILITY - const error_category& category() const _NOEXCEPT {return *__cat_;} - string message() const; - - _LIBCPP_INLINE_VISIBILITY - explicit operator bool() const _NOEXCEPT {return __val_ != 0;} -}; - -inline _LIBCPP_INLINE_VISIBILITY -error_condition -make_error_condition(errc __e) _NOEXCEPT -{ - return error_condition(static_cast<int>(__e), generic_category()); -} - -// error_code - -class _LIBCPP_TYPE_VIS error_code -{ - int __val_; - const error_category* __cat_; -public: - _LIBCPP_INLINE_VISIBILITY - error_code() _NOEXCEPT : __val_(0), __cat_(&system_category()) {} - - _LIBCPP_INLINE_VISIBILITY - error_code(int __val, const error_category& __cat) _NOEXCEPT - : __val_(__val), __cat_(&__cat) {} - - template <class _Ep> - _LIBCPP_INLINE_VISIBILITY - error_code(_Ep __e, - typename enable_if<is_error_code_enum<_Ep>::value>::type* = nullptr - ) _NOEXCEPT - { - using __adl_only::make_error_code; - *this = make_error_code(__e); - } - - _LIBCPP_INLINE_VISIBILITY - void assign(int __val, const error_category& __cat) _NOEXCEPT - { - __val_ = __val; - __cat_ = &__cat; - } - - template <class _Ep> - _LIBCPP_INLINE_VISIBILITY - typename enable_if - < - is_error_code_enum<_Ep>::value, - error_code& - >::type - operator=(_Ep __e) _NOEXCEPT - { - using __adl_only::make_error_code; - *this = make_error_code(__e); - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - void clear() _NOEXCEPT - { - __val_ = 0; - __cat_ = &system_category(); - } - - _LIBCPP_INLINE_VISIBILITY - int value() const _NOEXCEPT {return __val_;} - - _LIBCPP_INLINE_VISIBILITY - const error_category& category() const _NOEXCEPT {return *__cat_;} - - _LIBCPP_INLINE_VISIBILITY - error_condition default_error_condition() const _NOEXCEPT - {return __cat_->default_error_condition(__val_);} - - string message() const; - - _LIBCPP_INLINE_VISIBILITY - explicit operator bool() const _NOEXCEPT {return __val_ != 0;} -}; - -inline _LIBCPP_INLINE_VISIBILITY -error_code -make_error_code(errc __e) _NOEXCEPT -{ - return error_code(static_cast<int>(__e), generic_category()); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool -operator==(const error_code& __x, const error_code& __y) _NOEXCEPT -{ - return __x.category() == __y.category() && __x.value() == __y.value(); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool -operator==(const error_code& __x, const error_condition& __y) _NOEXCEPT -{ - return __x.category().equivalent(__x.value(), __y) - || __y.category().equivalent(__x, __y.value()); -} - -#if _LIBCPP_STD_VER <= 17 -inline _LIBCPP_INLINE_VISIBILITY -bool -operator==(const error_condition& __x, const error_code& __y) _NOEXCEPT -{ - return __y == __x; -} -#endif - -inline _LIBCPP_INLINE_VISIBILITY -bool -operator==(const error_condition& __x, const error_condition& __y) _NOEXCEPT -{ - return __x.category() == __y.category() && __x.value() == __y.value(); -} - -#if _LIBCPP_STD_VER <= 17 - -inline _LIBCPP_INLINE_VISIBILITY -bool -operator!=(const error_code& __x, const error_code& __y) _NOEXCEPT -{return !(__x == __y);} - -inline _LIBCPP_INLINE_VISIBILITY -bool -operator!=(const error_code& __x, const error_condition& __y) _NOEXCEPT -{return !(__x == __y);} - -inline _LIBCPP_INLINE_VISIBILITY -bool -operator!=(const error_condition& __x, const error_code& __y) _NOEXCEPT -{return !(__x == __y);} - -inline _LIBCPP_INLINE_VISIBILITY -bool -operator!=(const error_condition& __x, const error_condition& __y) _NOEXCEPT -{return !(__x == __y);} - -inline _LIBCPP_INLINE_VISIBILITY -bool -operator<(const error_condition& __x, const error_condition& __y) _NOEXCEPT -{ - return __x.category() < __y.category() - || (__x.category() == __y.category() && __x.value() < __y.value()); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool -operator<(const error_code& __x, const error_code& __y) _NOEXCEPT -{ - return __x.category() < __y.category() - || (__x.category() == __y.category() && __x.value() < __y.value()); -} - -#else // _LIBCPP_STD_VER <= 17 - -inline _LIBCPP_HIDE_FROM_ABI strong_ordering -operator<=>(const error_code& __x, const error_code& __y) noexcept -{ - if (auto __c = __x.category() <=> __y.category(); __c != 0) - return __c; - return __x.value() <=> __y.value(); -} - -inline _LIBCPP_HIDE_FROM_ABI strong_ordering -operator<=>(const error_condition& __x, const error_condition& __y) noexcept -{ - if (auto __c = __x.category() <=> __y.category(); __c != 0) - return __c; - return __x.value() <=> __y.value(); -} - -#endif // _LIBCPP_STD_VER <= 17 - -template <> -struct _LIBCPP_TEMPLATE_VIS hash<error_code> - : public __unary_function<error_code, size_t> -{ - _LIBCPP_INLINE_VISIBILITY - size_t operator()(const error_code& __ec) const _NOEXCEPT - { - return static_cast<size_t>(__ec.value()); - } -}; - -template <> -struct _LIBCPP_TEMPLATE_VIS hash<error_condition> - : public __unary_function<error_condition, size_t> -{ - _LIBCPP_INLINE_VISIBILITY - size_t operator()(const error_condition& __ec) const _NOEXCEPT - { - return static_cast<size_t>(__ec.value()); - } -}; - -// system_error - -class _LIBCPP_TYPE_VIS system_error - : public runtime_error -{ - error_code __ec_; -public: - system_error(error_code __ec, const string& __what_arg); - system_error(error_code __ec, const char* __what_arg); - system_error(error_code __ec); - system_error(int __ev, const error_category& __ecat, const string& __what_arg); - system_error(int __ev, const error_category& __ecat, const char* __what_arg); - system_error(int __ev, const error_category& __ecat); - system_error(const system_error&) _NOEXCEPT = default; - ~system_error() _NOEXCEPT override; - - _LIBCPP_INLINE_VISIBILITY - const error_code& code() const _NOEXCEPT {return __ec_;} - -private: - static string __init(const error_code&, string); -}; - -_LIBCPP_NORETURN _LIBCPP_FUNC_VIS -void __throw_system_error(int __ev, const char* __what_arg); - -_LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_SYSTEM_ERROR diff --git a/libcxx/include/thread b/libcxx/include/thread index 7a1117f555a7..4ddcf3ec79cb 100644 --- a/libcxx/include/thread +++ b/libcxx/include/thread @@ -64,6 +64,9 @@ template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& out, thread::id id); +template<class charT> +struct formatter<thread::id, charT>; + namespace this_thread { @@ -84,19 +87,12 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time); */ #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> #include <__config> -#include <__functional/hash.h> -#include <__memory/unique_ptr.h> -#include <__mutex_base> -#include <__thread/poll_with_backoff.h> -#include <__thread/timed_backoff_policy.h> +#include <__thread/formatter.h> +#include <__thread/this_thread.h> +#include <__thread/thread.h> #include <__threading_support> -#include <__utility/forward.h> -#include <cstddef> -#include <iosfwd> -#include <system_error> -#include <tuple> -#include <type_traits> #include <version> // standard-mandated includes @@ -108,314 +104,27 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time); # pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - #ifdef _LIBCPP_HAS_NO_THREADS # error "<thread> is not supported since libc++ has been configured without support for threads." #endif -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> class __thread_specific_ptr; -class _LIBCPP_TYPE_VIS __thread_struct; -class _LIBCPP_HIDDEN __thread_struct_imp; -class __assoc_sub_state; - -_LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); - -class _LIBCPP_TYPE_VIS __thread_struct -{ - __thread_struct_imp* __p_; - - __thread_struct(const __thread_struct&); - __thread_struct& operator=(const __thread_struct&); -public: - __thread_struct(); - ~__thread_struct(); - - void notify_all_at_thread_exit(condition_variable*, mutex*); - void __make_ready_at_thread_exit(__assoc_sub_state*); -}; - -template <class _Tp> -class __thread_specific_ptr -{ - __libcpp_tls_key __key_; - - // Only __thread_local_data() may construct a __thread_specific_ptr - // and only with _Tp == __thread_struct. - static_assert((is_same<_Tp, __thread_struct>::value), ""); - __thread_specific_ptr(); - friend _LIBCPP_FUNC_VIS __thread_specific_ptr<__thread_struct>& __thread_local_data(); - - __thread_specific_ptr(const __thread_specific_ptr&); - __thread_specific_ptr& operator=(const __thread_specific_ptr&); - - _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*); - -public: - typedef _Tp* pointer; - - ~__thread_specific_ptr(); - - _LIBCPP_INLINE_VISIBILITY - pointer get() const {return static_cast<_Tp*>(__libcpp_tls_get(__key_));} - _LIBCPP_INLINE_VISIBILITY - pointer operator*() const {return *get();} - _LIBCPP_INLINE_VISIBILITY - pointer operator->() const {return get();} - void set_pointer(pointer __p); -}; - -template <class _Tp> -void _LIBCPP_TLS_DESTRUCTOR_CC -__thread_specific_ptr<_Tp>::__at_thread_exit(void* __p) -{ - delete static_cast<pointer>(__p); -} - -template <class _Tp> -__thread_specific_ptr<_Tp>::__thread_specific_ptr() -{ - int __ec = - __libcpp_tls_create(&__key_, &__thread_specific_ptr::__at_thread_exit); - if (__ec) - __throw_system_error(__ec, "__thread_specific_ptr construction failed"); -} - -template <class _Tp> -__thread_specific_ptr<_Tp>::~__thread_specific_ptr() -{ - // __thread_specific_ptr is only created with a static storage duration - // so this destructor is only invoked during program termination. Invoking - // pthread_key_delete(__key_) may prevent other threads from deleting their - // thread local data. For this reason we leak the key. -} - -template <class _Tp> -void -__thread_specific_ptr<_Tp>::set_pointer(pointer __p) -{ - _LIBCPP_ASSERT(get() == nullptr, - "Attempting to overwrite thread local data"); - std::__libcpp_tls_set(__key_, __p); -} - -template<> -struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> - : public __unary_function<__thread_id, size_t> -{ - _LIBCPP_INLINE_VISIBILITY - size_t operator()(__thread_id __v) const _NOEXCEPT - { - return hash<__libcpp_thread_id>()(__v.__id_); - } -}; - -template<class _CharT, class _Traits> -_LIBCPP_INLINE_VISIBILITY -basic_ostream<_CharT, _Traits>& -operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) -{return __os << __id.__id_;} - -class _LIBCPP_TYPE_VIS thread -{ - __libcpp_thread_t __t_; - - thread(const thread&); - thread& operator=(const thread&); -public: - typedef __thread_id id; - typedef __libcpp_thread_t native_handle_type; - - _LIBCPP_INLINE_VISIBILITY - thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} -#ifndef _LIBCPP_CXX03_LANG - template <class _Fp, class ..._Args, - class = __enable_if_t<!is_same<__remove_cvref_t<_Fp>, thread>::value> > - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - explicit thread(_Fp&& __f, _Args&&... __args); -#else // _LIBCPP_CXX03_LANG - template <class _Fp> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - explicit thread(_Fp __f); +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) +# include <cstddef> +# include <ctime> +# include <iosfwd> +# include <ratio> #endif - ~thread(); - - _LIBCPP_INLINE_VISIBILITY - thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { - __t.__t_ = _LIBCPP_NULL_THREAD; - } - - _LIBCPP_INLINE_VISIBILITY - thread& operator=(thread&& __t) _NOEXCEPT { - if (!__libcpp_thread_isnull(&__t_)) - terminate(); - __t_ = __t.__t_; - __t.__t_ = _LIBCPP_NULL_THREAD; - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - void swap(thread& __t) _NOEXCEPT {_VSTD::swap(__t_, __t.__t_);} - - _LIBCPP_INLINE_VISIBILITY - bool joinable() const _NOEXCEPT {return !__libcpp_thread_isnull(&__t_);} - void join(); - void detach(); - _LIBCPP_INLINE_VISIBILITY - id get_id() const _NOEXCEPT {return __libcpp_thread_get_id(&__t_);} - _LIBCPP_INLINE_VISIBILITY - native_handle_type native_handle() _NOEXCEPT {return __t_;} - - static unsigned hardware_concurrency() _NOEXCEPT; -}; - -#ifndef _LIBCPP_CXX03_LANG - -template <class _TSp, class _Fp, class ..._Args, size_t ..._Indices> -inline _LIBCPP_INLINE_VISIBILITY -void -__thread_execute(tuple<_TSp, _Fp, _Args...>& __t, __tuple_indices<_Indices...>) -{ - _VSTD::__invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...); -} - -template <class _Fp> -_LIBCPP_INLINE_VISIBILITY -void* __thread_proxy(void* __vp) -{ - // _Fp = tuple< unique_ptr<__thread_struct>, Functor, Args...> - unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); - __thread_local_data().set_pointer(_VSTD::get<0>(*__p.get()).release()); - typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 2>::type _Index; - _VSTD::__thread_execute(*__p.get(), _Index()); - return nullptr; -} - -template <class _Fp, class ..._Args, - class - > -thread::thread(_Fp&& __f, _Args&&... __args) -{ - typedef unique_ptr<__thread_struct> _TSPtr; - _TSPtr __tsp(new __thread_struct); - typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp; - unique_ptr<_Gp> __p( - new _Gp(_VSTD::move(__tsp), - _VSTD::forward<_Fp>(__f), - _VSTD::forward<_Args>(__args)...)); - int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get()); - if (__ec == 0) - __p.release(); - else - __throw_system_error(__ec, "thread constructor failed"); -} - -#else // _LIBCPP_CXX03_LANG - -template <class _Fp> -struct __thread_invoke_pair { - // This type is used to pass memory for thread local storage and a functor - // to a newly created thread because std::pair doesn't work with - // std::unique_ptr in C++03. - __thread_invoke_pair(_Fp& __f) : __tsp_(new __thread_struct), __fn_(__f) {} - unique_ptr<__thread_struct> __tsp_; - _Fp __fn_; -}; - -template <class _Fp> -_LIBCPP_HIDE_FROM_ABI void* __thread_proxy_cxx03(void* __vp) -{ - unique_ptr<_Fp> __p(static_cast<_Fp*>(__vp)); - __thread_local_data().set_pointer(__p->__tsp_.release()); - (__p->__fn_)(); - return nullptr; -} - -template <class _Fp> -thread::thread(_Fp __f) -{ - - typedef __thread_invoke_pair<_Fp> _InvokePair; - typedef unique_ptr<_InvokePair> _PairPtr; - _PairPtr __pp(new _InvokePair(__f)); - int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); - if (__ec == 0) - __pp.release(); - else - __throw_system_error(__ec, "thread constructor failed"); -} - -#endif // _LIBCPP_CXX03_LANG - -inline _LIBCPP_INLINE_VISIBILITY -void swap(thread& __x, thread& __y) _NOEXCEPT {__x.swap(__y);} - -namespace this_thread -{ - -_LIBCPP_FUNC_VIS void sleep_for(const chrono::nanoseconds& __ns); - -template <class _Rep, class _Period> -_LIBCPP_HIDE_FROM_ABI void -sleep_for(const chrono::duration<_Rep, _Period>& __d) -{ - if (__d > chrono::duration<_Rep, _Period>::zero()) - { - // The standard guarantees a 64bit signed integer resolution for nanoseconds, - // so use INT64_MAX / 1e9 as cut-off point. Use a constant to avoid <climits> - // and issues with long double folding on PowerPC with GCC. - _LIBCPP_CONSTEXPR chrono::duration<long double> _Max = - chrono::duration<long double>(9223372036.0L); - chrono::nanoseconds __ns; - if (__d < _Max) - { - __ns = chrono::duration_cast<chrono::nanoseconds>(__d); - if (__ns < __d) - ++__ns; - } - else - __ns = chrono::nanoseconds::max(); - this_thread::sleep_for(__ns); - } -} - -template <class _Clock, class _Duration> -_LIBCPP_HIDE_FROM_ABI void -sleep_until(const chrono::time_point<_Clock, _Duration>& __t) -{ - mutex __mut; - condition_variable __cv; - unique_lock<mutex> __lk(__mut); - while (_Clock::now() < __t) - __cv.wait_until(__lk, __t); -} - -template <class _Duration> -inline _LIBCPP_INLINE_VISIBILITY -void -sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t) -{ - this_thread::sleep_for(__t - chrono::steady_clock::now()); -} - -inline _LIBCPP_INLINE_VISIBILITY -void yield() _NOEXCEPT {__libcpp_thread_yield();} - -} // namespace this_thread - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17 # include <chrono> #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstring> # include <functional> +# include <new> +# include <system_error> +# include <type_traits> #endif #endif // _LIBCPP_THREAD diff --git a/libcxx/include/tuple b/libcxx/include/tuple index b0616bd94da5..3542fafd4fb8 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -206,10 +206,18 @@ template <class... Types> #include <__compare/synth_three_way.h> #include <__config> #include <__functional/invoke.h> -#include <__functional/unwrap_ref.h> #include <__fwd/array.h> +#include <__fwd/get.h> +#include <__fwd/tuple.h> #include <__memory/allocator_arg_t.h> #include <__memory/uses_allocator.h> +#include <__tuple/make_tuple_types.h> +#include <__tuple/sfinae_helpers.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_indices.h> +#include <__tuple/tuple_like_ext.h> +#include <__tuple/tuple_size.h> +#include <__tuple/tuple_types.h> #include <__type_traits/apply_cv.h> #include <__type_traits/common_reference.h> #include <__type_traits/common_type.h> @@ -244,6 +252,7 @@ template <class... Types> #include <__type_traits/negation.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/remove_reference.h> +#include <__type_traits/unwrap_ref.h> #include <__utility/forward.h> #include <__utility/integer_sequence.h> #include <__utility/move.h> @@ -262,6 +271,9 @@ template <class... Types> # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_CXX03_LANG @@ -295,7 +307,7 @@ class __tuple_leaf _Hp __value_; template <class _Tp> - static constexpr bool __can_bind_reference() { + static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() { #if __has_keyword(__reference_binds_to_temporary) return !__reference_binds_to_temporary(_Hp, _Tp); #else @@ -367,8 +379,8 @@ public: {static_assert(!is_reference<_Hp>::value, "Attempted to uses-allocator construct a reference element in a tuple");} - __tuple_leaf(const __tuple_leaf& __t) = default; - __tuple_leaf(__tuple_leaf&& __t) = default; + _LIBCPP_HIDE_FROM_ABI __tuple_leaf(const __tuple_leaf& __t) = default; + _LIBCPP_HIDE_FROM_ABI __tuple_leaf(__tuple_leaf&& __t) = default; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 int swap(__tuple_leaf& __t) _NOEXCEPT_(__is_nothrow_swappable<__tuple_leaf>::value) @@ -865,7 +877,7 @@ public: : __base_(allocator_arg_t(), __a, __t) { } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 // tuple(tuple<U...>&) constructors (including allocator_arg_t variants) template <class... _Up, enable_if_t< @@ -879,7 +891,7 @@ public: _LIBCPP_HIDE_FROM_ABI constexpr explicit(!(is_convertible_v<_Up&, _Tp> && ...)) tuple(allocator_arg_t, const _Alloc& __alloc, tuple<_Up...>& __t) : __base_(allocator_arg_t(), __alloc, __t) {} -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 // tuple(tuple<U...>&&) constructors (including allocator_arg_t variants) @@ -929,7 +941,7 @@ public: : __base_(allocator_arg_t(), __a, _VSTD::move(__t)) { } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 // tuple(const tuple<U...>&&) constructors (including allocator_arg_t variants) template <class... _Up, enable_if_t< @@ -944,17 +956,17 @@ public: explicit(!(is_convertible_v<const _Up&&, _Tp> && ...)) tuple(allocator_arg_t, const _Alloc& __alloc, const tuple<_Up...>&& __t) : __base_(allocator_arg_t(), __alloc, std::move(__t)) {} -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 // tuple(const pair<U1, U2>&) constructors (including allocator_arg_t variants) - template <template <class...> class Pred, class _Pair, class _DecayedPair = __remove_cvref_t<_Pair>, class _Tuple = tuple> + template <template <class...> class _Pred, class _Pair, class _DecayedPair = __remove_cvref_t<_Pair>, class _Tuple = tuple> struct _CtorPredicateFromPair : false_type{}; - template <template <class...> class Pred, class _Pair, class _Up1, class _Up2, class _Tp1, class _Tp2> - struct _CtorPredicateFromPair<Pred, _Pair, pair<_Up1, _Up2>, tuple<_Tp1, _Tp2> > : _And< - Pred<_Tp1, __copy_cvref_t<_Pair, _Up1> >, - Pred<_Tp2, __copy_cvref_t<_Pair, _Up2> > + template <template <class...> class _Pred, class _Pair, class _Up1, class _Up2, class _Tp1, class _Tp2> + struct _CtorPredicateFromPair<_Pred, _Pair, pair<_Up1, _Up2>, tuple<_Tp1, _Tp2> > : _And< + _Pred<_Tp1, __copy_cvref_t<_Pair, _Up1> >, + _Pred<_Tp2, __copy_cvref_t<_Pair, _Up2> > > {}; template <class _Pair> @@ -1018,7 +1030,7 @@ public: : __base_(allocator_arg_t(), __a, __p) { } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 // tuple(pair<U1, U2>&) constructors (including allocator_arg_t variants) template <class _U1, class _U2, enable_if_t< @@ -1082,7 +1094,7 @@ public: : __base_(allocator_arg_t(), __a, _VSTD::move(__p)) { } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 // tuple(const pair<U1, U2>&&) constructors (including allocator_arg_t variants) template <class _U1, class _U2, enable_if_t< @@ -1097,7 +1109,7 @@ public: explicit(!_BothImplicitlyConvertible<const pair<_U1, _U2>&&>::value) tuple(allocator_arg_t, const _Alloc& __alloc, const pair<_U1, _U2>&& __p) : __base_(allocator_arg_t(), __alloc, std::move(__p)) {} -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 // [tuple.assign] _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 @@ -1109,7 +1121,7 @@ public: return *this; } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr const tuple& operator=(tuple const& __tuple) const requires (_And<is_copy_assignable<const _Tp>...>::value) { @@ -1126,7 +1138,7 @@ public: typename __make_tuple_indices<sizeof...(_Tp)>::type()); return *this; } -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple& operator=(_If<_And<is_move_assignable<_Tp>...>::value, tuple, __nat>&& __tuple) @@ -1170,7 +1182,7 @@ public: } -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class... _UTypes, enable_if_t< _And<_BoolConstant<sizeof...(_Tp) == sizeof...(_UTypes)>, is_assignable<const _Tp&, const _UTypes&>...>::value>* = nullptr> @@ -1193,17 +1205,17 @@ public: typename __make_tuple_indices<sizeof...(_Tp)>::type()); return *this; } -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 - template <template<class...> class Pred, bool _Const, + template <template<class...> class _Pred, bool _Const, class _Pair, class _DecayedPair = __remove_cvref_t<_Pair>, class _Tuple = tuple> struct _AssignPredicateFromPair : false_type {}; - template <template<class...> class Pred, bool _Const, + template <template<class...> class _Pred, bool _Const, class _Pair, class _Up1, class _Up2, class _Tp1, class _Tp2> - struct _AssignPredicateFromPair<Pred, _Const, _Pair, pair<_Up1, _Up2>, tuple<_Tp1, _Tp2> > : - _And<Pred<__maybe_const<_Const, _Tp1>&, __copy_cvref_t<_Pair, _Up1> >, - Pred<__maybe_const<_Const, _Tp2>&, __copy_cvref_t<_Pair, _Up2> > + struct _AssignPredicateFromPair<_Pred, _Const, _Pair, pair<_Up1, _Up2>, tuple<_Tp1, _Tp2> > : + _And<_Pred<__maybe_const<_Const, _Tp1>&, __copy_cvref_t<_Pair, _Up1> >, + _Pred<__maybe_const<_Const, _Tp2>&, __copy_cvref_t<_Pair, _Up2> > > {}; template <bool _Const, class _Pair> @@ -1212,7 +1224,7 @@ public: template <bool _Const, class _Pair> struct _NothrowAssignFromPair : _AssignPredicateFromPair<is_nothrow_assignable, _Const, _Pair> {}; -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class _U1, class _U2, enable_if_t< _EnableAssignFromPair<true, const pair<_U1, _U2>&>::value>* = nullptr> _LIBCPP_HIDE_FROM_ABI constexpr @@ -1232,7 +1244,7 @@ public: std::get<1>(*this) = std::move(__pair.second); return *this; } -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 template<class _Up1, class _Up2, __enable_if_t< _EnableAssignFromPair<false, pair<_Up1, _Up2> const&>::value @@ -1296,20 +1308,19 @@ public: void swap(tuple& __t) _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value) {__base_.swap(__t.__base_);} -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr void swap(const tuple& __t) const noexcept(__all<is_nothrow_swappable_v<const _Tp&>...>::value) { __base_.swap(__t.__base_); } -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 }; template <> class _LIBCPP_TEMPLATE_VIS tuple<> { public: - _LIBCPP_INLINE_VISIBILITY constexpr - tuple() _NOEXCEPT = default; + constexpr tuple() _NOEXCEPT = default; template <class _Alloc> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 tuple(allocator_arg_t, const _Alloc&) _NOEXCEPT {} @@ -1324,12 +1335,12 @@ public: tuple(allocator_arg_t, const _Alloc&, array<_Up, 0>) _NOEXCEPT {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(tuple&) _NOEXCEPT {} -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 _LIBCPP_HIDE_FROM_ABI constexpr void swap(const tuple&) const noexcept {} #endif }; -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class... _TTypes, class... _UTypes, template<class> class _TQual, template<class> class _UQual> requires requires { typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; } struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual> { @@ -1341,9 +1352,9 @@ template <class... _TTypes, class... _UTypes> struct common_type<tuple<_TTypes...>, tuple<_UTypes...>> { using type = tuple<common_type_t<_TTypes, _UTypes>...>; }; -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class ..._Tp> tuple(_Tp...) -> tuple<_Tp...>; template <class _Tp1, class _Tp2> @@ -1363,7 +1374,7 @@ swap(tuple<_Tp...>& __t, tuple<_Tp...>& __u) _NOEXCEPT_(__all<__is_nothrow_swappable<_Tp>::value...>::value) {__t.swap(__u);} -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 template <class... _Tp> _LIBCPP_HIDE_FROM_ABI constexpr enable_if_t<__all<is_swappable_v<const _Tp>...>::value, void> @@ -1413,7 +1424,7 @@ get(const tuple<_Tp...>&& __t) _NOEXCEPT static_cast<const __tuple_leaf<_Ip, type>&&>(__t.__base_).get()); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 namespace __find_detail { @@ -1501,9 +1512,13 @@ struct __ignore_t const __ignore_t& operator=(_Tp&&) const {return *this;} }; +# if _LIBCPP_STD_VER >= 17 +inline constexpr __ignore_t<unsigned char> ignore = __ignore_t<unsigned char>(); +# else namespace { constexpr __ignore_t<unsigned char> ignore = __ignore_t<unsigned char>(); } // namespace +# endif template <class... _Tp> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 @@ -1552,7 +1567,7 @@ operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) return __tuple_equal<sizeof...(_Tp)>()(__x, __y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 // operator<=> @@ -1574,7 +1589,7 @@ operator<=>(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) return _VSTD::__tuple_compare_three_way(__x, __y, index_sequence_for<_Tp...>{}); } -#else // _LIBCPP_STD_VER > 17 +#else // _LIBCPP_STD_VER >= 20 template <class ..._Tp, class ..._Up> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14 @@ -1644,7 +1659,7 @@ operator<=(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) return !(__y < __x); } -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 // tuple_cat @@ -1712,17 +1727,15 @@ template <class ..._Types, size_t ..._I0, class _Tuple0> struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>, _Tuple0> { typedef _LIBCPP_NODEBUG __libcpp_remove_reference_t<_Tuple0> _T0; - typedef tuple<_Types..., typename __apply_cv<_Tuple0, - typename tuple_element<_I0, _T0>::type>::type&&...> type; + typedef tuple<_Types..., __apply_cv_t<_Tuple0, typename tuple_element<_I0, _T0>::type>&&...> type; }; template <class ..._Types, size_t ..._I0, class _Tuple0, class _Tuple1, class ..._Tuples> struct __tuple_cat_return_ref_imp<tuple<_Types...>, __tuple_indices<_I0...>, _Tuple0, _Tuple1, _Tuples...> : public __tuple_cat_return_ref_imp< - tuple<_Types..., typename __apply_cv<_Tuple0, - typename tuple_element<_I0, - __libcpp_remove_reference_t<_Tuple0> >::type>::type&&...>, + tuple<_Types..., __apply_cv_t<_Tuple0, + typename tuple_element<_I0, __libcpp_remove_reference_t<_Tuple0>>::type>&&...>, typename __make_tuple_indices<tuple_size<__libcpp_remove_reference_t<_Tuple1> >::value>::type, _Tuple1, _Tuples...> { @@ -1762,13 +1775,9 @@ struct __tuple_cat<tuple<_Types...>, __tuple_indices<_I0...>, __tuple_indices<_J (void)__t; // avoid unused parameter warning on GCC when _I0 is empty typedef _LIBCPP_NODEBUG __libcpp_remove_reference_t<_Tuple0> _T0; typedef _LIBCPP_NODEBUG __libcpp_remove_reference_t<_Tuple1> _T1; - return __tuple_cat< - tuple<_Types..., - typename __apply_cv<_Tuple0, typename tuple_element< - _J0, _T0>::type>::type&&...>, - typename __make_tuple_indices<sizeof...(_Types) + - tuple_size<_T0>::value>::type, - typename __make_tuple_indices<tuple_size<_T1>::value>::type>()( + return __tuple_cat<tuple<_Types..., __apply_cv_t<_Tuple0, typename tuple_element<_J0, _T0>::type>&&...>, + typename __make_tuple_indices<sizeof...(_Types) + tuple_size<_T0>::value>::type, + typename __make_tuple_indices<tuple_size<_T1>::value>::type>()( _VSTD::forward_as_tuple( _VSTD::forward<_Types>(_VSTD::get<_I0>(__t))..., _VSTD::get<_J0>(_VSTD::forward<_Tuple0>(__t0))...), @@ -1803,7 +1812,7 @@ pair<_T1, _T2>::pair(piecewise_construct_t, { } -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class _Tp> inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; @@ -1845,12 +1854,14 @@ _LIBCPP_NOEXCEPT_RETURN( #undef _LIBCPP_NOEXCEPT_RETURN -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 #endif // !defined(_LIBCPP_CXX03_LANG) _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <exception> # include <iosfwd> diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index 7646f5805980..466aeb6e0ddd 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -51,7 +51,7 @@ namespace std template <class T> struct is_arithmetic; template <class T> struct is_fundamental; template <class T> struct is_member_pointer; - template <class T> struct is_scoped_enum; // C++2b + template <class T> struct is_scoped_enum; // C++23 template <class T> struct is_scalar; template <class T> struct is_object; template <class T> struct is_compound; @@ -286,7 +286,7 @@ namespace std template <class T> inline constexpr bool is_member_pointer_v = is_member_pointer<T>::value; // C++17 template <class T> inline constexpr bool is_scoped_enum_v - = is_scoped_enum<T>::value; // C++2b + = is_scoped_enum<T>::value; // C++23 // See C++14 20.10.4.3, type properties template <class T> inline constexpr bool is_const_v @@ -418,7 +418,6 @@ namespace std */ #include <__assert> // all public C++ headers provide the assertion handler #include <__config> -#include <__functional/invoke.h> #include <__fwd/hash.h> // This is https://llvm.org/PR56938 #include <__type_traits/add_const.h> #include <__type_traits/add_cv.h> @@ -443,6 +442,7 @@ namespace std #include <__type_traits/has_unique_object_representation.h> #include <__type_traits/has_virtual_destructor.h> #include <__type_traits/integral_constant.h> +#include <__type_traits/invoke.h> #include <__type_traits/is_abstract.h> #include <__type_traits/is_aggregate.h> #include <__type_traits/is_arithmetic.h> @@ -532,6 +532,7 @@ namespace std #include <__type_traits/result_of.h> #include <__type_traits/type_identity.h> #include <__type_traits/underlying_type.h> +#include <__type_traits/unwrap_ref.h> #include <__type_traits/void_t.h> #include <__utility/declval.h> #include <cstddef> diff --git a/libcxx/include/typeindex b/libcxx/include/typeindex index e3132c8cb856..251aa430610c 100644 --- a/libcxx/include/typeindex +++ b/libcxx/include/typeindex @@ -87,7 +87,7 @@ public: _LIBCPP_INLINE_VISIBILITY bool operator>=(const type_index& __y) const _NOEXCEPT {return !__t_->before(*__y.__t_);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(const type_index& __y) const noexcept { if (*__t_ == *__y.__t_) diff --git a/libcxx/include/typeinfo b/libcxx/include/typeinfo index 443103939849..0dc9f09b9e25 100644 --- a/libcxx/include/typeinfo +++ b/libcxx/include/typeinfo @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef __LIBCPP_TYPEINFO -#define __LIBCPP_TYPEINFO +#ifndef _LIBCPP_TYPEINFO +#define _LIBCPP_TYPEINFO /* @@ -21,7 +21,7 @@ class type_info public: virtual ~type_info(); - bool operator==(const type_info& rhs) const noexcept; + bool operator==(const type_info& rhs) const noexcept; // constexpr since C++23 bool operator!=(const type_info& rhs) const noexcept; // removed in C++20 bool before(const type_info& rhs) const noexcept; @@ -59,11 +59,11 @@ public: #include <__assert> // all public C++ headers provide the assertion handler #include <__availability> #include <__config> +#include <__exception/exception.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__verbose_abort> #include <cstddef> #include <cstdint> -#include <cstdlib> -#include <exception> -#include <type_traits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -79,7 +79,7 @@ namespace std // purposefully not using versioning namespace #if defined(_LIBCPP_ABI_MICROSOFT) -class _LIBCPP_EXCEPTION_ABI type_info +class _LIBCPP_EXPORTED_FROM_ABI type_info { type_info& operator=(const type_info&); type_info(const type_info&); @@ -104,8 +104,13 @@ public: size_t hash_code() const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const type_info& __arg) const _NOEXCEPT { + // When evaluated in a constant expression, both type infos simply can't come + // from different translation units, so it is sufficient to compare their addresses. + if (__libcpp_is_constant_evaluated()) { + return this == &__arg; + } return __compare(__arg) == 0; } @@ -294,7 +299,7 @@ struct __type_info_implementations { __impl; }; -class _LIBCPP_EXCEPTION_ABI type_info +class _LIBCPP_EXPORTED_FROM_ABI type_info { type_info& operator=(const type_info&); type_info(const type_info&); @@ -330,9 +335,14 @@ public: return __impl::__hash(__type_name); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const type_info& __arg) const _NOEXCEPT { + // When evaluated in a constant expression, both type infos simply can't come + // from different translation units, so it is sufficient to compare their addresses. + if (__libcpp_is_constant_evaluated()) { + return this == &__arg; + } return __impl::__eq(__type_name, __arg.__type_name); } @@ -344,17 +354,17 @@ public: }; #endif // defined(_LIBCPP_ABI_MICROSOFT) -class _LIBCPP_EXCEPTION_ABI bad_cast +class _LIBCPP_EXPORTED_FROM_ABI bad_cast : public exception { public: bad_cast() _NOEXCEPT; - bad_cast(const bad_cast&) _NOEXCEPT = default; + _LIBCPP_HIDE_FROM_ABI bad_cast(const bad_cast&) _NOEXCEPT = default; ~bad_cast() _NOEXCEPT override; const char* what() const _NOEXCEPT override; }; -class _LIBCPP_EXCEPTION_ABI bad_typeid +class _LIBCPP_EXPORTED_FROM_ABI bad_typeid : public exception { public: @@ -395,12 +405,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_cast() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_cast(); #else - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("bad_cast was thrown in -fno-exceptions mode"); #endif } _LIBCPP_END_NAMESPACE_STD -#endif // __LIBCPP_TYPEINFO +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstdlib> +# include <exception> +# include <type_traits> +#endif + +#endif // _LIBCPP_TYPEINFO diff --git a/libcxx/include/uchar.h b/libcxx/include/uchar.h index 3a51bb7a9f61..546113f7eab4 100644 --- a/libcxx/include/uchar.h +++ b/libcxx/include/uchar.h @@ -42,10 +42,12 @@ size_t c32rtomb(char* s, char32_t c32, mbstate_t* ps); // Some platforms don't implement <uchar.h> and we don't want to give a hard // error on those platforms. When the platform doesn't provide <uchar.h>, at -// least include <stddef.h> so we get the declaration for size_t. +// least include <stddef.h> so we get the declaration for size_t, and try to +// get the declaration of mbstate_t too. #if __has_include_next(<uchar.h>) # include_next <uchar.h> #else +# include <__mbstate_t.h> # include <stddef.h> #endif diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map index 14f93bab36e1..8d83063bbeae 100644 --- a/libcxx/include/unordered_map +++ b/libcxx/include/unordered_map @@ -59,6 +59,11 @@ public: size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<container-compatible-range<value_type> R> + unordered_map(from_range_t, R&& rg, size_type n = see below, + const hasher& hf = hasher(), const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); // C++23 + explicit unordered_map(const allocator_type&); unordered_map(const unordered_map&); unordered_map(const unordered_map&, const Allocator&); @@ -82,6 +87,12 @@ public: unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(f, l, n, hf, key_equal(), a) {} // C++14 + template<container-compatible-range<value_type> R> + unordered_map(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_map(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } // C++23 + template<container-compatible-range<value_type> R> + unordered_map(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) + : unordered_map(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { } // C++23 unordered_map(initializer_list<value_type> il, size_type n, const allocator_type& a) : unordered_map(il, n, hasher(), key_equal(), a) {} // C++14 unordered_map(initializer_list<value_type> il, size_type n, const hasher& hf, @@ -122,6 +133,8 @@ public: iterator insert(const_iterator hint, P&& obj); template <class InputIterator> void insert(InputIterator first, InputIterator last); + template<container-compatible-range<value_type> R> + void insert_range(R&& rg); // C++23 void insert(initializer_list<value_type>); node_type extract(const_iterator position); // C++17 @@ -224,6 +237,13 @@ unordered_map(InputIterator, InputIterator, typename see below::size_type = see -> unordered_map<iter_key_t<InputIterator>, iter_value_t<InputIterator>, Hash, Pred, Allocator>; // C++17 +template<ranges::input_range R, class Hash = hash<range-key-type<R>>, + class Pred = equal_to<range-key-type<R>>, + class Allocator = allocator<range-to-alloc-type<R>>> + unordered_map(from_range_t, R&&, typename see below::size_type = see below, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_map<range-key-type<R>, range-mapped-type<R>, Hash, Pred, Allocator>; // C++23 + template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>> unordered_map(initializer_list<pair<const Key, T>>, typename see below::size_type = see below, @@ -245,6 +265,21 @@ unordered_map(InputIterator, InputIterator, typename see below::size_type, Hash, -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Hash, equal_to<iter_key_t<InputIterator>>, Allocator>; // C++17 +template<ranges::input_range R, class Allocator> + unordered_map(from_range_t, R&&, typename see below::size_type, Allocator) + -> unordered_map<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>, + equal_to<range-key-type<R>>, Allocator>; // C++23 + +template<ranges::input_range R, class Allocator> + unordered_map(from_range_t, R&&, Allocator) + -> unordered_map<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>, + equal_to<range-key-type<R>>, Allocator>; // C++23 + +template<ranges::input_range R, class Hash, class Allocator> + unordered_map(from_range_t, R&&, typename see below::size_type, Hash, Allocator) + -> unordered_map<range-key-type<R>, range-mapped-type<R>, Hash, + equal_to<range-key-type<R>>, Allocator>; // C++23 + template<class Key, class T, typename Allocator> unordered_map(initializer_list<pair<const Key, T>>, typename see below::size_type, Allocator) -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>; // C++17 @@ -270,7 +305,7 @@ template <class Key, class T, class Hash, class Pred, class Alloc> template <class Key, class T, class Hash, class Pred, class Alloc> bool operator!=(const unordered_map<Key, T, Hash, Pred, Alloc>& x, - const unordered_map<Key, T, Hash, Pred, Alloc>& y); + const unordered_map<Key, T, Hash, Pred, Alloc>& y); // Removed in C++20 template <class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Alloc = allocator<pair<const Key, T>>> @@ -311,6 +346,10 @@ public: size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<container-compatible-range<value_type> R> + unordered_multimap(from_range_t, R&& rg, size_type n = see below, + const hasher& hf = hasher(), const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); // C++23 explicit unordered_multimap(const allocator_type&); unordered_multimap(const unordered_multimap&); unordered_multimap(const unordered_multimap&, const Allocator&); @@ -334,6 +373,12 @@ public: unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(f, l, n, hf, key_equal(), a) {} // C++14 + template<container-compatible-range<value_type> R> + unordered_multimap(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_multimap(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } // C++23 + template<container-compatible-range<value_type> R> + unordered_multimap(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) + : unordered_multimap(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { } // C++23 unordered_multimap(initializer_list<value_type> il, size_type n, const allocator_type& a) : unordered_multimap(il, n, hasher(), key_equal(), a) {} // C++14 unordered_multimap(initializer_list<value_type> il, size_type n, const hasher& hf, @@ -374,6 +419,8 @@ public: iterator insert(const_iterator hint, P&& obj); template <class InputIterator> void insert(InputIterator first, InputIterator last); + template<container-compatible-range<value_type> R> + void insert_range(R&& rg); // C++23 void insert(initializer_list<value_type>); node_type extract(const_iterator position); // C++17 @@ -453,6 +500,13 @@ unordered_multimap(InputIterator, InputIterator, typename see below::size_type = -> unordered_multimap<iter_key_t<InputIterator>, iter_value_t<InputIterator>, Hash, Pred, Allocator>; // C++17 +template<ranges::input_range R, class Hash = hash<range-key-type<R>>, + class Pred = equal_to<range-key-type<R>>, + class Allocator = allocator<range-to-alloc-type<R>>> + unordered_multimap(from_range_t, R&&, typename see below::size_type = see below, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, Hash, Pred, Allocator>; // C++23 + template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>> unordered_multimap(initializer_list<pair<const Key, T>>, typename see below::size_type = see below, @@ -474,6 +528,21 @@ unordered_multimap(InputIterator, InputIterator, typename see below::size_type, -> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Hash, equal_to<iter_key_t<InputIterator>>, Allocator>; // C++17 +template<ranges::input_range R, class Allocator> + unordered_multimap(from_range_t, R&&, typename see below::size_type, Allocator) + -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>, + equal_to<range-key-type<R>>, Allocator>; // C++23 + +template<ranges::input_range R, class Allocator> + unordered_multimap(from_range_t, R&&, Allocator) + -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>, + equal_to<range-key-type<R>>, Allocator>; // C++23 + +template<ranges::input_range R, class Hash, class Allocator> + unordered_multimap(from_range_t, R&&, typename see below::size_type, Hash, Allocator) + -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, Hash, + equal_to<range-key-type<R>>, Allocator>; // C++23 + template<class Key, class T, typename Allocator> unordered_multimap(initializer_list<pair<const Key, T>>, typename see below::size_type, Allocator) -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>; // C++17 @@ -508,7 +577,7 @@ template <class Key, class T, class Hash, class Pred, class Alloc> template <class Key, class T, class Hash, class Pred, class Alloc> bool operator!=(const unordered_multimap<Key, T, Hash, Pred, Alloc>& x, - const unordered_multimap<Key, T, Hash, Pred, Alloc>& y); + const unordered_multimap<Key, T, Hash, Pred, Alloc>& y); // Removed in C++20 } // std @@ -516,19 +585,24 @@ template <class Key, class T, class Hash, class Pred, class Alloc> #include <__algorithm/is_permutation.h> #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> #include <__config> -#include <__debug> #include <__functional/is_transparent.h> #include <__functional/operations.h> #include <__hash_table> #include <__iterator/distance.h> #include <__iterator/erase_if_container.h> #include <__iterator/iterator_traits.h> +#include <__iterator/ranges_iterator_traits.h> #include <__memory/addressof.h> #include <__memory/allocator.h> #include <__memory_resource/polymorphic_allocator.h> #include <__node_handle> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> #include <__type_traits/is_allocator.h> +#include <__type_traits/type_identity.h> #include <__utility/forward.h> #include <stdexcept> #include <tuple> @@ -575,7 +649,7 @@ public: _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Key& __x) const {return static_cast<const _Hash&>(*this)(__x);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <typename _K2> _LIBCPP_INLINE_VISIBILITY size_t operator()(const _K2& __x) const @@ -611,7 +685,7 @@ public: _LIBCPP_INLINE_VISIBILITY size_t operator()(const _Key& __x) const {return __hash_(__x);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <typename _K2> _LIBCPP_INLINE_VISIBILITY size_t operator()(const _K2& __x) const @@ -661,7 +735,7 @@ public: _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _Cp& __y) const {return static_cast<const _Pred&>(*this)(__x, __y.__get_value().first);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <typename _K2> _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _K2& __y) const @@ -712,7 +786,7 @@ public: _LIBCPP_INLINE_VISIBILITY bool operator()(const _Key& __x, const _Cp& __y) const {return __pred_(__x, __y.__get_value().first);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <typename _K2> _LIBCPP_INLINE_VISIBILITY bool operator()(const _Cp& __x, const _K2& __y) const @@ -825,7 +899,7 @@ public: _LIBCPP_INLINE_VISIBILITY value_type& __get_value() { -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return *_VSTD::launder(_VSTD::addressof(__cc_)); #else return __cc_; @@ -835,7 +909,7 @@ public: _LIBCPP_INLINE_VISIBILITY const value_type& __get_value() const { -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return *_VSTD::launder(_VSTD::addressof(__cc_)); #else return __cc_; @@ -953,9 +1027,11 @@ public: friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {return __x.__i_ == __y.__i_;} +#if _LIBCPP_STD_VER <= 17 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_map_iterator& __x, const __hash_map_iterator& __y) {return __x.__i_ != __y.__i_;} +#endif template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_map; template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; @@ -1007,9 +1083,11 @@ public: friend _LIBCPP_INLINE_VISIBILITY bool operator==(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {return __x.__i_ == __y.__i_;} +#if _LIBCPP_STD_VER <= 17 friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const __hash_map_const_iterator& __x, const __hash_map_const_iterator& __y) {return __x.__i_ != __y.__i_;} +#endif template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_map; template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_multimap; @@ -1035,7 +1113,7 @@ public: typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same<value_type, typename allocator_type::value_type>::value), - "Invalid allocator::value_type"); + "Allocator::value_type must be same type as value_type"); private: typedef __hash_value_type<key_type, mapped_type> __value_type; @@ -1075,7 +1153,7 @@ public: typedef __hash_map_iterator<typename __table::local_iterator> local_iterator; typedef __hash_map_const_iterator<typename __table::const_local_iterator> const_local_iterator; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef __map_node_handle<__node, allocator_type> node_type; typedef __insert_return_type<iterator, node_type> insert_return_type; #endif @@ -1089,41 +1167,55 @@ public: unordered_map() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { - _VSTD::__debug_db_insert_c(this); } - explicit unordered_map(size_type __n, const hasher& __hf = hasher(), + explicit _LIBCPP_HIDE_FROM_ABI unordered_map(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - unordered_map(size_type __n, const hasher& __hf, + _LIBCPP_HIDE_FROM_ABI unordered_map(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template <class _InputIterator> - unordered_map(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI unordered_map(_InputIterator __first, _InputIterator __last); template <class _InputIterator> - unordered_map(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template <class _InputIterator> - unordered_map(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_map(from_range_t, _Range&& __range, size_type __n = /*implementation-defined*/0, + const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : __table_(__hf, __eql, typename __table::allocator_type(__a)) { + if (__n > 0) { + __table_.__rehash_unique(__n); + } + insert_range(std::forward<_Range>(__range)); + } +#endif + _LIBCPP_INLINE_VISIBILITY explicit unordered_map(const allocator_type& __a); - unordered_map(const unordered_map& __u); - unordered_map(const unordered_map& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI unordered_map(const unordered_map& __u); + _LIBCPP_HIDE_FROM_ABI unordered_map(const unordered_map& __u, const allocator_type& __a); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY unordered_map(unordered_map&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value); - unordered_map(unordered_map&& __u, const allocator_type& __a); - unordered_map(initializer_list<value_type> __il); - unordered_map(initializer_list<value_type> __il, size_type __n, + _LIBCPP_HIDE_FROM_ABI unordered_map(unordered_map&& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI unordered_map(initializer_list<value_type> __il); + _LIBCPP_HIDE_FROM_ABI unordered_map(initializer_list<value_type> __il, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - unordered_map(initializer_list<value_type> __il, size_type __n, + _LIBCPP_HIDE_FROM_ABI unordered_map(initializer_list<value_type> __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); #endif // _LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _LIBCPP_INLINE_VISIBILITY unordered_map(size_type __n, const allocator_type& __a) : unordered_map(__n, hasher(), key_equal(), __a) {} @@ -1139,6 +1231,19 @@ public: unordered_map(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_map(__first, __last, __n, __hf, key_equal(), __a) {} + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_map(from_range_t, _Range&& __range, size_type __n, const allocator_type& __a) + : unordered_map(from_range, std::forward<_Range>(__range), __n, hasher(), key_equal(), __a) {} + + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_map(from_range_t, _Range&& __range, size_type __n, const hasher& __hf, const allocator_type& __a) + : unordered_map(from_range, std::forward<_Range>(__range), __n, __hf, key_equal(), __a) {} +#endif + _LIBCPP_INLINE_VISIBILITY unordered_map(initializer_list<value_type> __il, size_type __n, const allocator_type& __a) : unordered_map(__il, __n, hasher(), key_equal(), __a) {} @@ -1205,11 +1310,7 @@ public: pair<iterator, bool> insert(const value_type& __x) {return __table_.__insert_unique(__x);} - iterator insert(const_iterator __p, const value_type& __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "unordered_map::insert(const_iterator, const value_type&) called with an iterator not " - "referring to this unordered_map"); - ((void)__p); + _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator, const value_type& __x) { return insert(__x).first; } @@ -1217,6 +1318,16 @@ public: _LIBCPP_INLINE_VISIBILITY void insert(_InputIterator __first, _InputIterator __last); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + void insert_range(_Range&& __range) { + for (auto&& __element : __range) { + __table_.__insert_unique(std::forward<decltype(__element)>(__element)); + } + } +#endif + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void insert(initializer_list<value_type> __il) @@ -1226,11 +1337,7 @@ public: pair<iterator, bool> insert(value_type&& __x) {return __table_.__insert_unique(_VSTD::move(__x));} - iterator insert(const_iterator __p, value_type&& __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "unordered_map::insert(const_iterator, const value_type&) called with an iterator not" - " referring to this unordered_map"); - ((void)__p); + _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator, value_type&& __x) { return __table_.__insert_unique(_VSTD::move(__x)).first; } @@ -1243,12 +1350,8 @@ public: template <class _Pp, class = __enable_if_t<is_constructible<value_type, _Pp>::value> > _LIBCPP_INLINE_VISIBILITY - iterator insert(const_iterator __p, _Pp&& __x) + iterator insert(const_iterator, _Pp&& __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "unordered_map::insert(const_iterator, value_type&&) called with an iterator not" - " referring to this unordered_map"); - ((void)__p); return insert(_VSTD::forward<_Pp>(__x)).first; } @@ -1260,17 +1363,13 @@ public: template <class... _Args> _LIBCPP_INLINE_VISIBILITY - iterator emplace_hint(const_iterator __p, _Args&&... __args) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__p)) == this, - "unordered_map::emplace_hint(const_iterator, args...) called with an iterator not" - " referring to this unordered_map"); - ((void)__p); + iterator emplace_hint(const_iterator, _Args&&... __args) { return __table_.__emplace_unique(_VSTD::forward<_Args>(__args)...).first; } #endif // _LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template <class... _Args> _LIBCPP_INLINE_VISIBILITY pair<iterator, bool> try_emplace(const key_type& __k, _Args&&... __args) @@ -1291,23 +1390,15 @@ public: template <class... _Args> _LIBCPP_INLINE_VISIBILITY - iterator try_emplace(const_iterator __h, const key_type& __k, _Args&&... __args) + iterator try_emplace(const_iterator, const key_type& __k, _Args&&... __args) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__h)) == this, - "unordered_map::try_emplace(const_iterator, key, args...) called with an iterator not" - " referring to this unordered_map"); - ((void)__h); return try_emplace(__k, _VSTD::forward<_Args>(__args)...).first; } template <class... _Args> _LIBCPP_INLINE_VISIBILITY - iterator try_emplace(const_iterator __h, key_type&& __k, _Args&&... __args) + iterator try_emplace(const_iterator, key_type&& __k, _Args&&... __args) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__h)) == this, - "unordered_map::try_emplace(const_iterator, key, args...) called with an iterator not" - " referring to this unordered_map"); - ((void)__h); return try_emplace(_VSTD::move(__k), _VSTD::forward<_Args>(__args)...).first; } @@ -1339,7 +1430,6 @@ public: _LIBCPP_INLINE_VISIBILITY iterator insert_or_assign(const_iterator, const key_type& __k, _Vp&& __v) { - // FIXME: Add debug mode checking for the iterator input return insert_or_assign(__k, _VSTD::forward<_Vp>(__v)).first; } @@ -1347,10 +1437,9 @@ public: _LIBCPP_INLINE_VISIBILITY iterator insert_or_assign(const_iterator, key_type&& __k, _Vp&& __v) { - // FIXME: Add debug mode checking for the iterator input return insert_or_assign(_VSTD::move(__k), _VSTD::forward<_Vp>(__v)).first; } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __p) {return __table_.erase(__p.__i_);} @@ -1364,11 +1453,11 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__table_.clear();} -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY insert_return_type insert(node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_map::insert()"); return __table_.template __node_handle_insert_unique< node_type, insert_return_type>(_VSTD::move(__nh)); @@ -1376,7 +1465,7 @@ public: _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __hint, node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_map::insert()"); return __table_.template __node_handle_insert_unique<node_type>( __hint.__i_, _VSTD::move(__nh)); @@ -1397,32 +1486,32 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(unordered_map<key_type, mapped_type, _H2, _P2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_unique(__source.__table_); } template <class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_map<key_type, mapped_type, _H2, _P2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_unique(__source.__table_); } template <class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_multimap<key_type, mapped_type, _H2, _P2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_unique(__source.__table_); } template <class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_multimap<key_type, mapped_type, _H2, _P2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_unique(__source.__table_); } #endif @@ -1443,31 +1532,31 @@ public: iterator find(const key_type& __k) {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __table_.find(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY iterator find(const _K2& __k) {return __table_.find(__k);} template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY const_iterator find(const _K2& __k) const {return __table_.find(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY size_type count(const _K2& __k) const {return __table_.__count_unique(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY bool contains(const _K2& __k) const {return find(__k) != end();} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY pair<iterator, iterator> equal_range(const key_type& __k) @@ -1475,7 +1564,7 @@ public: _LIBCPP_INLINE_VISIBILITY pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {return __table_.__equal_range_unique(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY pair<iterator, iterator> equal_range(const _K2& __k) @@ -1484,15 +1573,15 @@ public: _LIBCPP_INLINE_VISIBILITY pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {return __table_.__equal_range_unique(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 - mapped_type& operator[](const key_type& __k); + _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __k); #ifndef _LIBCPP_CXX03_LANG - mapped_type& operator[](key_type&& __k); + _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __k); #endif - mapped_type& at(const key_type& __k); - const mapped_type& at(const key_type& __k) const; + _LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __k); + _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __k) const; _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const _NOEXCEPT {return __table_.bucket_count();} @@ -1529,23 +1618,10 @@ public: _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.__reserve_unique(__n);} -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - bool __dereferenceable(const const_iterator* __i) const - {return __table_.__dereferenceable(_VSTD::addressof(__i->__i_));} - bool __decrementable(const const_iterator* __i) const - {return __table_.__decrementable(_VSTD::addressof(__i->__i_));} - bool __addable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(_VSTD::addressof(__i->__i_), __n);} - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(_VSTD::addressof(__i->__i_), __n);} - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - private: #ifdef _LIBCPP_CXX03_LANG - __node_holder __construct_node_with_key(const key_type& __k); + _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_with_key(const key_type& __k); #endif }; @@ -1554,7 +1630,7 @@ template<class _InputIterator, class _Hash = hash<__iter_key_type<_InputIterator>>, class _Pred = equal_to<__iter_key_type<_InputIterator>>, class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Hash>::value>, class = enable_if_t<!is_integral<_Hash>::value>, class = enable_if_t<!__is_allocator<_Pred>::value>, @@ -1563,6 +1639,20 @@ unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocat _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Hash, _Pred, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, + class _Hash = hash<__range_key_type<_Range>>, + class _Pred = equal_to<__range_key_type<_Range>>, + class _Allocator = allocator<__range_to_alloc_type<_Range>>, + class = enable_if_t<!__is_allocator<_Hash>::value>, + class = enable_if_t<!is_integral<_Hash>::value>, + class = enable_if_t<!__is_allocator<_Pred>::value>, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_map(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map<__range_key_type<_Range>, __range_mapped_type<_Range>, _Hash, _Pred, _Allocator>; // C++23 +#endif + template<class _Key, class _Tp, class _Hash = hash<remove_const_t<_Key>>, class _Pred = equal_to<remove_const_t<_Key>>, class _Allocator = allocator<pair<const _Key, _Tp>>, @@ -1575,21 +1665,21 @@ unordered_map(initializer_list<pair<_Key, _Tp>>, typename allocator_traits<_Allo -> unordered_map<remove_const_t<_Key>, _Tp, _Hash, _Pred, _Allocator>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_map(_InputIterator, _InputIterator, _Allocator) -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; template<class _InputIterator, class _Hash, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Hash>::value>, class = enable_if_t<!is_integral<_Hash>::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> @@ -1597,6 +1687,30 @@ unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocat -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Hash, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; +#if _LIBCPP_STD_VER >= 23 + +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_map(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_map<__range_key_type<_Range>, __range_mapped_type<_Range>, hash<__range_key_type<_Range>>, + equal_to<__range_key_type<_Range>>, _Allocator>; + +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_map(from_range_t, _Range&&, _Allocator) + -> unordered_map<__range_key_type<_Range>, __range_mapped_type<_Range>, hash<__range_key_type<_Range>>, + equal_to<__range_key_type<_Range>>, _Allocator>; + +template <ranges::input_range _Range, class _Hash, class _Allocator, + class = enable_if_t<!__is_allocator<_Hash>::value>, + class = enable_if_t<!is_integral<_Hash>::value>, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_map(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_map<__range_key_type<_Range>, __range_mapped_type<_Range>, _Hash, + equal_to<__range_key_type<_Range>>, _Allocator>; + +#endif + template<class _Key, class _Tp, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_map(initializer_list<pair<_Key, _Tp>>, typename allocator_traits<_Allocator>::size_type, _Allocator) @@ -1625,7 +1739,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); } @@ -1635,7 +1748,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); } @@ -1645,7 +1757,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const allocator_type& __a) : __table_(typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); } template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> @@ -1653,7 +1764,6 @@ template <class _InputIterator> unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( _InputIterator __first, _InputIterator __last) { - _VSTD::__debug_db_insert_c(this); insert(__first, __last); } @@ -1664,7 +1774,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__first, __last); } @@ -1676,7 +1785,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__first, __last); } @@ -1686,7 +1794,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const unordered_map& __u) : __table_(__u.__table_) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -1696,7 +1803,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const unordered_map& __u, const allocator_type& __a) : __table_(__u.__table_, typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -1710,8 +1816,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { - _VSTD::__debug_db_insert_c(this); - std::__debug_db_swap(this, std::addressof(__u)); } template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> @@ -1719,7 +1823,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( unordered_map&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); if (__a != __u.get_allocator()) { iterator __i = __u.begin(); @@ -1728,15 +1831,12 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( __u.__table_.remove((__i++).__i_)->__value_.__move()); } } - else - std::__debug_db_swap(this, std::addressof(__u)); } template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( initializer_list<value_type> __il) { - _VSTD::__debug_db_insert_c(this); insert(__il.begin(), __il.end()); } @@ -1746,7 +1846,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__il.begin(), __il.end()); } @@ -1757,7 +1856,6 @@ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__il.begin(), __il.end()); } @@ -1874,7 +1972,7 @@ swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY @@ -1904,6 +2002,8 @@ operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, return true; } +#if _LIBCPP_STD_VER <= 17 + template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY bool @@ -1913,6 +2013,8 @@ operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, return !(__x == __y); } +#endif + template <class _Key, class _Tp, class _Hash = hash<_Key>, class _Pred = equal_to<_Key>, class _Alloc = allocator<pair<const _Key, _Tp> > > class _LIBCPP_TEMPLATE_VIS unordered_multimap @@ -1928,7 +2030,7 @@ public: typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same<value_type, typename allocator_type::value_type>::value), - "Invalid allocator::value_type"); + "Allocator::value_type must be same type as value_type"); private: typedef __hash_value_type<key_type, mapped_type> __value_type; @@ -1967,7 +2069,7 @@ private: typedef __hash_map_iterator<typename __table::local_iterator> local_iterator; typedef __hash_map_const_iterator<typename __table::const_local_iterator> const_local_iterator; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef __map_node_handle<__node, allocator_type> node_type; #endif @@ -1980,42 +2082,56 @@ private: unordered_multimap() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { - _VSTD::__debug_db_insert_c(this); } - explicit unordered_multimap(size_type __n, const hasher& __hf = hasher(), + explicit _LIBCPP_HIDE_FROM_ABI unordered_multimap(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - unordered_multimap(size_type __n, const hasher& __hf, + _LIBCPP_HIDE_FROM_ABI unordered_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template <class _InputIterator> - unordered_multimap(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI unordered_multimap(_InputIterator __first, _InputIterator __last); template <class _InputIterator> - unordered_multimap(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template <class _InputIterator> - unordered_multimap(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_multimap(from_range_t, _Range&& __range, size_type __n = /*implementation-defined*/0, + const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : __table_(__hf, __eql, typename __table::allocator_type(__a)) { + if (__n > 0) { + __table_.__rehash_multi(__n); + } + insert_range(std::forward<_Range>(__range)); + } +#endif + _LIBCPP_INLINE_VISIBILITY explicit unordered_multimap(const allocator_type& __a); - unordered_multimap(const unordered_multimap& __u); - unordered_multimap(const unordered_multimap& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI unordered_multimap(const unordered_multimap& __u); + _LIBCPP_HIDE_FROM_ABI unordered_multimap(const unordered_multimap& __u, const allocator_type& __a); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY unordered_multimap(unordered_multimap&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value); - unordered_multimap(unordered_multimap&& __u, const allocator_type& __a); - unordered_multimap(initializer_list<value_type> __il); - unordered_multimap(initializer_list<value_type> __il, size_type __n, + _LIBCPP_HIDE_FROM_ABI unordered_multimap(unordered_multimap&& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI unordered_multimap(initializer_list<value_type> __il); + _LIBCPP_HIDE_FROM_ABI unordered_multimap(initializer_list<value_type> __il, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - unordered_multimap(initializer_list<value_type> __il, size_type __n, + _LIBCPP_HIDE_FROM_ABI unordered_multimap(initializer_list<value_type> __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); #endif // _LIBCPP_CXX03_LANG -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _LIBCPP_INLINE_VISIBILITY unordered_multimap(size_type __n, const allocator_type& __a) : unordered_multimap(__n, hasher(), key_equal(), __a) {} @@ -2031,6 +2147,19 @@ private: unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a) {} + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_multimap(from_range_t, _Range&& __range, size_type __n, const allocator_type& __a) + : unordered_multimap(from_range, std::forward<_Range>(__range), __n, hasher(), key_equal(), __a) {} + + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_multimap(from_range_t, _Range&& __range, size_type __n, const hasher& __hf, const allocator_type& __a) + : unordered_multimap(from_range, std::forward<_Range>(__range), __n, __hf, key_equal(), __a) {} +#endif + _LIBCPP_INLINE_VISIBILITY unordered_multimap(initializer_list<value_type> __il, size_type __n, const allocator_type& __a) : unordered_multimap(__il, __n, hasher(), key_equal(), __a) {} @@ -2104,6 +2233,16 @@ private: _LIBCPP_INLINE_VISIBILITY void insert(_InputIterator __first, _InputIterator __last); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + void insert_range(_Range&& __range) { + for (auto&& __element : __range) { + __table_.__insert_multi(std::forward<decltype(__element)>(__element)); + } + } +#endif + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY void insert(initializer_list<value_type> __il) @@ -2128,12 +2267,12 @@ private: {return __table_.__insert_multi(__p.__i_, _VSTD::forward<_Pp>(__x));} template <class... _Args> - iterator emplace(_Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) { return __table_.__emplace_multi(_VSTD::forward<_Args>(__args)...); } template <class... _Args> - iterator emplace_hint(const_iterator __p, _Args&&... __args) { + _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __p, _Args&&... __args) { return __table_.__emplace_hint_multi(__p.__i_, _VSTD::forward<_Args>(__args)...); } #endif // _LIBCPP_CXX03_LANG @@ -2151,11 +2290,11 @@ private: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__table_.clear();} -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY iterator insert(node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_multimap::insert()"); return __table_.template __node_handle_insert_multi<node_type>( _VSTD::move(__nh)); @@ -2163,7 +2302,7 @@ private: _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __hint, node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_multimap::insert()"); return __table_.template __node_handle_insert_multi<node_type>( __hint.__i_, _VSTD::move(__nh)); @@ -2184,32 +2323,32 @@ private: _LIBCPP_INLINE_VISIBILITY void merge(unordered_multimap<key_type, mapped_type, _H2, _P2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } template <class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_multimap<key_type, mapped_type, _H2, _P2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } template <class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_map<key_type, mapped_type, _H2, _P2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } template <class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_map<key_type, mapped_type, _H2, _P2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } #endif @@ -2230,31 +2369,31 @@ private: iterator find(const key_type& __k) {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __table_.find(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY iterator find(const _K2& __k) {return __table_.find(__k);} template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY const_iterator find(const _K2& __k) const {return __table_.find(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY size_type count(const _K2& __k) const {return __table_.__count_multi(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY bool contains(const _K2& __k) const {return find(__k) != end();} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY pair<iterator, iterator> equal_range(const key_type& __k) @@ -2262,7 +2401,7 @@ private: _LIBCPP_INLINE_VISIBILITY pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {return __table_.__equal_range_multi(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY pair<iterator, iterator> equal_range(const _K2& __k) @@ -2271,7 +2410,7 @@ private: _LIBCPP_INLINE_VISIBILITY pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {return __table_.__equal_range_multi(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const _NOEXCEPT {return __table_.bucket_count();} @@ -2308,21 +2447,6 @@ private: void rehash(size_type __n) {__table_.__rehash_multi(__n);} _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.__reserve_multi(__n);} - -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - bool __dereferenceable(const const_iterator* __i) const - {return __table_.__dereferenceable(_VSTD::addressof(__i->__i_));} - bool __decrementable(const const_iterator* __i) const - {return __table_.__decrementable(_VSTD::addressof(__i->__i_));} - bool __addable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(_VSTD::addressof(__i->__i_), __n);} - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(_VSTD::addressof(__i->__i_), __n);} - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - - }; #if _LIBCPP_STD_VER >= 17 @@ -2330,7 +2454,7 @@ template<class _InputIterator, class _Hash = hash<__iter_key_type<_InputIterator>>, class _Pred = equal_to<__iter_key_type<_InputIterator>>, class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Hash>::value>, class = enable_if_t<!is_integral<_Hash>::value>, class = enable_if_t<!__is_allocator<_Pred>::value>, @@ -2339,6 +2463,20 @@ unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Al _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Hash, _Pred, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, + class _Hash = hash<__range_key_type<_Range>>, + class _Pred = equal_to<__range_key_type<_Range>>, + class _Allocator = allocator<__range_to_alloc_type<_Range>>, + class = enable_if_t<!__is_allocator<_Hash>::value>, + class = enable_if_t<!is_integral<_Hash>::value>, + class = enable_if_t<!__is_allocator<_Pred>::value>, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_multimap(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_multimap<__range_key_type<_Range>, __range_mapped_type<_Range>, _Hash, _Pred, _Allocator>; +#endif + template<class _Key, class _Tp, class _Hash = hash<remove_const_t<_Key>>, class _Pred = equal_to<remove_const_t<_Key>>, class _Allocator = allocator<pair<const _Key, _Tp>>, @@ -2351,21 +2489,21 @@ unordered_multimap(initializer_list<pair<_Key, _Tp>>, typename allocator_traits< -> unordered_multimap<remove_const_t<_Key>, _Tp, _Hash, _Pred, _Allocator>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multimap(_InputIterator, _InputIterator, _Allocator) -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; template<class _InputIterator, class _Hash, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Hash>::value>, class = enable_if_t<!is_integral<_Hash>::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> @@ -2373,6 +2511,30 @@ unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Al -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Hash, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; +#if _LIBCPP_STD_VER >= 23 + +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_multimap(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_multimap<__range_key_type<_Range>, __range_mapped_type<_Range>, hash<__range_key_type<_Range>>, + equal_to<__range_key_type<_Range>>, _Allocator>; + +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_multimap(from_range_t, _Range&&, _Allocator) + -> unordered_multimap<__range_key_type<_Range>, __range_mapped_type<_Range>, hash<__range_key_type<_Range>>, + equal_to<__range_key_type<_Range>>, _Allocator>; + +template <ranges::input_range _Range, class _Hash, class _Allocator, + class = enable_if_t<!__is_allocator<_Hash>::value>, + class = enable_if_t<!is_integral<_Hash>::value>, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_multimap(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_multimap<__range_key_type<_Range>, __range_mapped_type<_Range>, _Hash, + equal_to<__range_key_type<_Range>>, _Allocator>; + +#endif + template<class _Key, class _Tp, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multimap(initializer_list<pair<_Key, _Tp>>, typename allocator_traits<_Allocator>::size_type, _Allocator) @@ -2401,7 +2563,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); } @@ -2411,7 +2572,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); } @@ -2420,7 +2580,6 @@ template <class _InputIterator> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( _InputIterator __first, _InputIterator __last) { - _VSTD::__debug_db_insert_c(this); insert(__first, __last); } @@ -2431,7 +2590,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__first, __last); } @@ -2443,7 +2601,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__first, __last); } @@ -2454,7 +2611,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const allocator_type& __a) : __table_(typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); } template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> @@ -2462,7 +2618,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const unordered_multimap& __u) : __table_(__u.__table_) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -2472,7 +2627,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const unordered_multimap& __u, const allocator_type& __a) : __table_(__u.__table_, typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -2486,8 +2640,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { - _VSTD::__debug_db_insert_c(this); - std::__debug_db_swap(this, std::addressof(__u)); } template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> @@ -2495,7 +2647,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( unordered_multimap&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); if (__a != __u.get_allocator()) { iterator __i = __u.begin(); @@ -2505,15 +2656,12 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( __u.__table_.remove((__i++).__i_)->__value_.__move()); } } - else - std::__debug_db_swap(this, std::addressof(__u)); } template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( initializer_list<value_type> __il) { - _VSTD::__debug_db_insert_c(this); insert(__il.begin(), __il.end()); } @@ -2523,7 +2671,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__il.begin(), __il.end()); } @@ -2534,7 +2681,6 @@ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, typename __table::allocator_type(__a)) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__il.begin(), __il.end()); } @@ -2584,7 +2730,7 @@ swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY @@ -2618,6 +2764,8 @@ operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, return true; } +#if _LIBCPP_STD_VER <= 17 + template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY bool @@ -2627,17 +2775,19 @@ operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, return !(__x == __y); } +#endif + _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template <class _KeyT, class _ValueT, class _HashT = std::hash<_KeyT>, class _PredT = std::equal_to<_KeyT>> -using unordered_map = +using unordered_map _LIBCPP_AVAILABILITY_PMR = std::unordered_map<_KeyT, _ValueT, _HashT, _PredT, polymorphic_allocator<std::pair<const _KeyT, _ValueT>>>; template <class _KeyT, class _ValueT, class _HashT = std::hash<_KeyT>, class _PredT = std::equal_to<_KeyT>> -using unordered_multimap = +using unordered_multimap _LIBCPP_AVAILABILITY_PMR = std::unordered_multimap<_KeyT, _ValueT, _HashT, _PredT, polymorphic_allocator<std::pair<const _KeyT, _ValueT>>>; } // namespace pmr _LIBCPP_END_NAMESPACE_STD @@ -2647,7 +2797,9 @@ _LIBCPP_END_NAMESPACE_STD # include <algorithm> # include <bit> # include <concepts> +# include <cstdlib> # include <iterator> +# include <type_traits> #endif #endif // _LIBCPP_UNORDERED_MAP diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set index b4203c08a9b9..5e47f12446ff 100644 --- a/libcxx/include/unordered_set +++ b/libcxx/include/unordered_set @@ -58,6 +58,10 @@ public: size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<container-compatible-range<value_type> R> + unordered_set(from_range_t, R&& rg, size_type n = see below, + const hasher& hf = hasher(), const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); // C++23 explicit unordered_set(const allocator_type&); unordered_set(const unordered_set&); unordered_set(const unordered_set&, const Allocator&); @@ -77,6 +81,12 @@ public: template <class InputIterator> unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a); // C++14 + template<container-compatible-range<value_type> R> + unordered_set(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_set(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } // C++23 + template<container-compatible-range<value_type> R> + unordered_set(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) + : unordered_set(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { } // C++23 unordered_set(initializer_list<value_type> il, size_type n, const allocator_type& a); // C++14 unordered_set(initializer_list<value_type> il, size_type n, const hasher& hf, const allocator_type& a); // C++14 @@ -113,6 +123,8 @@ public: iterator insert(const_iterator hint, value_type&& obj); template <class InputIterator> void insert(InputIterator first, InputIterator last); + template<container-compatible-range<value_type> R> + void insert_range(R&& rg); // C++23 void insert(initializer_list<value_type>); node_type extract(const_iterator position); // C++17 @@ -191,6 +203,13 @@ unordered_set(InputIterator, InputIterator, typename see below::size_type = see -> unordered_set<typename iterator_traits<InputIterator>::value_type, Hash, Pred, Allocator>; // C++17 +template<ranges::input_range R, + class Hash = hash<ranges::range_value_t<R>>, + class Pred = equal_to<ranges::range_value_t<R>>, + class Allocator = allocator<ranges::range_value_t<R>>> + unordered_set(from_range_t, R&&, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_set<ranges::range_value_t<R>, Hash, Pred, Allocator>; // C++23 + template<class T, class Hash = hash<T>, class Pred = equal_to<T>, class Allocator = allocator<T>> unordered_set(initializer_list<T>, typename see below::size_type = see below, @@ -211,6 +230,21 @@ unordered_set(InputIterator, InputIterator, typename see below::size_type, equal_to<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17 +template<ranges::input_range R, class Allocator> + unordered_set(from_range_t, R&&, typename see below::size_type, Allocator) + -> unordered_set<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>, + equal_to<ranges::range_value_t<R>>, Allocator>; // C++23 + +template<ranges::input_range R, class Allocator> + unordered_set(from_range_t, R&&, Allocator) + -> unordered_set<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>, + equal_to<ranges::range_value_t<R>>, Allocator>; // C++23 + +template<ranges::input_range R, class Hash, class Allocator> + unordered_set(from_range_t, R&&, typename see below::size_type, Hash, Allocator) + -> unordered_set<ranges::range_value_t<R>, Hash, + equal_to<ranges::range_value_t<R>>, Allocator>; // C++23 + template<class T, class Allocator> unordered_set(initializer_list<T>, typename see below::size_type, Allocator) -> unordered_set<T, hash<T>, equal_to<T>, Allocator>; // C++17 @@ -232,7 +266,7 @@ template <class Value, class Hash, class Pred, class Alloc> template <class Value, class Hash, class Pred, class Alloc> bool operator!=(const unordered_set<Value, Hash, Pred, Alloc>& x, - const unordered_set<Value, Hash, Pred, Alloc>& y); + const unordered_set<Value, Hash, Pred, Alloc>& y); // removed in C++20 template <class Value, class Hash = hash<Value>, class Pred = equal_to<Value>, class Alloc = allocator<Value>> @@ -272,6 +306,10 @@ public: size_type n = 0, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<container-compatible-range<value_type> R> + unordered_multiset(from_range_t, R&& rg, size_type n = see below, + const hasher& hf = hasher(), const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); // C++23 explicit unordered_multiset(const allocator_type&); unordered_multiset(const unordered_multiset&); unordered_multiset(const unordered_multiset&, const Allocator&); @@ -291,6 +329,12 @@ public: template <class InputIterator> unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a); // C++14 + template<container-compatible-range<value_type> R> + unordered_multiset(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_multiset(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { } // C++23 + template<container-compatible-range<value_type> R> + unordered_multiset(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) + : unordered_multiset(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { } // C++23 unordered_multiset(initializer_list<value_type> il, size_type n, const allocator_type& a); // C++14 unordered_multiset(initializer_list<value_type> il, size_type n, const hasher& hf, const allocator_type& a); // C++14 @@ -327,6 +371,8 @@ public: iterator insert(const_iterator hint, value_type&& obj); template <class InputIterator> void insert(InputIterator first, InputIterator last); + template<container-compatible-range<value_type> R> + void insert_range(R&& rg); // C++23 void insert(initializer_list<value_type>); node_type extract(const_iterator position); // C++17 @@ -405,6 +451,13 @@ unordered_multiset(InputIterator, InputIterator, see below::size_type = see belo -> unordered_multiset<typename iterator_traits<InputIterator>::value_type, Hash, Pred, Allocator>; // C++17 +template<ranges::input_range R, + class Hash = hash<ranges::range_value_t<R>>, + class Pred = equal_to<ranges::range_value_t<R>>, + class Allocator = allocator<ranges::range_value_t<R>>> + unordered_multiset(from_range_t, R&&, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multiset<ranges::range_value_t<R>, Hash, Pred, Allocator>; // C++23 + template<class T, class Hash = hash<T>, class Pred = equal_to<T>, class Allocator = allocator<T>> unordered_multiset(initializer_list<T>, typename see below::size_type = see below, @@ -424,6 +477,21 @@ unordered_multiset(InputIterator, InputIterator, typename see below::size_type, -> unordered_multiset<typename iterator_traits<InputIterator>::value_type, Hash, equal_to<typename iterator_traits<InputIterator>::value_type>, Allocator>; // C++17 +template<ranges::input_range R, class Allocator> + unordered_multiset(from_range_t, R&&, typename see below::size_type, Allocator) + -> unordered_multiset<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>, + equal_to<ranges::range_value_t<R>>, Allocator>; // C++23 + +template<ranges::input_range R, class Allocator> + unordered_multiset(from_range_t, R&&, Allocator) + -> unordered_multiset<ranges::range_value_t<R>, hash<ranges::range_value_t<R>>, + equal_to<ranges::range_value_t<R>>, Allocator>; // C++23 + +template<ranges::input_range R, class Hash, class Allocator> + unordered_multiset(from_range_t, R&&, typename see below::size_type, Hash, Allocator) + -> unordered_multiset<ranges::range_value_t<R>, Hash, + equal_to<ranges::range_value_t<R>>, Allocator>; // C++23 + template<class T, class Allocator> unordered_multiset(initializer_list<T>, typename see below::size_type, Allocator) -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>; // C++17 @@ -454,25 +522,29 @@ template <class Value, class Hash, class Pred, class Alloc> template <class Value, class Hash, class Pred, class Alloc> bool operator!=(const unordered_multiset<Value, Hash, Pred, Alloc>& x, - const unordered_multiset<Value, Hash, Pred, Alloc>& y); + const unordered_multiset<Value, Hash, Pred, Alloc>& y); // removed in C++20 } // std */ #include <__algorithm/is_permutation.h> #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> #include <__config> -#include <__debug> #include <__functional/is_transparent.h> #include <__functional/operations.h> #include <__hash_table> #include <__iterator/distance.h> #include <__iterator/erase_if_container.h> #include <__iterator/iterator_traits.h> +#include <__iterator/ranges_iterator_traits.h> #include <__memory/addressof.h> #include <__memory/allocator.h> #include <__memory_resource/polymorphic_allocator.h> #include <__node_handle> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> #include <__type_traits/is_allocator.h> #include <__utility/forward.h> #include <version> @@ -513,7 +585,7 @@ public: typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same<value_type, typename allocator_type::value_type>::value), - "Invalid allocator::value_type"); + "Allocator::value_type must be same type as value_type"); static_assert(is_same<allocator_type, __rebind_alloc<allocator_traits<allocator_type>, value_type> >::value, "[allocator.requirements] states that rebinding an allocator to the same type should result in the " @@ -535,7 +607,7 @@ public: typedef typename __table::const_local_iterator local_iterator; typedef typename __table::const_local_iterator const_local_iterator; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef __set_node_handle<typename __table::__node, allocator_type> node_type; typedef __insert_return_type<iterator, node_type> insert_return_type; #endif @@ -549,11 +621,10 @@ public: unordered_set() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { - _VSTD::__debug_db_insert_c(this); } - explicit unordered_set(size_type __n, const hasher& __hf = hasher(), + explicit _LIBCPP_HIDE_FROM_ABI unordered_set(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 inline _LIBCPP_INLINE_VISIBILITY unordered_set(size_type __n, const allocator_type& __a) : unordered_set(__n, hasher(), key_equal(), __a) {} @@ -561,46 +632,74 @@ public: unordered_set(size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_set(__n, __hf, key_equal(), __a) {} #endif - unordered_set(size_type __n, const hasher& __hf, const key_equal& __eql, + _LIBCPP_HIDE_FROM_ABI unordered_set(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); template <class _InputIterator> - unordered_set(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI unordered_set(_InputIterator __first, _InputIterator __last); template <class _InputIterator> - unordered_set(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI unordered_set(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template <class _InputIterator> - unordered_set(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI unordered_set(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); -#if _LIBCPP_STD_VER > 11 + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_set(from_range_t, _Range&& __range, size_type __n = /*implementation-defined*/0, + const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : __table_(__hf, __eql, __a) { + if (__n > 0) { + __table_.__rehash_unique(__n); + } + insert_range(std::forward<_Range>(__range)); + } +#endif + +#if _LIBCPP_STD_VER >= 14 template <class _InputIterator> inline _LIBCPP_INLINE_VISIBILITY unordered_set(_InputIterator __first, _InputIterator __last, size_type __n, const allocator_type& __a) : unordered_set(__first, __last, __n, hasher(), key_equal(), __a) {} template <class _InputIterator> - unordered_set(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI unordered_set(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_set(__first, __last, __n, __hf, key_equal(), __a) {} #endif + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_set(from_range_t, _Range&& __range, size_type __n, const allocator_type& __a) + : unordered_set(from_range, std::forward<_Range>(__range), __n, hasher(), key_equal(), __a) {} + + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_set(from_range_t, _Range&& __range, size_type __n, const hasher& __hf, const allocator_type& __a) + : unordered_set(from_range, std::forward<_Range>(__range), __n, __hf, key_equal(), __a) {} +#endif + _LIBCPP_INLINE_VISIBILITY explicit unordered_set(const allocator_type& __a); - unordered_set(const unordered_set& __u); - unordered_set(const unordered_set& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI unordered_set(const unordered_set& __u); + _LIBCPP_HIDE_FROM_ABI unordered_set(const unordered_set& __u, const allocator_type& __a); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY unordered_set(unordered_set&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value); - unordered_set(unordered_set&& __u, const allocator_type& __a); - unordered_set(initializer_list<value_type> __il); - unordered_set(initializer_list<value_type> __il, size_type __n, + _LIBCPP_HIDE_FROM_ABI unordered_set(unordered_set&& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI unordered_set(initializer_list<value_type> __il); + _LIBCPP_HIDE_FROM_ABI unordered_set(initializer_list<value_type> __il, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - unordered_set(initializer_list<value_type> __il, size_type __n, + _LIBCPP_HIDE_FROM_ABI unordered_set(initializer_list<value_type> __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 inline _LIBCPP_INLINE_VISIBILITY unordered_set(initializer_list<value_type> __il, size_type __n, const allocator_type& __a) @@ -661,11 +760,7 @@ public: {return __table_.__emplace_unique(_VSTD::forward<_Args>(__args)...);} template <class... _Args> _LIBCPP_INLINE_VISIBILITY - iterator emplace_hint(const_iterator __p, _Args&&... __args) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__p)) == this, - "unordered_set::emplace_hint(const_iterator, args...) called with an iterator not" - " referring to this unordered_set"); - (void)__p; + iterator emplace_hint(const_iterator, _Args&&... __args) { return __table_.__emplace_unique(std::forward<_Args>(__args)...).first; } @@ -673,11 +768,7 @@ public: pair<iterator, bool> insert(value_type&& __x) {return __table_.__insert_unique(_VSTD::move(__x));} _LIBCPP_INLINE_VISIBILITY - iterator insert(const_iterator __p, value_type&& __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__p)) == this, - "unordered_set::insert(const_iterator, value_type&&) called with an iterator not" - " referring to this unordered_set"); - (void)__p; + iterator insert(const_iterator, value_type&& __x) { return insert(std::move(__x)).first; } @@ -690,17 +781,23 @@ public: {return __table_.__insert_unique(__x);} _LIBCPP_INLINE_VISIBILITY - iterator insert(const_iterator __p, const value_type& __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__p)) == this, - "unordered_set::insert(const_iterator, const value_type&) called with an iterator not" - " referring to this unordered_set"); - (void)__p; + iterator insert(const_iterator, const value_type& __x) { return insert(__x).first; } template <class _InputIterator> _LIBCPP_INLINE_VISIBILITY void insert(_InputIterator __first, _InputIterator __last); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + void insert_range(_Range&& __range) { + for (auto&& __element : __range) { + __table_.__insert_unique(std::forward<decltype(__element)>(__element)); + } + } +#endif + _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __p) {return __table_.erase(__p);} _LIBCPP_INLINE_VISIBILITY @@ -711,11 +808,11 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__table_.clear();} -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY insert_return_type insert(node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_set::insert()"); return __table_.template __node_handle_insert_unique< node_type, insert_return_type>(_VSTD::move(__nh)); @@ -723,7 +820,7 @@ public: _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __h, node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_set::insert()"); return __table_.template __node_handle_insert_unique<node_type>( __h, _VSTD::move(__nh)); @@ -743,32 +840,32 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(unordered_set<key_type, _H2, _P2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); __table_.__node_handle_merge_unique(__source.__table_); } template<class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_set<key_type, _H2, _P2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); __table_.__node_handle_merge_unique(__source.__table_); } template<class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); __table_.__node_handle_merge_unique(__source.__table_); } template<class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); __table_.__node_handle_merge_unique(__source.__table_); } #endif @@ -787,31 +884,31 @@ public: iterator find(const key_type& __k) {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __table_.find(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY iterator find(const _K2& __k) {return __table_.find(__k);} template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY const_iterator find(const _K2& __k) const {return __table_.find(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY size_type count(const _K2& __k) const {return __table_.__count_unique(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY bool contains(const _K2& __k) const {return find(__k) != end();} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY pair<iterator, iterator> equal_range(const key_type& __k) @@ -819,7 +916,7 @@ public: _LIBCPP_INLINE_VISIBILITY pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {return __table_.__equal_range_unique(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY pair<iterator, iterator> equal_range(const _K2& __k) @@ -828,7 +925,7 @@ public: _LIBCPP_INLINE_VISIBILITY pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {return __table_.__equal_range_unique(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const _NOEXCEPT {return __table_.bucket_count();} @@ -863,20 +960,6 @@ public: void rehash(size_type __n) {__table_.__rehash_unique(__n);} _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.__reserve_unique(__n);} - -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - bool __dereferenceable(const const_iterator* __i) const - {return __table_.__dereferenceable(__i);} - bool __decrementable(const const_iterator* __i) const - {return __table_.__decrementable(__i);} - bool __addable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(__i, __n);} - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(__i, __n);} - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - }; #if _LIBCPP_STD_VER >= 17 @@ -884,7 +967,7 @@ template<class _InputIterator, class _Hash = hash<__iter_value_type<_InputIterator>>, class _Pred = equal_to<__iter_value_type<_InputIterator>>, class _Allocator = allocator<__iter_value_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Hash>::value>, class = enable_if_t<!is_integral<_Hash>::value>, class = enable_if_t<!__is_allocator<_Pred>::value>, @@ -893,6 +976,20 @@ unordered_set(_InputIterator, _InputIterator, typename allocator_traits<_Allocat _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) -> unordered_set<__iter_value_type<_InputIterator>, _Hash, _Pred, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, + class _Hash = hash<ranges::range_value_t<_Range>>, + class _Pred = equal_to<ranges::range_value_t<_Range>>, + class _Allocator = allocator<ranges::range_value_t<_Range>>, + class = enable_if_t<!__is_allocator<_Hash>::value>, + class = enable_if_t<!is_integral<_Hash>::value>, + class = enable_if_t<!__is_allocator<_Pred>::value>, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_set(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set<ranges::range_value_t<_Range>, _Hash, _Pred, _Allocator>; // C++23 +#endif + template<class _Tp, class _Hash = hash<_Tp>, class _Pred = equal_to<_Tp>, class _Allocator = allocator<_Tp>, @@ -905,7 +1002,7 @@ unordered_set(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size -> unordered_set<_Tp, _Hash, _Pred, _Allocator>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_set(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) @@ -915,7 +1012,7 @@ unordered_set(_InputIterator, _InputIterator, _Allocator>; template<class _InputIterator, class _Hash, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Hash>::value>, class = enable_if_t<!is_integral<_Hash>::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> @@ -925,6 +1022,29 @@ unordered_set(_InputIterator, _InputIterator, equal_to<__iter_value_type<_InputIterator>>, _Allocator>; +#if _LIBCPP_STD_VER >= 23 + +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_set(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_set<ranges::range_value_t<_Range>, hash<ranges::range_value_t<_Range>>, + equal_to<ranges::range_value_t<_Range>>, _Allocator>; + +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_set(from_range_t, _Range&&, _Allocator) + -> unordered_set<ranges::range_value_t<_Range>, hash<ranges::range_value_t<_Range>>, + equal_to<ranges::range_value_t<_Range>>, _Allocator>; + +template <ranges::input_range _Range, class _Hash, class _Allocator, + class = enable_if_t<!__is_allocator<_Hash>::value>, + class = enable_if_t<!is_integral<_Hash>::value>, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_set(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_set<ranges::range_value_t<_Range>, _Hash, equal_to<ranges::range_value_t<_Range>>, _Allocator>; + +#endif + template<class _Tp, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_set(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Allocator) @@ -943,7 +1063,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); } @@ -952,7 +1071,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); } @@ -961,7 +1079,6 @@ template <class _InputIterator> unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( _InputIterator __first, _InputIterator __last) { - _VSTD::__debug_db_insert_c(this); insert(__first, __last); } @@ -972,7 +1089,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__first, __last); } @@ -984,7 +1100,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__first, __last); } @@ -995,7 +1110,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( const allocator_type& __a) : __table_(__a) { - _VSTD::__debug_db_insert_c(this); } template <class _Value, class _Hash, class _Pred, class _Alloc> @@ -1003,7 +1117,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( const unordered_set& __u) : __table_(__u.__table_) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -1013,7 +1126,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( const unordered_set& __u, const allocator_type& __a) : __table_(__u.__table_, __a) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -1027,8 +1139,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { - _VSTD::__debug_db_insert_c(this); - std::__debug_db_swap(this, std::addressof(__u)); } template <class _Value, class _Hash, class _Pred, class _Alloc> @@ -1036,22 +1146,18 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( unordered_set&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), __a) { - _VSTD::__debug_db_insert_c(this); if (__a != __u.get_allocator()) { iterator __i = __u.begin(); while (__u.size() != 0) __table_.__insert_unique(_VSTD::move(__u.__table_.remove(__i++)->__value_)); } - else - std::__debug_db_swap(this, std::addressof(__u)); } template <class _Value, class _Hash, class _Pred, class _Alloc> unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( initializer_list<value_type> __il) { - _VSTD::__debug_db_insert_c(this); insert(__il.begin(), __il.end()); } @@ -1061,7 +1167,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__il.begin(), __il.end()); } @@ -1072,7 +1177,6 @@ unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set( const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_unique(__n); insert(__il.begin(), __il.end()); } @@ -1120,7 +1224,7 @@ swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Value, class _Hash, class _Pred, class _Alloc, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY @@ -1150,6 +1254,8 @@ operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, return true; } +#if _LIBCPP_STD_VER <= 17 + template <class _Value, class _Hash, class _Pred, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY bool @@ -1159,6 +1265,8 @@ operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, return !(__x == __y); } +#endif + template <class _Value, class _Hash = hash<_Value>, class _Pred = equal_to<_Value>, class _Alloc = allocator<_Value> > class _LIBCPP_TEMPLATE_VIS unordered_multiset @@ -1173,7 +1281,7 @@ public: typedef value_type& reference; typedef const value_type& const_reference; static_assert((is_same<value_type, typename allocator_type::value_type>::value), - "Invalid allocator::value_type"); + "Allocator::value_type must be same type as value_type"); private: typedef __hash_table<value_type, hasher, key_equal, allocator_type> __table; @@ -1191,7 +1299,7 @@ public: typedef typename __table::const_local_iterator local_iterator; typedef typename __table::const_local_iterator const_local_iterator; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typedef __set_node_handle<typename __table::__node, allocator_type> node_type; #endif @@ -1204,13 +1312,12 @@ public: unordered_multiset() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) { - _VSTD::__debug_db_insert_c(this); } - explicit unordered_multiset(size_type __n, const hasher& __hf = hasher(), + explicit _LIBCPP_HIDE_FROM_ABI unordered_multiset(size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - unordered_multiset(size_type __n, const hasher& __hf, + _LIBCPP_HIDE_FROM_ABI unordered_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 inline _LIBCPP_INLINE_VISIBILITY unordered_multiset(size_type __n, const allocator_type& __a) : unordered_multiset(__n, hasher(), key_equal(), __a) {} @@ -1219,16 +1326,31 @@ public: : unordered_multiset(__n, __hf, key_equal(), __a) {} #endif template <class _InputIterator> - unordered_multiset(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI unordered_multiset(_InputIterator __first, _InputIterator __last); template <class _InputIterator> - unordered_multiset(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI unordered_multiset(_InputIterator __first, _InputIterator __last, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); template <class _InputIterator> - unordered_multiset(_InputIterator __first, _InputIterator __last, + _LIBCPP_HIDE_FROM_ABI unordered_multiset(_InputIterator __first, _InputIterator __last, size_type __n , const hasher& __hf, const key_equal& __eql, const allocator_type& __a); -#if _LIBCPP_STD_VER > 11 + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_multiset(from_range_t, _Range&& __range, size_type __n = /*implementation-defined*/0, + const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : __table_(__hf, __eql, __a) { + if (__n > 0) { + __table_.__rehash_multi(__n); + } + insert_range(std::forward<_Range>(__range)); + } +#endif + +#if _LIBCPP_STD_VER >= 14 template <class _InputIterator> inline _LIBCPP_INLINE_VISIBILITY unordered_multiset(_InputIterator __first, _InputIterator __last, @@ -1240,23 +1362,36 @@ public: size_type __n, const hasher& __hf, const allocator_type& __a) : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a) {} #endif + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_multiset(from_range_t, _Range&& __range, size_type __n, const allocator_type& __a) + : unordered_multiset(from_range, std::forward<_Range>(__range), __n, hasher(), key_equal(), __a) {} + + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + unordered_multiset(from_range_t, _Range&& __range, size_type __n, const hasher& __hf, const allocator_type& __a) + : unordered_multiset(from_range, std::forward<_Range>(__range), __n, __hf, key_equal(), __a) {} +#endif + _LIBCPP_INLINE_VISIBILITY explicit unordered_multiset(const allocator_type& __a); - unordered_multiset(const unordered_multiset& __u); - unordered_multiset(const unordered_multiset& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI unordered_multiset(const unordered_multiset& __u); + _LIBCPP_HIDE_FROM_ABI unordered_multiset(const unordered_multiset& __u, const allocator_type& __a); #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY unordered_multiset(unordered_multiset&& __u) _NOEXCEPT_(is_nothrow_move_constructible<__table>::value); - unordered_multiset(unordered_multiset&& __u, const allocator_type& __a); - unordered_multiset(initializer_list<value_type> __il); - unordered_multiset(initializer_list<value_type> __il, size_type __n, + _LIBCPP_HIDE_FROM_ABI unordered_multiset(unordered_multiset&& __u, const allocator_type& __a); + _LIBCPP_HIDE_FROM_ABI unordered_multiset(initializer_list<value_type> __il); + _LIBCPP_HIDE_FROM_ABI unordered_multiset(initializer_list<value_type> __il, size_type __n, const hasher& __hf = hasher(), const key_equal& __eql = key_equal()); - unordered_multiset(initializer_list<value_type> __il, size_type __n, + _LIBCPP_HIDE_FROM_ABI unordered_multiset(initializer_list<value_type> __il, size_type __n, const hasher& __hf, const key_equal& __eql, const allocator_type& __a); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 inline _LIBCPP_INLINE_VISIBILITY unordered_multiset(initializer_list<value_type> __il, size_type __n, const allocator_type& __a) : unordered_multiset(__il, __n, hasher(), key_equal(), __a) {} @@ -1280,7 +1415,7 @@ public: _LIBCPP_INLINE_VISIBILITY unordered_multiset& operator=(unordered_multiset&& __u) _NOEXCEPT_(is_nothrow_move_assignable<__table>::value); - unordered_multiset& operator=(initializer_list<value_type> __il); + _LIBCPP_HIDE_FROM_ABI unordered_multiset& operator=(initializer_list<value_type> __il); #endif // _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY @@ -1338,11 +1473,21 @@ public: _LIBCPP_INLINE_VISIBILITY void insert(_InputIterator __first, _InputIterator __last); -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<value_type> _Range> + _LIBCPP_HIDE_FROM_ABI + void insert_range(_Range&& __range) { + for (auto&& __element : __range) { + __table_.__insert_multi(std::forward<decltype(__element)>(__element)); + } + } +#endif + +#if _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY iterator insert(node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_multiset::insert()"); return __table_.template __node_handle_insert_multi<node_type>( _VSTD::move(__nh)); @@ -1350,7 +1495,7 @@ public: _LIBCPP_INLINE_VISIBILITY iterator insert(const_iterator __hint, node_type&& __nh) { - _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__nh.empty() || __nh.get_allocator() == get_allocator(), "node_type with incompatible allocator passed to unordered_multiset::insert()"); return __table_.template __node_handle_insert_multi<node_type>( __hint, _VSTD::move(__nh)); @@ -1371,32 +1516,32 @@ public: _LIBCPP_INLINE_VISIBILITY void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } template <class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_multiset<key_type, _H2, _P2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } template <class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_set<key_type, _H2, _P2, allocator_type>& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } template <class _H2, class _P2> _LIBCPP_INLINE_VISIBILITY void merge(unordered_set<key_type, _H2, _P2, allocator_type>&& __source) { - _LIBCPP_ASSERT(__source.get_allocator() == get_allocator(), - "merging container with incompatible allocator"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__source.get_allocator() == get_allocator(), + "merging container with incompatible allocator"); return __table_.__node_handle_merge_multi(__source.__table_); } #endif @@ -1425,31 +1570,31 @@ public: iterator find(const key_type& __k) {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY const_iterator find(const key_type& __k) const {return __table_.find(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY iterator find(const _K2& __k) {return __table_.find(__k);} template<class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY const_iterator find(const _K2& __k) const {return __table_.find(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY size_type count(const _K2& __k) const {return __table_.__count_multi(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY bool contains(const key_type& __k) const {return find(__k) != end();} template<class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY bool contains(const _K2& __k) const {return find(__k) != end();} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY pair<iterator, iterator> equal_range(const key_type& __k) @@ -1457,7 +1602,7 @@ public: _LIBCPP_INLINE_VISIBILITY pair<const_iterator, const_iterator> equal_range(const key_type& __k) const {return __table_.__equal_range_multi(__k);} -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template<class _K2, enable_if_t<__is_transparent<hasher, _K2>::value && __is_transparent<key_equal, _K2>::value>* = nullptr> _LIBCPP_INLINE_VISIBILITY pair<iterator, iterator> equal_range(const _K2& __k) @@ -1466,7 +1611,7 @@ public: _LIBCPP_INLINE_VISIBILITY pair<const_iterator, const_iterator> equal_range(const _K2& __k) const {return __table_.__equal_range_multi(__k);} -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 _LIBCPP_INLINE_VISIBILITY size_type bucket_count() const _NOEXCEPT {return __table_.bucket_count();} @@ -1501,20 +1646,6 @@ public: void rehash(size_type __n) {__table_.__rehash_multi(__n);} _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) {__table_.__reserve_multi(__n);} - -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - bool __dereferenceable(const const_iterator* __i) const - {return __table_.__dereferenceable(__i);} - bool __decrementable(const const_iterator* __i) const - {return __table_.__decrementable(__i);} - bool __addable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(__i, __n);} - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const - {return __table_.__addable(__i, __n);} - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - }; #if _LIBCPP_STD_VER >= 17 @@ -1522,7 +1653,7 @@ template<class _InputIterator, class _Hash = hash<__iter_value_type<_InputIterator>>, class _Pred = equal_to<__iter_value_type<_InputIterator>>, class _Allocator = allocator<__iter_value_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Hash>::value>, class = enable_if_t<!is_integral<_Hash>::value>, class = enable_if_t<!__is_allocator<_Pred>::value>, @@ -1531,6 +1662,20 @@ unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Al _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) -> unordered_multiset<__iter_value_type<_InputIterator>, _Hash, _Pred, _Allocator>; +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, + class _Hash = hash<ranges::range_value_t<_Range>>, + class _Pred = equal_to<ranges::range_value_t<_Range>>, + class _Allocator = allocator<ranges::range_value_t<_Range>>, + class = enable_if_t<!__is_allocator<_Hash>::value>, + class = enable_if_t<!is_integral<_Hash>::value>, + class = enable_if_t<!__is_allocator<_Pred>::value>, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_multiset(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_multiset<ranges::range_value_t<_Range>, _Hash, _Pred, _Allocator>; // C++23 +#endif + template<class _Tp, class _Hash = hash<_Tp>, class _Pred = equal_to<_Tp>, class _Allocator = allocator<_Tp>, class = enable_if_t<!__is_allocator<_Hash>::value>, @@ -1542,7 +1687,7 @@ unordered_multiset(initializer_list<_Tp>, typename allocator_traits<_Allocator>: -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>; template<class _InputIterator, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) -> unordered_multiset<__iter_value_type<_InputIterator>, @@ -1551,7 +1696,7 @@ unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Al _Allocator>; template<class _InputIterator, class _Hash, class _Allocator, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<!__is_allocator<_Hash>::value>, class = enable_if_t<!is_integral<_Hash>::value>, class = enable_if_t<__is_allocator<_Allocator>::value>> @@ -1561,6 +1706,29 @@ unordered_multiset(_InputIterator, _InputIterator, typename allocator_traits<_Al equal_to<__iter_value_type<_InputIterator>>, _Allocator>; +#if _LIBCPP_STD_VER >= 23 + +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_multiset(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_multiset<ranges::range_value_t<_Range>, hash<ranges::range_value_t<_Range>>, + equal_to<ranges::range_value_t<_Range>>, _Allocator>; + +template <ranges::input_range _Range, class _Allocator, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_multiset(from_range_t, _Range&&, _Allocator) + -> unordered_multiset<ranges::range_value_t<_Range>, hash<ranges::range_value_t<_Range>>, + equal_to<ranges::range_value_t<_Range>>, _Allocator>; + +template <ranges::input_range _Range, class _Hash, class _Allocator, + class = enable_if_t<!__is_allocator<_Hash>::value>, + class = enable_if_t<!is_integral<_Hash>::value>, + class = enable_if_t<__is_allocator<_Allocator>::value>> +unordered_multiset(from_range_t, _Range&&, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_multiset<ranges::range_value_t<_Range>, _Hash, equal_to<ranges::range_value_t<_Range>>, _Allocator>; + +#endif + template<class _Tp, class _Allocator, class = enable_if_t<__is_allocator<_Allocator>::value>> unordered_multiset(initializer_list<_Tp>, typename allocator_traits<_Allocator>::size_type, _Allocator) @@ -1579,7 +1747,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( size_type __n, const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); } @@ -1589,7 +1756,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( const allocator_type& __a) : __table_(__hf, __eql, __a) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); } @@ -1598,7 +1764,6 @@ template <class _InputIterator> unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( _InputIterator __first, _InputIterator __last) { - _VSTD::__debug_db_insert_c(this); insert(__first, __last); } @@ -1609,7 +1774,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( const hasher& __hf, const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__first, __last); } @@ -1621,7 +1785,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( const hasher& __hf, const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__first, __last); } @@ -1632,7 +1795,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( const allocator_type& __a) : __table_(__a) { - _VSTD::__debug_db_insert_c(this); } template <class _Value, class _Hash, class _Pred, class _Alloc> @@ -1640,7 +1802,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( const unordered_multiset& __u) : __table_(__u.__table_) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -1650,7 +1811,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( const unordered_multiset& __u, const allocator_type& __a) : __table_(__u.__table_, __a) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__u.bucket_count()); insert(__u.begin(), __u.end()); } @@ -1664,8 +1824,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( _NOEXCEPT_(is_nothrow_move_constructible<__table>::value) : __table_(_VSTD::move(__u.__table_)) { - _VSTD::__debug_db_insert_c(this); - std::__debug_db_swap(this, std::addressof(__u)); } template <class _Value, class _Hash, class _Pred, class _Alloc> @@ -1673,22 +1831,18 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( unordered_multiset&& __u, const allocator_type& __a) : __table_(_VSTD::move(__u.__table_), __a) { - _VSTD::__debug_db_insert_c(this); if (__a != __u.get_allocator()) { iterator __i = __u.begin(); while (__u.size() != 0) __table_.__insert_multi(_VSTD::move(__u.__table_.remove(__i++)->__value_)); } - else - std::__debug_db_swap(this, std::addressof(__u)); } template <class _Value, class _Hash, class _Pred, class _Alloc> unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( initializer_list<value_type> __il) { - _VSTD::__debug_db_insert_c(this); insert(__il.begin(), __il.end()); } @@ -1698,7 +1852,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( const key_equal& __eql) : __table_(__hf, __eql) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__il.begin(), __il.end()); } @@ -1709,7 +1862,6 @@ unordered_multiset<_Value, _Hash, _Pred, _Alloc>::unordered_multiset( const key_equal& __eql, const allocator_type& __a) : __table_(__hf, __eql, __a) { - _VSTD::__debug_db_insert_c(this); __table_.__rehash_multi(__n); insert(__il.begin(), __il.end()); } @@ -1758,7 +1910,7 @@ swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Value, class _Hash, class _Pred, class _Alloc, class _Predicate> inline _LIBCPP_INLINE_VISIBILITY @@ -1792,6 +1944,8 @@ operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, return true; } +#if _LIBCPP_STD_VER <= 17 + template <class _Value, class _Hash, class _Pred, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY bool @@ -1801,24 +1955,28 @@ operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, return !(__x == __y); } +#endif + _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template <class _KeyT, class _HashT = std::hash<_KeyT>, class _PredT = std::equal_to<_KeyT>> -using unordered_set = std::unordered_set<_KeyT, _HashT, _PredT, polymorphic_allocator<_KeyT>>; +using unordered_set _LIBCPP_AVAILABILITY_PMR = std::unordered_set<_KeyT, _HashT, _PredT, polymorphic_allocator<_KeyT>>; template <class _KeyT, class _HashT = std::hash<_KeyT>, class _PredT = std::equal_to<_KeyT>> -using unordered_multiset = std::unordered_multiset<_KeyT, _HashT, _PredT, polymorphic_allocator<_KeyT>>; +using unordered_multiset _LIBCPP_AVAILABILITY_PMR = std::unordered_multiset<_KeyT, _HashT, _PredT, polymorphic_allocator<_KeyT>>; } // namespace pmr _LIBCPP_END_NAMESPACE_STD #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <concepts> +# include <cstdlib> # include <functional> # include <iterator> +# include <type_traits> #endif #endif // _LIBCPP_UNORDERED_SET diff --git a/libcxx/include/utility b/libcxx/include/utility index a4d8cf853d20..c5581d55e79b 100644 --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -84,14 +84,15 @@ struct pair explicit(see-below) constexpr pair(); explicit(see-below) pair(const T1& x, const T2& y); // constexpr in C++14 template <class U = T1, class V = T2> explicit(see-below) pair(U&&, V&&); // constexpr in C++14 - template <class U, class V> constexpr explicit(see below) pair(pair<U, V>&); // since C++23 + template <class U, class V> constexpr explicit(see-below) pair(pair<U, V>&); // since C++23 template <class U, class V> explicit(see-below) pair(const pair<U, V>& p); // constexpr in C++14 template <class U, class V> explicit(see-below) pair(pair<U, V>&& p); // constexpr in C++14 template <class U, class V> - constexpr explicit(see below) pair(const pair<U, V>&&); // since C++23 + constexpr explicit(see-below) pair(const pair<U, V>&&); // since C++23 + template <pair-like P> constexpr explicit(see-below) pair(P&&); // since C++23 template <class... Args1, class... Args2> - pair(piecewise_construct_t, tuple<Args1...> first_args, - tuple<Args2...> second_args); // constexpr in C++20 + pair(piecewise_construct_t, tuple<Args1...> first_args, // constexpr in C++20 + tuple<Args2...> second_args); constexpr const pair& operator=(const pair& p) const; // since C++23 template <class U, class V> pair& operator=(const pair<U, V>& p); // constexpr in C++20 @@ -103,6 +104,8 @@ struct pair template <class U, class V> pair& operator=(pair<U, V>&& p); // constexpr in C++20 template <class U, class V> constexpr const pair& operator=(pair<U, V>&& p) const; // since C++23 + template <pair-like P> constexpr pair& operator=(P&&); // since C++23 + template <pair-like P> constexpr const pair& operator=(P&&) const; // since C++23 void swap(pair& p) noexcept(is_nothrow_swappable_v<T1> && is_nothrow_swappable_v<T2>); // constexpr in C++20 @@ -117,24 +120,30 @@ struct common_type<pair<T1, T2>, pair<U1, U2>>; template<class T1, class T2> pair(T1, T2) -> pair<T1, T2>; -template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14 -template <class T1, class T2> bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20 -template <class T1, class T2> bool operator< (const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20 -template <class T1, class T2> bool operator> (const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20 -template <class T1, class T2> bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20 -template <class T1, class T2> bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20 -template <class T1, class T2> - constexpr common_comparison_type_t<synth-three-way-result<T1>, - synth-three-way-result<T2>> - operator<=>(const pair<T1,T2>&, const pair<T1,T2>&); // C++20 +template <class T1, class T2, class U1, class U2> +bool operator==(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14 +template <class T1, class T2, class U1, class U2> +bool operator!=(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20 +template <class T1, class T2, class U1, class U2> +bool operator< (const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20 +template <class T1, class T2, class U1, class U2> +bool operator> (const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20 +template <class T1, class T2, class U1, class U2> +bool operator>=(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20 +template <class T1, class T2, class U1, class U2> +bool operator<=(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20 +template <class T1, class T2, class U1, class U2> + constexpr common_comparison_type_t<synth-three-way-result<T1,U1>, + synth-three-way-result<T2,U2>> + operator<=>(const pair<T1,T2>&, const pair<U1,U2>&); // C++20 template <class T1, class T2> pair<V1, V2> make_pair(T1&&, T2&&); // constexpr in C++14 template <class T1, class T2> void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); // constexpr in C++20 -template<class T1, class T2> -constexpr void swap(const pair<T1, T2>& x, const pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); // since C++23 +template<class T1, class T2> // since C++23 +constexpr void swap(const pair<T1, T2>& x, const pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; inline constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); @@ -208,8 +217,8 @@ template<class... T> using index_sequence_for = make_index_sequence<sizeof...(T)>; template<class T, class U=T> - constexpr T exchange(T& obj, U&& new_value) - noexcept(is_nothrow_move_constructible<T>::value && is_nothrow_assignable<T&, U>::value); // constexpr in C++17, noexcept in C++23 + constexpr T exchange(T& obj, U&& new_value) // constexpr in C++17, noexcept in C++23 + noexcept(is_nothrow_move_constructible<T>::value && is_nothrow_assignable<T&, U>::value); // 20.2.7, in-place construction // C++17 struct in_place_t { @@ -231,7 +240,7 @@ template <size_t I> // [utility.underlying], to_underlying template <class T> - constexpr underlying_type_t<T> to_underlying( T value ) noexcept; // C++2b + constexpr underlying_type_t<T> to_underlying( T value ) noexcept; // C++23 } // std @@ -266,8 +275,8 @@ template <class T> #include <initializer_list> // [tuple.helper] -#include <__tuple_dir/tuple_element.h> -#include <__tuple_dir/tuple_size.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_size.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/valarray b/libcxx/include/valarray index 92521ed3819c..09a7c9016c99 100644 --- a/libcxx/include/valarray +++ b/libcxx/include/valarray @@ -116,6 +116,8 @@ public: size_t start() const; size_t size() const; size_t stride() const; + + friend bool operator==(const slice& x, const slice& y); // since C++20 }; template <class T> @@ -351,8 +353,10 @@ template <class T> unspecified2 end(const valarray<T>& v); #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__functional/operations.h> +#include <__memory/addressof.h> #include <__memory/allocator.h> #include <__memory/uninitialized_algorithms.h> +#include <__type_traits/decay.h> #include <__type_traits/remove_reference.h> #include <__utility/move.h> #include <__utility/swap.h> @@ -400,10 +404,18 @@ public: _LIBCPP_INLINE_VISIBILITY size_t start() const {return __start_;} _LIBCPP_INLINE_VISIBILITY size_t size() const {return __size_;} _LIBCPP_INLINE_VISIBILITY size_t stride() const {return __stride_;} + +#if _LIBCPP_STD_VER >= 20 + + _LIBCPP_HIDE_FROM_ABI friend bool operator==(const slice& __x, const slice& __y) { + return __x.start() == __y.start() && __x.size() == __y.size() && __x.stride() == __y.stride(); + } + +#endif }; template <class _Tp> class _LIBCPP_TEMPLATE_VIS slice_array; -class _LIBCPP_TYPE_VIS gslice; +class _LIBCPP_EXPORTED_FROM_ABI gslice; template <class _Tp> class _LIBCPP_TEMPLATE_VIS gslice_array; template <class _Tp> class _LIBCPP_TEMPLATE_VIS mask_array; template <class _Tp> class _LIBCPP_TEMPLATE_VIS indirect_array; @@ -432,7 +444,7 @@ template <class _Op, class _A0> struct _UnaryOp { typedef typename _Op::__result_type __result_type; - typedef typename decay<__result_type>::type value_type; + using value_type = __decay_t<__result_type>; _Op __op_; _A0 __a0_; @@ -451,7 +463,7 @@ template <class _Op, class _A0, class _A1> struct _BinaryOp { typedef typename _Op::__result_type __result_type; - typedef typename decay<__result_type>::type value_type; + using value_type = __decay_t<__result_type>; _Op __op_; _A0 __a0_; @@ -1104,18 +1116,18 @@ private: valarray& __assign_range(const value_type* __f, const value_type* __l); }; -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 template<class _Tp, size_t _Size> valarray(const _Tp(&)[_Size], size_t) -> valarray<_Tp>; #endif -extern template _LIBCPP_FUNC_VIS void valarray<size_t>::resize(size_t, size_t); +extern template _LIBCPP_EXPORTED_FROM_ABI void valarray<size_t>::resize(size_t, size_t); template <class _Op, class _Tp> struct _UnaryOp<_Op, valarray<_Tp> > { typedef typename _Op::__result_type __result_type; - typedef typename decay<__result_type>::type value_type; + using value_type = __decay_t<__result_type>; _Op __op_; const valarray<_Tp>& __a0_; @@ -1134,7 +1146,7 @@ template <class _Op, class _Tp, class _A1> struct _BinaryOp<_Op, valarray<_Tp>, _A1> { typedef typename _Op::__result_type __result_type; - typedef typename decay<__result_type>::type value_type; + using value_type = __decay_t<__result_type>; _Op __op_; const valarray<_Tp>& __a0_; @@ -1155,7 +1167,7 @@ template <class _Op, class _A0, class _Tp> struct _BinaryOp<_Op, _A0, valarray<_Tp> > { typedef typename _Op::__result_type __result_type; - typedef typename decay<__result_type>::type value_type; + using value_type = __decay_t<__result_type>; _Op __op_; _A0 __a0_; @@ -1176,7 +1188,7 @@ template <class _Op, class _Tp> struct _BinaryOp<_Op, valarray<_Tp>, valarray<_Tp> > { typedef typename _Op::__result_type __result_type; - typedef typename decay<__result_type>::type value_type; + using value_type = __decay_t<__result_type>; _Op __op_; const valarray<_Tp>& __a0_; @@ -1326,7 +1338,6 @@ private: {} template <class> friend class valarray; - template <class> friend class sliceExpr; }; template <class _Tp> @@ -1527,7 +1538,7 @@ slice_array<_Tp>::operator=(const value_type& __x) const // gslice -class _LIBCPP_TYPE_VIS gslice +class _LIBCPP_EXPORTED_FROM_ABI gslice { valarray<size_t> __size_; valarray<size_t> __stride_; @@ -2818,20 +2829,20 @@ valarray<_Tp>::valarray(size_t __n) if (__n) { __begin_ = __end_ = allocator<value_type>().allocate(__n); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (size_t __n_left = __n; __n_left; --__n_left, ++__end_) ::new ((void*)__end_) value_type(); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __clear(__n); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -2852,20 +2863,20 @@ valarray<_Tp>::valarray(const value_type* __p, size_t __n) if (__n) { __begin_ = __end_ = allocator<value_type>().allocate(__n); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (size_t __n_left = __n; __n_left; ++__end_, ++__p, --__n_left) ::new ((void*)__end_) value_type(*__p); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __clear(__n); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -2877,20 +2888,20 @@ valarray<_Tp>::valarray(const valarray& __v) if (__v.size()) { __begin_ = __end_ = allocator<value_type>().allocate(__v.size()); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (value_type* __p = __v.__begin_; __p != __v.__end_; ++__end_, ++__p) ::new ((void*)__end_) value_type(*__p); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __clear(__v.size()); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -2914,21 +2925,21 @@ valarray<_Tp>::valarray(initializer_list<value_type> __il) if (__n) { __begin_ = __end_ = allocator<value_type>().allocate(__n); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS size_t __n_left = __n; for (const value_type* __p = __il.begin(); __n_left; ++__end_, ++__p, --__n_left) ::new ((void*)__end_) value_type(*__p); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __clear(__n); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -2943,21 +2954,21 @@ valarray<_Tp>::valarray(const slice_array<value_type>& __sa) if (__n) { __begin_ = __end_ = allocator<value_type>().allocate(__n); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS size_t __n_left = __n; for (const value_type* __p = __sa.__vp_; __n_left; ++__end_, __p += __sa.__stride_, --__n_left) ::new ((void*)__end_) value_type(*__p); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __clear(__n); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -2970,23 +2981,23 @@ valarray<_Tp>::valarray(const gslice_array<value_type>& __ga) if (__n) { __begin_ = __end_ = allocator<value_type>().allocate(__n); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef const size_t* _Ip; const value_type* __s = __ga.__vp_; for (_Ip __i = __ga.__1d_.__begin_, __e = __ga.__1d_.__end_; __i != __e; ++__i, ++__end_) ::new ((void*)__end_) value_type(__s[*__i]); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __clear(__n); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -2999,23 +3010,23 @@ valarray<_Tp>::valarray(const mask_array<value_type>& __ma) if (__n) { __begin_ = __end_ = allocator<value_type>().allocate(__n); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef const size_t* _Ip; const value_type* __s = __ma.__vp_; for (_Ip __i = __ma.__1d_.__begin_, __e = __ma.__1d_.__end_; __i != __e; ++__i, ++__end_) ::new ((void*)__end_) value_type(__s[*__i]); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __clear(__n); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -3028,23 +3039,23 @@ valarray<_Tp>::valarray(const indirect_array<value_type>& __ia) if (__n) { __begin_ = __end_ = allocator<value_type>().allocate(__n); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS typedef const size_t* _Ip; const value_type* __s = __ia.__vp_; for (_Ip __i = __ia.__1d_.__begin_, __e = __ia.__1d_.__end_; __i != __e; ++__i, ++__end_) ::new ((void*)__end_) value_type(__s[*__i]); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __clear(__n); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -3753,20 +3764,20 @@ valarray<_Tp>::resize(size_t __n, value_type __x) if (__n) { __begin_ = __end_ = allocator<value_type>().allocate(__n); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS for (size_t __n_left = __n; __n_left; --__n_left, ++__end_) ::new ((void*)__end_) value_type(__x); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { __clear(__n); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -4933,8 +4944,11 @@ _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <algorithm> # include <concepts> +# include <cstdlib> # include <cstring> # include <functional> +# include <stdexcept> +# include <type_traits> #endif #endif // _LIBCPP_VALARRAY diff --git a/libcxx/include/variant b/libcxx/include/variant index 13c89822ca77..7df2e87cf3bf 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -210,10 +210,12 @@ namespace std { #include <__compare/compare_three_way_result.h> #include <__compare/three_way_comparable.h> #include <__config> +#include <__exception/exception.h> #include <__functional/hash.h> #include <__functional/invoke.h> #include <__functional/operations.h> #include <__functional/unary_function.h> +#include <__memory/addressof.h> #include <__type_traits/add_const.h> #include <__type_traits/add_cv.h> #include <__type_traits/add_pointer.h> @@ -231,12 +233,13 @@ namespace std { #include <__type_traits/remove_const.h> #include <__type_traits/type_identity.h> #include <__type_traits/void_t.h> +#include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> #include <__utility/swap.h> #include <__variant/monostate.h> -#include <exception> +#include <__verbose_abort> #include <initializer_list> #include <limits> #include <new> @@ -257,7 +260,7 @@ _LIBCPP_PUSH_MACROS namespace std { // explicitly not using versioning namespace -class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS bad_variant_access : public exception { +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS bad_variant_access : public exception { public: const char* what() const _NOEXCEPT override; }; @@ -266,7 +269,7 @@ public: _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 // Light N-dimensional array of function pointers. Used in place of std::array to avoid // adding a dependency. @@ -285,10 +288,10 @@ _LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS void __throw_bad_variant_access() { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS throw bad_variant_access(); #else - _VSTD::abort(); + _LIBCPP_VERBOSE_ABORT("bad_variant_access was thrown in -fno-exceptions mode"); #endif } @@ -547,7 +550,7 @@ private: } template <class _Fp, class... _Fs> - static constexpr void __std_visit_visitor_return_type_check() { + static _LIBCPP_HIDE_FROM_ABI constexpr void __std_visit_visitor_return_type_check() { static_assert( __all<is_same_v<_Fp, _Fs>...>::value, "`std::visit` requires the visitor to have a single return type."); @@ -594,9 +597,9 @@ private: template <class _Fp, class _Vp, class... _Vs> _LIBCPP_HIDE_FROM_ABI static constexpr auto __make_fdiagonal() { - constexpr size_t _Np = __remove_cvref_t<_Vp>::__size(); - static_assert(__all<(_Np == __remove_cvref_t<_Vs>::__size())...>::value); - return __make_fdiagonal_impl<_Fp, _Vp, _Vs...>(make_index_sequence<_Np>{}); + constexpr size_t __np = __remove_cvref_t<_Vp>::__size(); + static_assert(__all<(__np == __remove_cvref_t<_Vs>::__size())...>::value); + return __make_fdiagonal_impl<_Fp, _Vp, _Vs...>(make_index_sequence<__np>{}); } template <class _Fp, class... _Vs, size_t... _Is> @@ -660,7 +663,7 @@ struct __variant { _VSTD::forward<_Vs>(__vs)...); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Rp, class _Visitor, class... _Vs> _LIBCPP_HIDE_FROM_ABI static constexpr _Rp __visit_value(_Visitor&& __visitor, @@ -673,7 +676,7 @@ struct __variant { private: template <class _Visitor, class... _Values> - static constexpr void __std_visit_exhaustive_visitor_check() { + static _LIBCPP_HIDE_FROM_ABI constexpr void __std_visit_exhaustive_visitor_check() { static_assert(is_invocable_v<_Visitor, _Values...>, "`std::visit` requires the visitor to be exhaustive."); } @@ -692,7 +695,7 @@ private: _Visitor&& __visitor; }; -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Rp, class _Visitor> struct __value_visitor_return_type { template <class... _Alts> @@ -721,7 +724,7 @@ private: return __value_visitor<_Visitor>{_VSTD::forward<_Visitor>(__visitor)}; } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Rp, class _Visitor> _LIBCPP_HIDE_FROM_ABI static constexpr auto __make_value_visitor(_Visitor&& __visitor) { @@ -1034,10 +1037,10 @@ protected: __a.__value = _VSTD::forward<_Arg>(__arg); } else { struct { - void operator()(true_type) const { + _LIBCPP_HIDE_FROM_ABI void operator()(true_type) const { __this->__emplace<_Ip>(_VSTD::forward<_Arg>(__arg)); } - void operator()(false_type) const { + _LIBCPP_HIDE_FROM_ABI void operator()(false_type) const { __this->__emplace<_Ip>(_Tp(_VSTD::forward<_Arg>(__arg))); } __assignment* __this; @@ -1155,10 +1158,10 @@ class _LIBCPP_TEMPLATE_VIS __impl public: using __base_type::__base_type; // get in_place_index_t constructor & friends - __impl(__impl const&) = default; - __impl(__impl&&) = default; - __impl& operator=(__impl const&) = default; - __impl& operator=(__impl&&) = default; + _LIBCPP_HIDE_FROM_ABI __impl(__impl const&) = default; + _LIBCPP_HIDE_FROM_ABI __impl(__impl&&) = default; + _LIBCPP_HIDE_FROM_ABI __impl& operator=(__impl const&) = default; + _LIBCPP_HIDE_FROM_ABI __impl& operator=(__impl&&) = default; template <size_t _Ip, class _Arg> _LIBCPP_HIDE_FROM_ABI @@ -1187,7 +1190,7 @@ public: _VSTD::swap(__lhs, __rhs); } __impl __tmp(_VSTD::move(*__rhs)); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS if constexpr (__all<is_nothrow_move_constructible_v<_Types>...>::value) { this->__generic_construct(*__rhs, _VSTD::move(*__lhs)); } else { @@ -1271,7 +1274,7 @@ struct __all_overloads : _Bases... { using _Bases::operator()...; }; -template <class IdxSeq> +template <class _IdxSeq> struct __make_overloads_imp; template <size_t ..._Idx> @@ -1291,7 +1294,7 @@ using __best_match_t = } // namespace __variant_detail template <class... _Types> -class _LIBCPP_TEMPLATE_VIS variant +class _LIBCPP_TEMPLATE_VIS _LIBCPP_DECLSPEC_EMPTY_BASES variant : private __sfinae_ctor_base< __all<is_copy_constructible_v<_Types>...>::value, __all<is_move_constructible_v<_Types>...>::value>, @@ -1323,8 +1326,8 @@ public: constexpr variant() noexcept(is_nothrow_default_constructible_v<__first_type>) : __impl_(in_place_index<0>) {} - constexpr variant(const variant&) = default; - constexpr variant(variant&&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr variant(const variant&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr variant(variant&&) = default; template < class _Arg, @@ -1393,10 +1396,10 @@ public: is_nothrow_constructible_v<_Tp, initializer_list< _Up>&, _Args...>) : __impl_(in_place_index<_Ip>, __il, _VSTD::forward<_Args>(__args)...) {} - ~variant() = default; + _LIBCPP_HIDE_FROM_ABI ~variant() = default; - constexpr variant& operator=(const variant&) = default; - constexpr variant& operator=(variant&&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr variant& operator=(const variant&) = default; + _LIBCPP_HIDE_FROM_ABI constexpr variant& operator=(variant&&) = default; template < class _Arg, @@ -1652,7 +1655,7 @@ constexpr bool operator==(const variant<_Types...>& __lhs, return __variant::__visit_value_at(__lhs.index(), __convert_to_bool<equal_to<>>{}, __lhs, __rhs); } -# if _LIBCPP_STD_VER > 17 +# if _LIBCPP_STD_VER >= 20 template <class... _Types> requires (three_way_comparable<_Types> && ...) _LIBCPP_HIDE_FROM_ABI constexpr common_comparison_category_t<compare_three_way_result_t<_Types>...> @@ -1671,7 +1674,7 @@ operator<=>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) { return __variant::__visit_value_at(__lhs.index(), __three_way, __lhs, __rhs); } -# endif // _LIBCPP_STD_VER > 17 +# endif // _LIBCPP_STD_VER >= 20 template <class... _Types> _LIBCPP_HIDE_FROM_ABI @@ -1757,7 +1760,7 @@ constexpr decltype(auto) visit(_Visitor&& __visitor, _Vs&&... __vs) { _VSTD::forward<_Vs>(__vs)...); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template < class _Rp, class _Visitor, class... _Vs, typename = void_t<decltype(_VSTD::__as_variant(std::declval<_Vs>()))...> > @@ -1824,13 +1827,14 @@ constexpr auto&& __unchecked_get(variant<_Types...>& __v) noexcept { return std::__unchecked_get<__find_exactly_one_t<_Tp, _Types...>::value>(__v); } -#endif // _LIBCPP_STD_VER > 14 +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <exception> # include <type_traits> # include <typeinfo> # include <utility> diff --git a/libcxx/include/vector b/libcxx/include/vector index 4b7ae130a7bc..139e4d13c1e7 100644 --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -41,6 +41,8 @@ public: vector(size_type n, const value_type& value, const allocator_type& = allocator_type()); template <class InputIterator> vector(InputIterator first, InputIterator last, const allocator_type& = allocator_type()); + template<container-compatible-range<T> R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); // C++23 vector(const vector& x); vector(vector&& x) noexcept(is_nothrow_move_constructible<allocator_type>::value); @@ -55,6 +57,8 @@ public: vector& operator=(initializer_list<value_type> il); template <class InputIterator> void assign(InputIterator first, InputIterator last); + template<container-compatible-range<T> R> + constexpr void assign_range(R&& rg); // C++23 void assign(size_type n, const value_type& u); void assign(initializer_list<value_type> il); @@ -99,6 +103,8 @@ public: void push_back(value_type&& x); template <class... Args> reference emplace_back(Args&&... args); // reference in C++17 + template<container-compatible-range<T> R> + constexpr void append_range(R&& rg); // C++23 void pop_back(); template <class... Args> iterator emplace(const_iterator position, Args&&... args); @@ -107,6 +113,8 @@ public: iterator insert(const_iterator position, size_type n, const value_type& x); template <class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<container-compatible-range<T> R> + constexpr iterator insert_range(const_iterator position, R&& rg); // C++23 iterator insert(const_iterator position, initializer_list<value_type> il); iterator erase(const_iterator position); @@ -165,6 +173,8 @@ public: vector(size_type n, const value_type& value, const allocator_type& = allocator_type()); template <class InputIterator> vector(InputIterator first, InputIterator last, const allocator_type& = allocator_type()); + template<container-compatible-range<bool> R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); vector(const vector& x); vector(vector&& x) noexcept(is_nothrow_move_constructible<allocator_type>::value); @@ -179,6 +189,8 @@ public: vector& operator=(initializer_list<value_type> il); template <class InputIterator> void assign(InputIterator first, InputIterator last); + template<container-compatible-range<T> R> + constexpr void assign_range(R&& rg); // C++23 void assign(size_type n, const value_type& u); void assign(initializer_list<value_type> il); @@ -218,6 +230,8 @@ public: void push_back(const value_type& x); template <class... Args> reference emplace_back(Args&&... args); // C++14; reference in C++17 + template<container-compatible-range<T> R> + constexpr void append_range(R&& rg); // C++23 void pop_back(); template <class... Args> iterator emplace(const_iterator position, Args&&... args); // C++14 @@ -225,6 +239,8 @@ public: iterator insert(const_iterator position, size_type n, const value_type& x); template <class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<container-compatible-range<T> R> + constexpr iterator insert_range(const_iterator position, R&& rg); // C++23 iterator insert(const_iterator position, initializer_list<value_type> il); iterator erase(const_iterator position); @@ -247,14 +263,21 @@ template <class InputIterator, class Allocator = allocator<typename iterator_tra vector(InputIterator, InputIterator, Allocator = Allocator()) -> vector<typename iterator_traits<InputIterator>::value_type, Allocator>; // C++17 +template<ranges::input_range R, class Allocator = allocator<ranges::range_value_t<R>>> + vector(from_range_t, R&&, Allocator = Allocator()) + -> vector<ranges::range_value_t<R>, Allocator>; // C++23 + template <class Allocator> struct hash<std::vector<bool, Allocator>>; -template <class T, class Allocator> bool operator==(const vector<T,Allocator>& x, const vector<T,Allocator>& y); -template <class T, class Allocator> bool operator< (const vector<T,Allocator>& x, const vector<T,Allocator>& y); -template <class T, class Allocator> bool operator!=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); -template <class T, class Allocator> bool operator> (const vector<T,Allocator>& x, const vector<T,Allocator>& y); -template <class T, class Allocator> bool operator>=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); -template <class T, class Allocator> bool operator<=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); +template <class T, class Allocator> bool operator==(const vector<T,Allocator>& x, const vector<T,Allocator>& y); // constexpr since C++20 +template <class T, class Allocator> bool operator!=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); // removed in C++20 +template <class T, class Allocator> bool operator< (const vector<T,Allocator>& x, const vector<T,Allocator>& y); // removed in C++20 +template <class T, class Allocator> bool operator> (const vector<T,Allocator>& x, const vector<T,Allocator>& y); // removed in C++20 +template <class T, class Allocator> bool operator>=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); // removed in C++20 +template <class T, class Allocator> bool operator<=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); // removed in C++20 +template <class T, class Allocator> constexpr + constexpr synth-three-way-result<T> operator<=>(const vector<T, Allocator>& x, + const vector<T, Allocator>& y); // since C++20 template <class T, class Allocator> void swap(vector<T,Allocator>& x, vector<T,Allocator>& y) @@ -262,10 +285,10 @@ void swap(vector<T,Allocator>& x, vector<T,Allocator>& y) template <class T, class Allocator, class U> typename vector<T, Allocator>::size_type -erase(vector<T, Allocator>& c, const U& value); // C++20 +erase(vector<T, Allocator>& c, const U& value); // since C++20 template <class T, class Allocator, class Predicate> typename vector<T, Allocator>::size_type -erase_if(vector<T, Allocator>& c, Predicate pred); // C++20 +erase_if(vector<T, Allocator>& c, Predicate pred); // since C++20 template<class T> @@ -281,44 +304,57 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++ #include <__algorithm/copy.h> #include <__algorithm/equal.h> #include <__algorithm/fill_n.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/remove.h> #include <__algorithm/remove_if.h> #include <__algorithm/rotate.h> #include <__algorithm/unwrap_iter.h> #include <__assert> // all public C++ headers provide the assertion handler +#include <__availability> #include <__bit_reference> #include <__concepts/same_as.h> #include <__config> -#include <__debug> #include <__format/enable_insertable.h> #include <__format/formatter.h> +#include <__format/formatter_bool.h> #include <__functional/hash.h> #include <__functional/unary_function.h> #include <__iterator/advance.h> +#include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> #include <__iterator/wrap_iter.h> +#include <__memory/addressof.h> #include <__memory/allocate_at_least.h> +#include <__memory/allocator_traits.h> #include <__memory/pointer_traits.h> #include <__memory/swap_allocator.h> #include <__memory/temp_value.h> #include <__memory/uninitialized_algorithms.h> #include <__memory_resource/polymorphic_allocator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/container_compatible_range.h> +#include <__ranges/from_range.h> +#include <__ranges/size.h> #include <__split_buffer> #include <__type_traits/is_allocator.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_nothrow_move_assignable.h> #include <__type_traits/noexcept_move_assign_container.h> +#include <__type_traits/type_identity.h> #include <__utility/exception_guard.h> #include <__utility/forward.h> #include <__utility/move.h> +#include <__utility/pair.h> #include <__utility/swap.h> #include <climits> -#include <cstdlib> #include <cstring> #include <iosfwd> // for forward declaration of vector #include <limits> #include <stdexcept> -#include <type_traits> #include <version> // standard-mandated includes @@ -341,7 +377,6 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++ _LIBCPP_PUSH_MACROS #include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp, class _Allocator /* = allocator<_Tp> */> @@ -376,7 +411,6 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) { - std::__debug_db_insert_c(this); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(const allocator_type& __a) #if _LIBCPP_STD_VER <= 14 @@ -386,10 +420,9 @@ public: #endif : __end_cap_(nullptr, __a) { - std::__debug_db_insert_c(this); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a); #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(size_type __n, const value_type& __x); @@ -399,7 +432,6 @@ public: vector(size_type __n, const value_type& __x, const allocator_type& __a) : __end_cap_(nullptr, __a) { - std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); @@ -408,12 +440,12 @@ public: } template <class _InputIterator, - __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIterator>::value && + __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value && is_constructible<value_type, typename iterator_traits<_InputIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_InputIterator __first, _InputIterator __last); template <class _InputIterator, - __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIterator>::value && + __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value && is_constructible<value_type, typename iterator_traits<_InputIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI @@ -421,29 +453,41 @@ public: template < class _ForwardIterator, - __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && + __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && is_constructible<value_type, typename iterator_traits<_ForwardIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_ForwardIterator __first, _ForwardIterator __last); template <class _ForwardIterator, - __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && + __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && is_constructible<value_type, typename iterator_traits<_ForwardIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI constexpr vector(from_range_t, _Range&& __range, + const allocator_type& __alloc = allocator_type()) : __end_cap_(nullptr, __alloc) { + if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + __init_with_size(ranges::begin(__range), ranges::end(__range), __n); + + } else { + __init_with_sentinel(ranges::begin(__range), ranges::end(__range)); + } + } +#endif + private: class __destroy_vector { public: - _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {} + _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() { - __vec_.__annotate_delete(); - std::__debug_db_erase_c(std::addressof(__vec_)); - if (__vec_.__begin_ != nullptr) { __vec_.__clear(); + __vec_.__annotate_delete(); __alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.capacity()); } } @@ -474,7 +518,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(vector&& __x) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 noexcept; #else _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value); @@ -487,17 +531,31 @@ public: _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); template <class _InputIterator, - __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIterator>::value && + __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value && is_constructible<value_type, typename iterator_traits<_InputIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(_InputIterator __first, _InputIterator __last); template < class _ForwardIterator, - __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && + __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && is_constructible<value_type, typename iterator_traits<_ForwardIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(_ForwardIterator __first, _ForwardIterator __last); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + constexpr void assign_range(_Range&& __range) { + if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + __assign_with_size(ranges::begin(__range), ranges::end(__range), __n); + + } else { + __assign_with_sentinel(ranges::begin(__range), ranges::end(__range)); + } + } +#endif + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const_reference __u); #ifndef _LIBCPP_CXX03_LANG @@ -561,22 +619,22 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT { - _LIBCPP_ASSERT(!empty(), "front() called on an empty vector"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector"); return *this->__begin_; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT { - _LIBCPP_ASSERT(!empty(), "front() called on an empty vector"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector"); return *this->__begin_; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT { - _LIBCPP_ASSERT(!empty(), "back() called on an empty vector"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector"); return *(this->__end_ - 1); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT { - _LIBCPP_ASSERT(!empty(), "back() called on an empty vector"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector"); return *(this->__end_ - 1); } @@ -594,12 +652,20 @@ public: template <class... _Args> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 reference emplace_back(_Args&&... __args); #else void emplace_back(_Args&&... __args); #endif +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + constexpr void append_range(_Range&& __range) { + insert_range(end(), std::forward<_Range>(__range)); + } +#endif + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back(); @@ -613,15 +679,29 @@ public: iterator insert(const_iterator __position, size_type __n, const_reference __x); template <class _InputIterator, - __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIterator>::value && + __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value && is_constructible< value_type, typename iterator_traits<_InputIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, _InputIterator __first, _InputIterator __last); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<_Tp> _Range> + _LIBCPP_HIDE_FROM_ABI + constexpr iterator insert_range(const_iterator __position, _Range&& __range) { + if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + return __insert_with_size(__position, ranges::begin(__range), ranges::end(__range), __n); + + } else { + return __insert_with_sentinel(__position, ranges::begin(__range), ranges::end(__range)); + } + } +#endif + template < class _ForwardIterator, - __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && + __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && is_constructible< value_type, typename iterator_traits<_ForwardIterator>::reference>::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator @@ -642,7 +722,6 @@ public: size_type __old_size = size(); __clear(); __annotate_shrink(__old_size); - std::__debug_db_invalidate_all(this); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz); @@ -658,23 +737,12 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const; -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - - bool __dereferenceable(const const_iterator* __i) const; - bool __decrementable(const const_iterator* __i) const; - bool __addable(const const_iterator* __i, ptrdiff_t __n) const; - bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - private: pointer __begin_ = nullptr; pointer __end_ = nullptr; __compressed_pair<pointer, allocator_type> __end_cap_ = __compressed_pair<pointer, allocator_type>(nullptr, __default_init_tag()); - _LIBCPP_HIDE_FROM_ABI void __invalidate_iterators_past(pointer __new_last); - // Allocate space for __n objects // throws length_error if __n > max_size() // throws (probably bad_alloc) if memory run out @@ -698,16 +766,56 @@ private: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x); - template <class _ForwardIterator, __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value, int> = 0> - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void - __construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n); + template <class _InputIterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __init_with_size(_InputIterator __first, _Sentinel __last, size_type __n) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); + + if (__n > 0) { + __vallocate(__n); + __construct_at_end(__first, __last, __n); + } + + __guard.__complete(); + } + + template <class _InputIterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __init_with_sentinel(_InputIterator __first, _Sentinel __last) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); + + for (; __first != __last; ++__first) + emplace_back(*__first); + + __guard.__complete(); + } + + template <class _Iterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __assign_with_sentinel(_Iterator __first, _Sentinel __last); + + template <class _ForwardIterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __assign_with_size(_ForwardIterator __first, _Sentinel __last, difference_type __n); + + template <class _InputIterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + iterator __insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last); + + template <class _Iterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + iterator __insert_with_size(const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n); + + template <class _InputIterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __append(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __append(size_type __n, const_reference __x); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - iterator __make_iter(pointer __p) _NOEXCEPT { return iterator(this, __p); } + iterator __make_iter(pointer __p) _NOEXCEPT { return iterator(__p); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI - const_iterator __make_iter(const_pointer __p) const _NOEXCEPT { return const_iterator(this, __p); } + const_iterator __make_iter(const_pointer __p) const _NOEXCEPT { return const_iterator(__p); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_range(pointer __from_s, pointer __from_e, pointer __to); @@ -718,8 +826,6 @@ private: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last) _NOEXCEPT { - if (!__libcpp_is_constant_evaluated()) - __invalidate_iterators_past(__new_last); size_type __old_size = size(); __base_destruct_at_end(__new_last); __annotate_shrink(__old_size); @@ -734,17 +840,19 @@ private: inline void __emplace_back_slow_path(_Args&&... __args); // The following functions are no-ops outside of AddressSanitizer mode. - // We call annotatations only for the default Allocator because other allocators - // may not meet the AddressSanitizer alignment constraints. - // See the documentation for __sanitizer_annotate_contiguous_container for more details. + // We call annotations for every allocator, unless explicitly disabled. + // + // To disable annotations for a particular allocator, change value of + // __asan_annotate_container_with_allocator to false. + // For more details, see the "Using libc++" documentation page or + // the documentation for __sanitizer_annotate_contiguous_container. #ifndef _LIBCPP_HAS_NO_ASAN _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_contiguous_container(const void *__beg, const void *__end, const void *__old_mid, const void *__new_mid) const { - - if (!__libcpp_is_constant_evaluated() && __beg && is_same<allocator_type, __default_allocator_type>::value) + if (!__libcpp_is_constant_evaluated() && __beg != nullptr && __asan_annotate_container_with_allocator<_Allocator>::value) __sanitizer_annotate_contiguous_container(__beg, __end, __old_mid, __new_mid); } #else @@ -866,6 +974,7 @@ private: if (__alloc() != __c.__alloc()) { __clear(); + __annotate_delete(); __alloc_traits::deallocate(__alloc(), this->__begin_, capacity()); this->__begin_ = this->__end_ = __end_cap() = nullptr; } @@ -892,7 +1001,7 @@ private: #if _LIBCPP_STD_VER >= 17 template<class _InputIterator, class _Alloc = allocator<__iter_value_type<_InputIterator>>, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Alloc>::value> > vector(_InputIterator, _InputIterator) @@ -900,13 +1009,22 @@ vector(_InputIterator, _InputIterator) template<class _InputIterator, class _Alloc, - class = enable_if_t<__is_cpp17_input_iterator<_InputIterator>::value>, + class = enable_if_t<__has_input_iterator_category<_InputIterator>::value>, class = enable_if_t<__is_allocator<_Alloc>::value> > vector(_InputIterator, _InputIterator, _Alloc) -> vector<__iter_value_type<_InputIterator>, _Alloc>; #endif +#if _LIBCPP_STD_VER >= 23 +template <ranges::input_range _Range, + class _Alloc = allocator<ranges::range_value_t<_Range>>, + class = enable_if_t<__is_allocator<_Alloc>::value> + > +vector(from_range_t, _Range&&, _Alloc = _Alloc()) + -> vector<ranges::range_value_t<_Range>, _Alloc>; +#endif + template <class _Tp, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 void @@ -922,7 +1040,6 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a std::swap(this->__end_cap(), __v.__end_cap()); __v.__first_ = __v.__begin_; __annotate_new(size()); - std::__debug_db_invalidate_all(this); } template <class _Tp, class _Allocator> @@ -942,7 +1059,6 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a std::swap(this->__end_cap(), __v.__end_cap()); __v.__first_ = __v.__begin_; __annotate_new(size()); - std::__debug_db_invalidate_all(this); return __r; } @@ -954,6 +1070,7 @@ vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT if (this->__begin_ != nullptr) { clear(); + __annotate_delete(); __alloc_traits::deallocate(this->__alloc(), this->__begin_, capacity()); this->__begin_ = this->__end_ = this->__end_cap() = nullptr; } @@ -1021,10 +1138,9 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) } template <class _Tp, class _Allocator> -template <class _ForwardIterator, __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value, int> > +template <class _InputIterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 void -vector<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n) -{ +vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) { _ConstructTransaction __tx(*this, __n); __tx.__pos_ = std::__uninitialized_allocator_copy(__alloc(), __first, __last, __tx.__pos_); } @@ -1074,7 +1190,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); @@ -1083,14 +1198,13 @@ vector<_Tp, _Allocator>::vector(size_type __n) __guard.__complete(); } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Tp, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const allocator_type& __a) : __end_cap_(nullptr, __a) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); @@ -1105,7 +1219,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); if (__n > 0) { __vallocate(__n); @@ -1115,69 +1228,47 @@ vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x) } template <class _Tp, class _Allocator> -template <class _InputIterator, __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIterator>::value && +template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value && is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); - for (; __first != __last; ++__first) - emplace_back(*__first); - __guard.__complete(); + __init_with_sentinel(__first, __last); } template <class _Tp, class _Allocator> -template <class _InputIterator, __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIterator>::value && +template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value && is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : __end_cap_(nullptr, __a) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); - for (; __first != __last; ++__first) - emplace_back(*__first); - __guard.__complete(); + __init_with_sentinel(__first, __last); } template <class _Tp, class _Allocator> -template <class _ForwardIterator, __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && +template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); - size_type __n = static_cast<size_type>(std::distance(__first, __last)); - if (__n > 0) - { - __vallocate(__n); - __construct_at_end(__first, __last, __n); - } - __guard.__complete(); + size_type __n = static_cast<size_type>(std::distance(__first, __last)); + __init_with_size(__first, __last, __n); } template <class _Tp, class _Allocator> -template <class _ForwardIterator, __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && +template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a) : __end_cap_(nullptr, __a) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); - size_type __n = static_cast<size_type>(std::distance(__first, __last)); - if (__n > 0) - { - __vallocate(__n); - __construct_at_end(__first, __last, __n); - } - __guard.__complete(); + size_type __n = static_cast<size_type>(std::distance(__first, __last)); + __init_with_size(__first, __last, __n); } template <class _Tp, class _Allocator> @@ -1185,15 +1276,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(const vector& __x) : __end_cap_(nullptr, __alloc_traits::select_on_container_copy_construction(__x.__alloc())) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); - size_type __n = __x.size(); - if (__n > 0) - { - __vallocate(__n); - __construct_at_end(__x.__begin_, __x.__end_, __n); - } - __guard.__complete(); + __init_with_size(__x.__begin_, __x.__end_, __x.size()); } template <class _Tp, class _Allocator> @@ -1201,30 +1284,20 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(const vector& __x, const __type_identity_t<allocator_type>& __a) : __end_cap_(nullptr, __a) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); - size_type __n = __x.size(); - if (__n > 0) - { - __vallocate(__n); - __construct_at_end(__x.__begin_, __x.__end_, __n); - } - __guard.__complete(); + __init_with_size(__x.__begin_, __x.__end_, __x.size()); } template <class _Tp, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(vector&& __x) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 noexcept #else _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value) #endif : __end_cap_(nullptr, std::move(__x.__alloc())) { - std::__debug_db_insert_c(this); - std::__debug_db_swap(this, std::addressof(__x)); this->__begin_ = __x.__begin_; this->__end_ = __x.__end_; this->__end_cap() = __x.__end_cap(); @@ -1237,14 +1310,12 @@ inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_type>& __a) : __end_cap_(nullptr, __a) { - std::__debug_db_insert_c(this); if (__a == __x.__alloc()) { this->__begin_ = __x.__begin_; this->__end_ = __x.__end_; this->__end_cap() = __x.__end_cap(); __x.__begin_ = __x.__end_ = __x.__end_cap() = nullptr; - std::__debug_db_swap(this, std::addressof(__x)); } else { @@ -1263,7 +1334,6 @@ inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); if (__il.size() > 0) { __vallocate(__il.size()); @@ -1279,7 +1349,6 @@ vector<_Tp, _Allocator>::vector(initializer_list<value_type> __il, const allocat : __end_cap_(nullptr, __a) { auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - std::__debug_db_insert_c(this); if (__il.size() > 0) { __vallocate(__il.size()); @@ -1329,7 +1398,6 @@ vector<_Tp, _Allocator>::__move_assign(vector& __c, true_type) this->__end_ = __c.__end_; this->__end_cap() = __c.__end_cap(); __c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr; - std::__debug_db_swap(this, std::addressof(__c)); } template <class _Tp, class _Allocator> @@ -1347,40 +1415,52 @@ vector<_Tp, _Allocator>::operator=(const vector& __x) } template <class _Tp, class _Allocator> -template <class _InputIterator, __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIterator>::value && +template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value && is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { + __assign_with_sentinel(__first, __last); +} + +template <class _Tp, class _Allocator> +template <class _Iterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI +void vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) { clear(); for (; __first != __last; ++__first) emplace_back(*__first); } template <class _Tp, class _Allocator> -template <class _ForwardIterator, __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && +template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) { - size_type __new_size = static_cast<size_type>(std::distance(__first, __last)); + __assign_with_size(__first, __last, std::distance(__first, __last)); +} + +template <class _Tp, class _Allocator> +template <class _ForwardIterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI +void vector<_Tp, _Allocator>::__assign_with_size(_ForwardIterator __first, _Sentinel __last, difference_type __n) { + size_type __new_size = static_cast<size_type>(__n); if (__new_size <= capacity()) { - _ForwardIterator __mid = __last; - bool __growing = false; if (__new_size > size()) { - __growing = true; - __mid = __first; - std::advance(__mid, size()); - } - pointer __m = std::copy(__first, __mid, this->__begin_); - if (__growing) + _ForwardIterator __mid = std::next(__first, size()); + std::copy(__first, __mid, this->__begin_); __construct_at_end(__mid, __last, __new_size - size()); + } else + { + pointer __m = std::__copy<_ClassicAlgPolicy>(__first, __last, this->__begin_).second; this->__destruct_at_end(__m); + } } else { @@ -1388,7 +1468,6 @@ vector<_Tp, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __las __vallocate(__recommend(__new_size)); __construct_at_end(__first, __last, __new_size); } - std::__debug_db_invalidate_all(this); } template <class _Tp, class _Allocator> @@ -1411,7 +1490,6 @@ vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) __vallocate(__recommend(static_cast<size_type>(__n))); __construct_at_end(__n, __u); } - std::__debug_db_invalidate_all(this); } template <class _Tp, class _Allocator> @@ -1456,7 +1534,7 @@ inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::operator[](size_type __n) _NOEXCEPT { - _LIBCPP_ASSERT(__n < size(), "vector[] index out of bounds"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds"); return this->__begin_[__n]; } @@ -1466,7 +1544,7 @@ inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::const_reference vector<_Tp, _Allocator>::operator[](size_type __n) const _NOEXCEPT { - _LIBCPP_ASSERT(__n < size(), "vector[] index out of bounds"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds"); return this->__begin_[__n]; } @@ -1512,19 +1590,19 @@ vector<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT { if (capacity() > size()) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS allocator_type& __a = this->__alloc(); __split_buffer<value_type, allocator_type&> __v(size(), size(), __a); __swap_out_circular_buffer(__v); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -1588,7 +1666,7 @@ template <class _Tp, class _Allocator> template <class... _Args> _LIBCPP_CONSTEXPR_SINCE_CXX20 inline -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 typename vector<_Tp, _Allocator>::reference #else void @@ -1601,7 +1679,7 @@ vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) } else __emplace_back_slow_path(std::forward<_Args>(__args)...); -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return this->back(); #endif } @@ -1612,7 +1690,7 @@ inline void vector<_Tp, _Allocator>::pop_back() { - _LIBCPP_ASSERT(!empty(), "vector::pop_back called on an empty vector"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector"); this->__destruct_at_end(this->__end_ - 1); } @@ -1622,15 +1700,11 @@ inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __position) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, - "vector::erase(iterator) called with an iterator not referring to this vector"); - _LIBCPP_ASSERT(__position != end(), + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator"); difference_type __ps = __position - cbegin(); pointer __p = this->__begin_ + __ps; this->__destruct_at_end(std::move(__p + 1, this->__end_, __p)); - if (!__libcpp_is_constant_evaluated()) - this->__invalidate_iterators_past(__p - 1); return __make_iter(__p); } @@ -1639,17 +1713,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__first)) == this, - "vector::erase(iterator, iterator) called with an iterator not referring to this vector"); - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__last)) == this, - "vector::erase(iterator, iterator) called with an iterator not referring to this vector"); - - _LIBCPP_ASSERT(__first <= __last, "vector::erase(first, last) called with invalid range"); + _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range"); pointer __p = this->__begin_ + (__first - begin()); if (__first != __last) { this->__destruct_at_end(std::move(__p + (__last - __first), this->__end_, __p)); - if (!__libcpp_is_constant_evaluated()) - this->__invalidate_iterators_past(__p - 1); } return __make_iter(__p); } @@ -1679,8 +1746,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, - "vector::insert(iterator, x) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); // We can't compare unrelated pointers inside constant expressions if (!__libcpp_is_constant_evaluated() && this->__end_ < this->__end_cap()) @@ -1713,8 +1778,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, - "vector::insert(iterator, x) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); if (this->__end_ < this->__end_cap()) { @@ -1744,8 +1807,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, - "vector::emplace(iterator, x) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); if (this->__end_ < this->__end_cap()) { @@ -1775,8 +1836,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, - "vector::insert(iterator, n, x) called with an iterator not referring to this vector"); pointer __p = this->__begin_ + (__position - begin()); if (__n > 0) { @@ -1810,16 +1869,21 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_ } return __make_iter(__p); } - template <class _Tp, class _Allocator> -template <class _InputIterator, __enable_if_t<__is_exactly_cpp17_input_iterator<_InputIterator>::value && +template <class _InputIterator, __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value && is_constructible<_Tp, typename iterator_traits<_InputIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, - "vector::insert(iterator, range) called with an iterator not referring to this vector"); + return __insert_with_sentinel(__position, __first, __last); +} + +template <class _Tp, class _Allocator> +template <class _InputIterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI +typename vector<_Tp, _Allocator>::iterator +vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) { difference_type __off = __position - begin(); pointer __p = this->__begin_ + __off; allocator_type& __a = this->__alloc(); @@ -1831,24 +1895,24 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __firs __split_buffer<value_type, allocator_type&> __v(__a); if (__first != __last) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS - __v.__construct_at_end(__first, __last); +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + __v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last)); difference_type __old_size = __old_last - this->__begin_; difference_type __old_p = __p - this->__begin_; reserve(__recommend(size() + __v.size())); __p = this->__begin_ + __old_p; __old_last = this->__begin_ + __old_size; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { erase(__make_iter(__old_last), end()); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } __p = std::rotate(__p, __old_last, this->__end_); insert(__make_iter(__p), std::make_move_iterator(__v.begin()), @@ -1857,23 +1921,30 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __firs } template <class _Tp, class _Allocator> -template <class _ForwardIterator, __enable_if_t<__is_cpp17_forward_iterator<_ForwardIterator>::value && +template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value && is_constructible<_Tp, typename iterator_traits<_ForwardIterator>::reference>::value, int> > _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last) { - _LIBCPP_DEBUG_ASSERT(__get_const_db()->__find_c_from_i(std::addressof(__position)) == this, - "vector::insert(iterator, range) called with an iterator not referring to this vector"); + return __insert_with_size(__position, __first, __last, std::distance(__first, __last)); +} + +template <class _Tp, class _Allocator> +template <class _Iterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI +typename vector<_Tp, _Allocator>::iterator +vector<_Tp, _Allocator>::__insert_with_size(const_iterator __position, _Iterator __first, _Sentinel __last, + difference_type __n) { + auto __insertion_size = __n; pointer __p = this->__begin_ + (__position - begin()); - difference_type __n = std::distance(__first, __last); if (__n > 0) { if (__n <= this->__end_cap() - this->__end_) { size_type __old_n = __n; pointer __old_last = this->__end_; - _ForwardIterator __m = __last; + _Iterator __m = std::next(__first, __n); difference_type __dx = this->__end_ - __p; if (__n > __dx) { @@ -1893,7 +1964,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __fi { allocator_type& __a = this->__alloc(); __split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), __p - this->__begin_, __a); - __v.__construct_at_end(__first, __last); + __v.__construct_at_end_with_size(__first, __insertion_size); __p = __swap_out_circular_buffer(__v, __p); } } @@ -1935,16 +2006,15 @@ vector<_Tp, _Allocator>::swap(vector& __x) __is_nothrow_swappable<allocator_type>::value) #endif { - _LIBCPP_ASSERT(__alloc_traits::propagate_on_container_swap::value || - this->__alloc() == __x.__alloc(), - "vector::swap: Either propagate_on_container_swap must be true" - " or the allocators must compare equal"); + _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(__alloc_traits::propagate_on_container_swap::value || + this->__alloc() == __x.__alloc(), + "vector::swap: Either propagate_on_container_swap must be true" + " or the allocators must compare equal"); std::swap(this->__begin_, __x.__begin_); std::swap(this->__end_, __x.__end_); std::swap(this->__end_cap(), __x.__end_cap()); std::__swap_allocator(this->__alloc(), __x.__alloc(), integral_constant<bool,__alloc_traits::propagate_on_container_swap::value>()); - std::__debug_db_swap(this, std::addressof(__x)); } template <class _Tp, class _Allocator> @@ -1969,61 +2039,6 @@ vector<_Tp, _Allocator>::__invariants() const return true; } -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - -template <class _Tp, class _Allocator> -bool -vector<_Tp, _Allocator>::__dereferenceable(const const_iterator* __i) const -{ - return this->__begin_ <= __i->base() && __i->base() < this->__end_; -} - -template <class _Tp, class _Allocator> -bool -vector<_Tp, _Allocator>::__decrementable(const const_iterator* __i) const -{ - return this->__begin_ < __i->base() && __i->base() <= this->__end_; -} - -template <class _Tp, class _Allocator> -bool -vector<_Tp, _Allocator>::__addable(const const_iterator* __i, ptrdiff_t __n) const -{ - const_pointer __p = __i->base() + __n; - return this->__begin_ <= __p && __p <= this->__end_; -} - -template <class _Tp, class _Allocator> -bool -vector<_Tp, _Allocator>::__subscriptable(const const_iterator* __i, ptrdiff_t __n) const -{ - const_pointer __p = __i->base() + __n; - return this->__begin_ <= __p && __p < this->__end_; -} - -#endif // _LIBCPP_ENABLE_DEBUG_MODE - -template <class _Tp, class _Allocator> -inline _LIBCPP_HIDE_FROM_ABI -void -vector<_Tp, _Allocator>::__invalidate_iterators_past(pointer __new_last) { -#ifdef _LIBCPP_ENABLE_DEBUG_MODE - __c_node* __c = __get_db()->__find_c_and_lock(this); - for (__i_node** __p = __c->end_; __p != __c->beg_; ) { - --__p; - const_iterator* __i = static_cast<const_iterator*>((*__p)->__i_); - if (__i->base() > __new_last) { - (*__p)->__c_ = nullptr; - if (--__c->end_ != __p) - std::memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); - } - } - __get_db()->unlock(); -#else - ((void)__new_last); -#endif -} - // vector<bool> template <class _Allocator> class vector<bool, _Allocator>; @@ -2107,12 +2122,11 @@ public: private: class __destroy_vector { public: - _LIBCPP_CONSTEXPR __destroy_vector(vector& __vec) : __vec_(__vec) {} + _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() { if (__vec_.__begin_ != nullptr) __storage_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.__cap()); - std::__debug_db_invalidate_all(this); } private: @@ -2123,23 +2137,40 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~vector() { __destroy_vector(*this)(); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit vector(size_type __n); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit vector(size_type __n, const allocator_type& __a); #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(size_type __n, const value_type& __v); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(size_type __n, const value_type& __v, const allocator_type& __a); template <class _InputIterator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(_InputIterator __first, _InputIterator __last, - typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type* = 0); + typename enable_if<__has_exactly_input_iterator_category<_InputIterator>::value>::type* = 0); template <class _InputIterator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, - typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type* = 0); + typename enable_if<__has_exactly_input_iterator_category<_InputIterator>::value>::type* = 0); template <class _ForwardIterator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(_ForwardIterator __first, _ForwardIterator __last, - typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0); + typename enable_if<__has_forward_iterator_category<_ForwardIterator>::value>::type* = 0); template <class _ForwardIterator> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, - typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type* = 0); + typename enable_if<__has_forward_iterator_category<_ForwardIterator>::value>::type* = 0); + +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<bool> _Range> + _LIBCPP_HIDE_FROM_ABI constexpr + vector(from_range_t, _Range&& __range, const allocator_type& __a = allocator_type()) + : __begin_(nullptr), + __size_(0), + __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { + if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + __init_with_size(ranges::begin(__range), ranges::end(__range), __n); + + } else { + __init_with_sentinel(ranges::begin(__range), ranges::end(__range)); + } + } +#endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(const vector& __v); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(const vector& __v, const allocator_type& __a); @@ -2157,7 +2188,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector(vector&& __v) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 noexcept; #else _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value); @@ -2168,18 +2199,32 @@ public: _NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value)); template <class _InputIterator> - typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, + typename enable_if <__has_exactly_input_iterator_category<_InputIterator>::value, void >::type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 assign(_InputIterator __first, _InputIterator __last); template <class _ForwardIterator> typename enable_if < - __is_cpp17_forward_iterator<_ForwardIterator>::value, + __has_forward_iterator_category<_ForwardIterator>::value, void >::type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 assign(_ForwardIterator __first, _ForwardIterator __last); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<bool> _Range> + _LIBCPP_HIDE_FROM_ABI + constexpr void assign_range(_Range&& __range) { + if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + __assign_with_size(ranges::begin(__range), ranges::end(__range), __n); + + } else { + __assign_with_sentinel(ranges::begin(__range), ranges::end(__range)); + } + } +#endif + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void assign(size_type __n, const value_type& __x); #ifndef _LIBCPP_CXX03_LANG @@ -2254,24 +2299,32 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const {return __make_ref(__size_ - 1);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(const value_type& __x); -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class... _Args> -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference emplace_back(_Args&&... __args) #else _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args) #endif { push_back ( value_type ( std::forward<_Args>(__args)... )); -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 return this->back(); #endif } #endif +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<bool> _Range> + _LIBCPP_HIDE_FROM_ABI + constexpr void append_range(_Range&& __range) { + insert_range(end(), std::forward<_Range>(__range)); + } +#endif + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back() {--__size_;} -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class... _Args> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator emplace(const_iterator __position, _Args&&... __args) { return insert ( __position, value_type ( std::forward<_Args>(__args)... )); } @@ -2280,18 +2333,32 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __position, const value_type& __x); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __position, size_type __n, const value_type& __x); template <class _InputIterator> - typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, + typename enable_if <__has_exactly_input_iterator_category<_InputIterator>::value, iterator >::type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 insert(const_iterator __position, _InputIterator __first, _InputIterator __last); template <class _ForwardIterator> typename enable_if < - __is_cpp17_forward_iterator<_ForwardIterator>::value, + __has_forward_iterator_category<_ForwardIterator>::value, iterator >::type _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last); +#if _LIBCPP_STD_VER >= 23 + template <_ContainerCompatibleRange<bool> _Range> + _LIBCPP_HIDE_FROM_ABI + constexpr iterator insert_range(const_iterator __position, _Range&& __range) { + if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) { + auto __n = static_cast<size_type>(ranges::distance(__range)); + return __insert_with_size(__position, ranges::begin(__range), ranges::end(__range), __n); + + } else { + return __insert_with_sentinel(__position, ranges::begin(__range), ranges::end(__range)); + } + } +#endif + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator insert(const_iterator __position, initializer_list<value_type> __il) @@ -2304,7 +2371,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void clear() _NOEXCEPT {__size_ = 0;} - _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(vector&) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(vector&) #if _LIBCPP_STD_VER >= 14 _NOEXCEPT; #else @@ -2329,6 +2396,52 @@ private: std::__throw_out_of_range("vector"); } + template <class _InputIterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + void __init_with_size(_InputIterator __first, _Sentinel __last, size_type __n) { + auto __guard = std::__make_exception_guard(__destroy_vector(*this)); + + if (__n > 0) { + __vallocate(__n); + __construct_at_end(std::move(__first), std::move(__last), __n); + } + + __guard.__complete(); + } + + template <class _InputIterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + void __init_with_sentinel(_InputIterator __first, _Sentinel __last) { +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + try { +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + for (; __first != __last; ++__first) + push_back(*__first); +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS + } catch (...) { + if (__begin_ != nullptr) + __storage_traits::deallocate(__alloc(), __begin_, __cap()); + throw; + } +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + } + + template <class _Iterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __assign_with_sentinel(_Iterator __first, _Sentinel __last); + + template <class _ForwardIterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + void __assign_with_size(_ForwardIterator __first, _Sentinel __last, difference_type __ns); + + template <class _InputIterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + iterator __insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last); + + template <class _Iterator, class _Sentinel> + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI + iterator __insert_with_size(const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n); + // Allocate space for __n objects // throws length_error if __n > max_size() // throws (probably bad_alloc) if memory run out @@ -2355,13 +2468,9 @@ private: {return (__new_size + (__bits_per_word-1)) & ~((size_type)__bits_per_word-1);} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __recommend(size_type __new_size) const; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct_at_end(size_type __n, bool __x); - template <class _ForwardIterator> - typename enable_if - < - __is_cpp17_forward_iterator<_ForwardIterator>::value, - void - >::type - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); + template <class _InputIterator, class _Sentinel> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 + void __construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __append(size_type __n, const_reference __x); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference __make_ref(size_type __pos) _NOEXCEPT @@ -2436,7 +2545,6 @@ vector<bool, _Allocator>::__vdeallocate() _NOEXCEPT if (this->__begin_ != nullptr) { __storage_traits::deallocate(this->__alloc(), this->__begin_, __cap()); - std::__debug_db_invalidate_all(this); this->__begin_ = nullptr; this->__size_ = this->__cap() = 0; } @@ -2491,17 +2599,11 @@ vector<bool, _Allocator>::__construct_at_end(size_type __n, bool __x) } template <class _Allocator> -template <class _ForwardIterator> +template <class _InputIterator, class _Sentinel> _LIBCPP_CONSTEXPR_SINCE_CXX20 -typename enable_if -< - __is_cpp17_forward_iterator<_ForwardIterator>::value, - void ->::type -vector<bool, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) -{ +void vector<bool, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) { size_type __old_size = this->__size_; - this->__size_ += std::distance(__first, __last); + this->__size_ += __n; if (__old_size == 0 || ((__old_size - 1) / __bits_per_word) != ((this->__size_ - 1) / __bits_per_word)) { if (this->__size_ <= __bits_per_word) @@ -2509,7 +2611,7 @@ vector<bool, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardI else this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); } - std::copy(__first, __last, __make_iter(__old_size)); + std::__copy<_ClassicAlgPolicy>(__first, __last, __make_iter(__old_size)); } template <class _Allocator> @@ -2550,7 +2652,7 @@ vector<bool, _Allocator>::vector(size_type __n) } } -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 template <class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(size_type __n, const allocator_type& __a) @@ -2598,92 +2700,50 @@ template <class _Allocator> template <class _InputIterator> _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last, - typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type*) + typename enable_if<__has_exactly_input_iterator_category<_InputIterator>::value>::type*) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - for (; __first != __last; ++__first) - push_back(*__first); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - if (__begin_ != nullptr) - __storage_traits::deallocate(__alloc(), __begin_, __cap()); - std::__debug_db_invalidate_all(this); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS + __init_with_sentinel(__first, __last); } template <class _Allocator> template <class _InputIterator> _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a, - typename enable_if<__is_exactly_cpp17_input_iterator<_InputIterator>::value>::type*) + typename enable_if<__has_exactly_input_iterator_category<_InputIterator>::value>::type*) : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - for (; __first != __last; ++__first) - push_back(*__first); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - if (__begin_ != nullptr) - __storage_traits::deallocate(__alloc(), __begin_, __cap()); - std::__debug_db_invalidate_all(this); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS + __init_with_sentinel(__first, __last); } template <class _Allocator> template <class _ForwardIterator> _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, - typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type*) + typename enable_if<__has_forward_iterator_category<_ForwardIterator>::value>::type*) : __begin_(nullptr), __size_(0), __cap_alloc_(0, __default_init_tag()) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - size_type __n = static_cast<size_type>(std::distance(__first, __last)); - if (__n > 0) - { - __vallocate(__n); - __construct_at_end(__first, __last); - } - __guard.__complete(); + auto __n = static_cast<size_type>(std::distance(__first, __last)); + __init_with_size(__first, __last, __n); } template <class _Allocator> template <class _ForwardIterator> _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a, - typename enable_if<__is_cpp17_forward_iterator<_ForwardIterator>::value>::type*) + typename enable_if<__has_forward_iterator_category<_ForwardIterator>::value>::type*) : __begin_(nullptr), __size_(0), __cap_alloc_(0, static_cast<__storage_allocator>(__a)) { - auto __guard = std::__make_exception_guard(__destroy_vector(*this)); - size_type __n = static_cast<size_type>(std::distance(__first, __last)); - if (__n > 0) - { - __vallocate(__n); - __construct_at_end(__first, __last); - } - __guard.__complete(); + auto __n = static_cast<size_type>(std::distance(__first, __last)); + __init_with_size(__first, __last, __n); } #ifndef _LIBCPP_CXX03_LANG @@ -2699,7 +2759,7 @@ vector<bool, _Allocator>::vector(initializer_list<value_type> __il) if (__n > 0) { __vallocate(__n); - __construct_at_end(__il.begin(), __il.end()); + __construct_at_end(__il.begin(), __il.end(), __n); } } @@ -2714,7 +2774,7 @@ vector<bool, _Allocator>::vector(initializer_list<value_type> __il, const alloca if (__n > 0) { __vallocate(__n); - __construct_at_end(__il.begin(), __il.end()); + __construct_at_end(__il.begin(), __il.end(), __n); } } @@ -2730,7 +2790,7 @@ vector<bool, _Allocator>::vector(const vector& __v) if (__v.size() > 0) { __vallocate(__v.size()); - __construct_at_end(__v.begin(), __v.end()); + __construct_at_end(__v.begin(), __v.end(), __v.size()); } } @@ -2744,7 +2804,7 @@ vector<bool, _Allocator>::vector(const vector& __v, const allocator_type& __a) if (__v.size() > 0) { __vallocate(__v.size()); - __construct_at_end(__v.begin(), __v.end()); + __construct_at_end(__v.begin(), __v.end(), __v.size()); } } @@ -2772,7 +2832,7 @@ vector<bool, _Allocator>::operator=(const vector& __v) template <class _Allocator> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<bool, _Allocator>::vector(vector&& __v) -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _NOEXCEPT #else _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value) @@ -2803,7 +2863,7 @@ vector<bool, _Allocator>::vector(vector&& __v, const __type_identity_t<allocator else if (__v.size() > 0) { __vallocate(__v.size()); - __construct_at_end(__v.begin(), __v.end()); + __construct_at_end(__v.begin(), __v.end(), __v.size()); } } @@ -2861,16 +2921,22 @@ vector<bool, _Allocator>::assign(size_type __n, const value_type& __x) } std::fill_n(begin(), __n, __x); } - std::__debug_db_invalidate_all(this); } template <class _Allocator> template <class _InputIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if <__has_exactly_input_iterator_category<_InputIterator>::value, void >::type vector<bool, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { + __assign_with_sentinel(__first, __last); +} + +template <class _Allocator> +template <class _Iterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI +void vector<bool, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) { clear(); for (; __first != __last; ++__first) push_back(*__first); @@ -2881,14 +2947,22 @@ template <class _ForwardIterator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < - __is_cpp17_forward_iterator<_ForwardIterator>::value, + __has_forward_iterator_category<_ForwardIterator>::value, void >::type vector<bool, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) { + __assign_with_size(__first, __last, std::distance(__first, __last)); +} + +template <class _Allocator> +template <class _ForwardIterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI +void vector<bool, _Allocator>::__assign_with_size(_ForwardIterator __first, _Sentinel __last, difference_type __ns) { + _LIBCPP_ASSERT_VALID_INPUT_RANGE(__ns >= 0, "invalid range specified"); + clear(); - difference_type __ns = std::distance(__first, __last); - _LIBCPP_ASSERT(__ns >= 0, "invalid range specified"); + const size_t __n = static_cast<size_type>(__ns); if (__n) { @@ -2897,7 +2971,7 @@ vector<bool, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __la __vdeallocate(); __vallocate(__n); } - __construct_at_end(__first, __last); + __construct_at_end(__first, __last, __n); } } @@ -2911,9 +2985,8 @@ vector<bool, _Allocator>::reserve(size_type __n) this->__throw_length_error(); vector __v(this->get_allocator()); __v.__vallocate(__n); - __v.__construct_at_end(this->begin(), this->end()); + __v.__construct_at_end(this->begin(), this->end(), this->size()); swap(__v); - std::__debug_db_invalidate_all(this); } } @@ -2923,17 +2996,17 @@ vector<bool, _Allocator>::shrink_to_fit() _NOEXCEPT { if (__external_cap_to_internal(size()) > __cap()) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS vector(*this, allocator_type(__alloc())).swap(*this); -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } } @@ -3018,11 +3091,19 @@ vector<bool, _Allocator>::insert(const_iterator __position, size_type __n, const template <class _Allocator> template <class _InputIterator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if <__is_exactly_cpp17_input_iterator<_InputIterator>::value, +_LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if <__has_exactly_input_iterator_category<_InputIterator>::value, typename vector<bool, _Allocator>::iterator >::type vector<bool, _Allocator>::insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { + return __insert_with_sentinel(__position, __first, __last); +} + +template <class _Allocator> +template <class _InputIterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI +typename vector<bool, _Allocator>::iterator +vector<bool, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) { difference_type __off = __position - begin(); iterator __p = __const_iterator_cast(__position); iterator __old_end = end(); @@ -3034,24 +3115,24 @@ vector<bool, _Allocator>::insert(const_iterator __position, _InputIterator __fir vector __v(get_allocator()); if (__first != __last) { -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS try { -#endif // _LIBCPP_NO_EXCEPTIONS - __v.assign(__first, __last); +#endif // _LIBCPP_HAS_NO_EXCEPTIONS + __v.__assign_with_sentinel(std::move(__first), std::move(__last)); difference_type __old_size = static_cast<difference_type>(__old_end - begin()); difference_type __old_p = __p - begin(); reserve(__recommend(size() + __v.size())); __p = begin() + __old_p; __old_end = begin() + __old_size; -#ifndef _LIBCPP_NO_EXCEPTIONS +#ifndef _LIBCPP_HAS_NO_EXCEPTIONS } catch (...) { erase(__old_end, end()); throw; } -#endif // _LIBCPP_NO_EXCEPTIONS +#endif // _LIBCPP_HAS_NO_EXCEPTIONS } __p = std::rotate(__p, __old_end, end()); insert(__p, __v.begin(), __v.end()); @@ -3063,13 +3144,21 @@ template <class _ForwardIterator> _LIBCPP_CONSTEXPR_SINCE_CXX20 typename enable_if < - __is_cpp17_forward_iterator<_ForwardIterator>::value, + __has_forward_iterator_category<_ForwardIterator>::value, typename vector<bool, _Allocator>::iterator >::type vector<bool, _Allocator>::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last) { - const difference_type __n_signed = std::distance(__first, __last); - _LIBCPP_ASSERT(__n_signed >= 0, "invalid range specified"); + return __insert_with_size(__position, __first, __last, std::distance(__first, __last)); +} + +template <class _Allocator> +template <class _ForwardIterator, class _Sentinel> +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI +typename vector<bool, _Allocator>::iterator +vector<bool, _Allocator>::__insert_with_size(const_iterator __position, _ForwardIterator __first, _Sentinel __last, + difference_type __n_signed) { + _LIBCPP_ASSERT_VALID_INPUT_RANGE(__n_signed >= 0, "invalid range specified"); const size_type __n = static_cast<size_type>(__n_signed); iterator __r; size_type __c = capacity(); @@ -3089,7 +3178,7 @@ vector<bool, _Allocator>::insert(const_iterator __position, _ForwardIterator __f std::copy_backward(__position, cend(), __v.end()); swap(__v); } - std::copy(__first, __last, __r); + std::__copy<_ClassicAlgPolicy>(__first, __last, __r); return __r; } @@ -3238,8 +3327,9 @@ operator==(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ return __sz == __y.size() && std::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template <class _Tp, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3248,7 +3338,6 @@ operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template <class _Tp, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3257,7 +3346,6 @@ operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template <class _Tp, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3266,7 +3354,6 @@ operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template <class _Tp, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3275,7 +3362,6 @@ operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ } template <class _Tp, class _Allocator> -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) @@ -3283,6 +3369,17 @@ operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __ return !(__y < __x); } +#else // _LIBCPP_STD_VER <= 17 + +template <class _Tp, class _Allocator> +_LIBCPP_HIDE_FROM_ABI constexpr __synth_three_way_result<_Tp> +operator<=>(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) { + return std::lexicographical_compare_three_way( + __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>); +} + +#endif // _LIBCPP_STD_VER <= 17 + template <class _Tp, class _Allocator> _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI @@ -3293,7 +3390,7 @@ swap(vector<_Tp, _Allocator>& __x, vector<_Tp, _Allocator>& __y) __x.swap(__y); } -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Allocator, class _Up> _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::size_type @@ -3319,15 +3416,15 @@ template <> inline constexpr bool __format::__enable_insertable<vector<wchar_t>> = true; #endif -#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_STD_VER >= 20 -#if _LIBCPP_STD_VER > 20 -template <class _Tp, class CharT> +#if _LIBCPP_STD_VER >= 23 +template <class _Tp, class _CharT> // Since is-vector-bool-reference is only used once it's inlined here. requires same_as<typename _Tp::__container, vector<bool, typename _Tp::__container::allocator_type>> -struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_Tp, CharT> { +struct _LIBCPP_TEMPLATE_VIS formatter<_Tp, _CharT> { private: - formatter<bool, CharT> __underlying_; + formatter<bool, _CharT> __underlying_; public: template <class _ParseContext> @@ -3340,15 +3437,15 @@ public: return __underlying_.format(__ref, __ctx); } }; -#endif // _LIBCPP_STD_VER > 20 +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 _LIBCPP_BEGIN_NAMESPACE_STD namespace pmr { template <class _ValueT> -using vector = std::vector<_ValueT, polymorphic_allocator<_ValueT>>; +using vector _LIBCPP_AVAILABILITY_PMR = std::vector<_ValueT, polymorphic_allocator<_ValueT>>; } // namespace pmr _LIBCPP_END_NAMESPACE_STD #endif @@ -3359,6 +3456,8 @@ _LIBCPP_POP_MACROS # include <algorithm> # include <atomic> # include <concepts> +# include <cstdlib> +# include <type_traits> # include <typeinfo> # include <utility> #endif diff --git a/libcxx/include/version b/libcxx/include/version index 9705229a1c52..53d40e7bb2b1 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -28,6 +28,8 @@ __cpp_lib_array_constexpr 201811L <array> <iterato __cpp_lib_as_const 201510L <utility> __cpp_lib_associative_heterogeneous_erasure 202110L <map> <set> <unordered_map> <unordered_set> +__cpp_lib_associative_heterogeneous_insertion 202306L <map> <set> <unordered_map> + <unordered_set> __cpp_lib_assume_aligned 201811L <memory> __cpp_lib_atomic_flag_test 201907L <atomic> __cpp_lib_atomic_float 201711L <atomic> @@ -38,10 +40,13 @@ __cpp_lib_atomic_shared_ptr 201711L <atomic> __cpp_lib_atomic_value_initialization 201911L <atomic> <memory> __cpp_lib_atomic_wait 201907L <atomic> __cpp_lib_barrier 201907L <barrier> -__cpp_lib_bind_back 202202L <functional> -__cpp_lib_bind_front 201907L <functional> +__cpp_lib_bind_back 202306L <functional> + 202202L // C++23 +__cpp_lib_bind_front 202306L <functional> + 201907L // C++20 __cpp_lib_bit_cast 201806L <bit> __cpp_lib_bitops 201907L <bit> +__cpp_lib_bitset 202306L <bitset> __cpp_lib_bool_constant 201505L <type_traits> __cpp_lib_bounded_array_traits 201902L <type_traits> __cpp_lib_boyer_moore_searcher 201603L <functional> @@ -72,6 +77,7 @@ __cpp_lib_constexpr_tuple 201811L <tuple> __cpp_lib_constexpr_typeinfo 202106L <typeinfo> __cpp_lib_constexpr_utility 201811L <utility> __cpp_lib_constexpr_vector 201907L <vector> +__cpp_lib_copyable_function 202306L <functional> __cpp_lib_coroutine 201902L <coroutine> __cpp_lib_destroying_delete 201806L <new> __cpp_lib_enable_shared_from_this 201603L <memory> @@ -82,15 +88,20 @@ __cpp_lib_erase_if 202002L <deque> <forward __cpp_lib_exchange_function 201304L <utility> __cpp_lib_execution 201902L <execution> 201603L // C++17 -__cpp_lib_expected 202202L <expected> +__cpp_lib_expected 202211L <expected> __cpp_lib_filesystem 201703L <filesystem> __cpp_lib_format 202106L <format> +__cpp_lib_format_ranges 202207L <format> +__cpp_lib_formatters 202302L <stacktrace> <thread> __cpp_lib_forward_like 202207L <utility> +__cpp_lib_fstream_native_handle 202306L <fstream> +__cpp_lib_function_ref 202306L <functional> __cpp_lib_gcd_lcm 201606L <numeric> __cpp_lib_generic_associative_lookup 201304L <map> <set> __cpp_lib_generic_unordered_lookup 201811L <unordered_map> <unordered_set> __cpp_lib_hardware_interference_size 201703L <new> __cpp_lib_has_unique_object_representations 201606L <type_traits> +__cpp_lib_hazard_pointer 202306L <hazard_pointer> __cpp_lib_hypot 201603L <cmath> __cpp_lib_incomplete_container_elements 201505L <forward_list> <list> <vector> __cpp_lib_int_pow2 202002L <bit> @@ -121,7 +132,9 @@ __cpp_lib_make_unique 201304L <memory> __cpp_lib_map_try_emplace 201411L <map> __cpp_lib_math_constants 201907L <numbers> __cpp_lib_math_special_functions 201603L <cmath> +__cpp_lib_mdspan 202207L <mdspan> __cpp_lib_memory_resource 201603L <memory_resource> +__cpp_lib_move_iterator_concept 202207L <iterator> __cpp_lib_move_only_function 202110L <functional> __cpp_lib_node_extract 201606L <map> <set> <unordered_map> <unordered_set> @@ -136,21 +149,26 @@ __cpp_lib_optional 202110L <optional> __cpp_lib_out_ptr 202106L <memory> __cpp_lib_parallel_algorithm 201603L <algorithm> <numeric> __cpp_lib_polymorphic_allocator 201902L <memory_resource> +__cpp_lib_print 202207L <ostream> <print> __cpp_lib_quoted_string_io 201304L <iomanip> -__cpp_lib_ranges 202106L <algorithm> <functional> <iterator> +__cpp_lib_ranges 202207L <algorithm> <functional> <iterator> <memory> <ranges> +__cpp_lib_ranges_as_rvalue 202207L <ranges> __cpp_lib_ranges_chunk 202202L <ranges> __cpp_lib_ranges_chunk_by 202202L <ranges> __cpp_lib_ranges_iota 202202L <numeric> __cpp_lib_ranges_join_with 202202L <ranges> +__cpp_lib_ranges_repeat 202207L <ranges> __cpp_lib_ranges_slide 202202L <ranges> __cpp_lib_ranges_starts_ends_with 202106L <algorithm> __cpp_lib_ranges_to_container 202202L <deque> <forward_list> <list> - <map> <priority_queue> <queue> + <map> <queue> <ranges> <set> <stack> <string> <unordered_map> <unordered_set> <vector> __cpp_lib_ranges_zip 202110L <ranges> <tuple> <utility> +__cpp_lib_ratio 202306L <ratio> __cpp_lib_raw_memory_algorithms 201606L <memory> +__cpp_lib_rcu 202306L <rcu> __cpp_lib_reference_from_temporary 202202L <type_traits> __cpp_lib_remove_cvref 201711L <type_traits> __cpp_lib_result_of_sfinae 201210L <functional> <type_traits> @@ -165,10 +183,12 @@ __cpp_lib_shared_ptr_weak_type 201606L <memory> __cpp_lib_shared_timed_mutex 201402L <shared_mutex> __cpp_lib_shift 201806L <algorithm> __cpp_lib_smart_ptr_for_overwrite 202002L <memory> +__cpp_lib_smart_ptr_owner_equality 202306L <memory> __cpp_lib_source_location 201907L <source_location> __cpp_lib_span 202002L <span> __cpp_lib_spanstream 202106L <spanstream> __cpp_lib_ssize 201902L <iterator> +__cpp_lib_sstream_from_string_view 202306L <sstream> __cpp_lib_stacktrace 202011L <stacktrace> __cpp_lib_starts_ends_with 201711L <string> <string_view> __cpp_lib_stdatomic_h 202011L <stdatomic.h> @@ -177,11 +197,14 @@ __cpp_lib_string_resize_and_overwrite 202110L <string> __cpp_lib_string_udls 201304L <string> __cpp_lib_string_view 201803L <string> <string_view> 201606L // C++17 +__cpp_lib_submdspan 202306L <mdspan> __cpp_lib_syncbuf 201803L <syncstream> +__cpp_lib_text_encoding 202306L <text_encoding> __cpp_lib_three_way_comparison 201907L <compare> __cpp_lib_to_address 201711L <memory> __cpp_lib_to_array 201907L <array> __cpp_lib_to_chars 201611L <charconv> +__cpp_lib_to_string 202306L <string> __cpp_lib_to_underlying 202102L <utility> __cpp_lib_transformation_trait_aliases 201304L <type_traits> __cpp_lib_transparent_operators 201510L <functional> <memory> @@ -196,6 +219,7 @@ __cpp_lib_unreachable 202202L <utility> __cpp_lib_unwrap_ref 201811L <functional> __cpp_lib_variant 202102L <variant> __cpp_lib_void_t 201411L <type_traits> +__cpp_lib_within_lifetime 202306L <type_traits> */ @@ -208,7 +232,7 @@ __cpp_lib_void_t 201411L <type_traits> // clang-format off -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER >= 14 # define __cpp_lib_chrono_udls 201304L # define __cpp_lib_complex_udls 201309L # define __cpp_lib_exchange_function 201304L @@ -223,7 +247,7 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_quoted_string_io 201304L # define __cpp_lib_result_of_sfinae 201210L # define __cpp_lib_robust_nonmodifying_seq_ops 201304L -# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX) # define __cpp_lib_shared_timed_mutex 201402L # endif # define __cpp_lib_string_udls 201304L @@ -233,7 +257,7 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_tuples_by_type 201304L #endif -#if _LIBCPP_STD_VER > 14 +#if _LIBCPP_STD_VER >= 17 # define __cpp_lib_addressof_constexpr 201603L # define __cpp_lib_allocator_traits_is_always_equal 201411L # define __cpp_lib_any 201606L @@ -248,7 +272,7 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_clamp 201603L # define __cpp_lib_enable_shared_from_this 201603L // # define __cpp_lib_execution 201603L -# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem) +# if !defined(_LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM_LIBRARY) # define __cpp_lib_filesystem 201703L # endif # define __cpp_lib_gcd_lcm 201606L @@ -267,7 +291,9 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_make_from_tuple 201606L # define __cpp_lib_map_try_emplace 201411L // # define __cpp_lib_math_special_functions 201603L -# define __cpp_lib_memory_resource 201603L +# if !defined(_LIBCPP_AVAILABILITY_HAS_NO_PMR) +# define __cpp_lib_memory_resource 201603L +# endif # define __cpp_lib_node_extract 201606L # define __cpp_lib_nonmember_container_access 201411L # define __cpp_lib_not_fn 201603L @@ -276,7 +302,7 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_raw_memory_algorithms 201606L # define __cpp_lib_sample 201603L # define __cpp_lib_scoped_lock 201703L -# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX) # define __cpp_lib_shared_mutex 201505L # endif # define __cpp_lib_shared_ptr_arrays 201611L @@ -292,7 +318,7 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_void_t 201411L #endif -#if _LIBCPP_STD_VER > 17 +#if _LIBCPP_STD_VER >= 20 # undef __cpp_lib_array_constexpr # define __cpp_lib_array_constexpr 201811L # define __cpp_lib_assume_aligned 201811L @@ -302,15 +328,15 @@ __cpp_lib_void_t 201411L <type_traits> // # define __cpp_lib_atomic_ref 201806L // # define __cpp_lib_atomic_shared_ptr 201711L # define __cpp_lib_atomic_value_initialization 201911L -# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait) +# if !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC) # define __cpp_lib_atomic_wait 201907L # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC) # define __cpp_lib_barrier 201907L # endif # define __cpp_lib_bind_front 201907L # define __cpp_lib_bit_cast 201806L -// # define __cpp_lib_bitops 201907L +# define __cpp_lib_bitops 201907L # define __cpp_lib_bounded_array_traits 201902L # if !defined(_LIBCPP_HAS_NO_CHAR8_T) # define __cpp_lib_char8_t 201907L @@ -329,16 +355,14 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_constexpr_utility 201811L # define __cpp_lib_constexpr_vector 201907L # define __cpp_lib_coroutine 201902L -# if _LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L +# if _LIBCPP_STD_VER >= 20 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L # define __cpp_lib_destroying_delete 201806L # endif # define __cpp_lib_endian 201907L # define __cpp_lib_erase_if 202002L # undef __cpp_lib_execution // # define __cpp_lib_execution 201902L -# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) -// # define __cpp_lib_format 202106L -# endif +// # define __cpp_lib_format 202106L # define __cpp_lib_generic_unordered_lookup 201811L # define __cpp_lib_int_pow2 202002L # define __cpp_lib_integer_comparison_functions 202002L @@ -350,22 +374,25 @@ __cpp_lib_void_t 201411L <type_traits> # if !defined(_LIBCPP_HAS_NO_THREADS) // # define __cpp_lib_jthread 201911L # endif -# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC) # define __cpp_lib_latch 201907L # endif # define __cpp_lib_list_remove_return_type 201806L # define __cpp_lib_math_constants 201907L -# define __cpp_lib_polymorphic_allocator 201902L -# define __cpp_lib_ranges 202106L +# define __cpp_lib_move_iterator_concept 202207L +# if !defined(_LIBCPP_AVAILABILITY_HAS_NO_PMR) +# define __cpp_lib_polymorphic_allocator 201902L +# endif +# define __cpp_lib_ranges 202207L # define __cpp_lib_remove_cvref 201711L -# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) +# if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC) # define __cpp_lib_semaphore 201907L # endif # undef __cpp_lib_shared_ptr_arrays # define __cpp_lib_shared_ptr_arrays 201707L # define __cpp_lib_shift 201806L // # define __cpp_lib_smart_ptr_for_overwrite 202002L -# if __has_builtin(__builtin_source_location) +# if __has_builtin(__builtin_source_location) && !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER <= 1403) # define __cpp_lib_source_location 201907L # endif # define __cpp_lib_span 202002L @@ -381,7 +408,7 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_unwrap_ref 201811L #endif -#if _LIBCPP_STD_VER > 20 +#if _LIBCPP_STD_VER >= 23 # define __cpp_lib_adaptor_iterator_pair_constructor 202106L # define __cpp_lib_allocate_at_least 202106L // # define __cpp_lib_associative_heterogeneous_erasure 202110L @@ -392,22 +419,28 @@ __cpp_lib_void_t 201411L <type_traits> // # define __cpp_lib_constexpr_cmath 202202L # undef __cpp_lib_constexpr_memory # define __cpp_lib_constexpr_memory 202202L -// # define __cpp_lib_constexpr_typeinfo 202106L -# define __cpp_lib_expected 202202L +# define __cpp_lib_constexpr_typeinfo 202106L +# define __cpp_lib_expected 202211L +# define __cpp_lib_format_ranges 202207L +// # define __cpp_lib_formatters 202302L # define __cpp_lib_forward_like 202207L -// # define __cpp_lib_invoke_r 202106L +# define __cpp_lib_invoke_r 202106L # define __cpp_lib_is_scoped_enum 202011L +// # define __cpp_lib_mdspan 202207L // # define __cpp_lib_move_only_function 202110L # undef __cpp_lib_optional # define __cpp_lib_optional 202110L // # define __cpp_lib_out_ptr 202106L +// # define __cpp_lib_print 202207L +# define __cpp_lib_ranges_as_rvalue 202207L // # define __cpp_lib_ranges_chunk 202202L // # define __cpp_lib_ranges_chunk_by 202202L // # define __cpp_lib_ranges_iota 202202L // # define __cpp_lib_ranges_join_with 202202L +# define __cpp_lib_ranges_repeat 202207L // # define __cpp_lib_ranges_slide 202202L // # define __cpp_lib_ranges_starts_ends_with 202106L -// # define __cpp_lib_ranges_to_container 202202L +# define __cpp_lib_ranges_to_container 202202L // # define __cpp_lib_ranges_zip 202110L // # define __cpp_lib_reference_from_temporary 202202L // # define __cpp_lib_spanstream 202106L @@ -415,10 +448,31 @@ __cpp_lib_void_t 201411L <type_traits> # define __cpp_lib_stdatomic_h 202011L # define __cpp_lib_string_contains 202011L # define __cpp_lib_string_resize_and_overwrite 202110L +// # define __cpp_lib_to_string 202306L # define __cpp_lib_to_underlying 202102L # define __cpp_lib_unreachable 202202L #endif +#if _LIBCPP_STD_VER >= 26 +// # define __cpp_lib_associative_heterogeneous_insertion 202306L +# undef __cpp_lib_bind_back +// # define __cpp_lib_bind_back 202306L +# undef __cpp_lib_bind_front +# define __cpp_lib_bind_front 202306L +// # define __cpp_lib_bitset 202306L +// # define __cpp_lib_copyable_function 202306L +// # define __cpp_lib_fstream_native_handle 202306L +// # define __cpp_lib_function_ref 202306L +// # define __cpp_lib_hazard_pointer 202306L +# define __cpp_lib_ratio 202306L +// # define __cpp_lib_rcu 202306L +// # define __cpp_lib_smart_ptr_owner_equality 202306L +// # define __cpp_lib_sstream_from_string_view 202306L +// # define __cpp_lib_submdspan 202306L +// # define __cpp_lib_text_encoding 202306L +// # define __cpp_lib_within_lifetime 202306L +#endif + // clang-format on #endif // _LIBCPP_VERSIONH diff --git a/libcxx/include/wchar.h b/libcxx/include/wchar.h index c684508dc2cc..eeccf3e937ff 100644 --- a/libcxx/include/wchar.h +++ b/libcxx/include/wchar.h @@ -116,12 +116,16 @@ size_t wcsrtombs(char* restrict dst, const wchar_t** restrict src, size_t len, # pragma GCC system_header #endif +// We define this here to support older versions of glibc <wchar.h> that do +// not define this for clang. #ifdef __cplusplus #define __CORRECT_ISO_CPP_WCHAR_H_PROTO #endif # if __has_include_next(<wchar.h>) # include_next <wchar.h> +# else +# include <__mbstate_t.h> // make sure we have mbstate_t regardless of the existence of <wchar.h> # endif // Determine whether we have const-correct overloads for wcschr and friends. |
