diff --git a/lib/libcxx/include/__algorithm/algorithm_family.h b/lib/libcxx/include/__algorithm/algorithm_family.h deleted file mode 100644 index 30ffff832e..0000000000 --- a/lib/libcxx/include/__algorithm/algorithm_family.h +++ /dev/null @@ -1,52 +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___ALGORITHM_ALGORITHM_FAMILY_H -#define _LIBCPP___ALGORITHM_ALGORITHM_FAMILY_H - -#include <__algorithm/iterator_operations.h> -#include <__algorithm/move.h> -#include <__algorithm/ranges_move.h> -#include <__config> -#include <__utility/move.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template -struct _AlgFamily; - -#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) - -template <> -struct _AlgFamily<_RangeAlgPolicy> { - static constexpr auto __move = ranges::move; -}; - -#endif - -template <> -struct _AlgFamily<_ClassicAlgPolicy> { - - // move - template - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 static _OutputIterator - __move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - return std::move( - std::move(__first), - std::move(__last), - std::move(__result)); - } -}; - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___ALGORITHM_ALGORITHM_FAMILY_H diff --git a/lib/libcxx/include/__algorithm/clamp.h b/lib/libcxx/include/__algorithm/clamp.h index b3762b85a0..30ddbdce64 100644 --- a/lib/libcxx/include/__algorithm/clamp.h +++ b/lib/libcxx/include/__algorithm/clamp.h @@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 template _LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_INLINE_VISIBILITY constexpr const _Tp& clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) { @@ -33,7 +33,7 @@ clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) template _LIBCPP_NODISCARD_EXT inline -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_LIBCPP_INLINE_VISIBILITY constexpr const _Tp& clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) { diff --git a/lib/libcxx/include/__algorithm/copy_backward.h b/lib/libcxx/include/__algorithm/copy_backward.h index 26b8c4d791..c5fa64bc8d 100644 --- a/lib/libcxx/include/__algorithm/copy_backward.h +++ b/lib/libcxx/include/__algorithm/copy_backward.h @@ -20,7 +20,6 @@ #include <__ranges/subrange.h> #include <__utility/move.h> #include <__utility/pair.h> -#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -44,9 +43,10 @@ __copy_backward(_InputIterator __first, _InputIterator __last, _OutputIterator _ template ::value, int> = 0> _LIBCPP_HIDE_FROM_ABI constexpr pair<_Iter1, _Iter2> __copy_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result) { - auto __reverse_range = std::__reverse_range(std::ranges::subrange(std::move(__first), std::move(__last))); + auto __last_iter = _IterOps<_AlgPolicy>::next(__first, std::move(__last)); + auto __reverse_range = std::__reverse_range(std::ranges::subrange(std::move(__first), __last_iter)); auto __ret = ranges::copy(std::move(__reverse_range), std::make_reverse_iterator(__result)); - return std::make_pair(__ret.in.base(), __ret.out.base()); + return std::make_pair(__last_iter, __ret.out.base()); } #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) diff --git a/lib/libcxx/include/__algorithm/find_first_of.h b/lib/libcxx/include/__algorithm/find_first_of.h index b968329fc3..2096b0f0c9 100644 --- a/lib/libcxx/include/__algorithm/find_first_of.h +++ b/lib/libcxx/include/__algorithm/find_first_of.h @@ -24,7 +24,8 @@ template #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/iterator_operations.h> @@ -65,7 +64,7 @@ void __half_inplace_merge(_InputIterator1 __first1, _Sent1 __last1, { if (__first2 == __last2) { - _AlgFamily<_AlgPolicy>::__move(__first1, __last1, __result); + std::__move<_AlgPolicy>(__first1, __last1, __result); return; } @@ -185,8 +184,7 @@ void __inplace_merge( difference_type __len22 = __len2 - __len21; // distance(__m2, __last) // [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last) // swap middle two partitions - // TODO(alg-policy): pass `_AlgPolicy` once it's supported by `rotate`. - __middle = _VSTD::rotate(__m1, __middle, __m2); + __middle = std::__rotate<_AlgPolicy>(__m1, __middle, __m2).first; // __len12 and __len21 now have swapped meanings // merge smaller range with recursive call and larger with tail recursion elimination if (__len11 + __len21 < __len12 + __len22) diff --git a/lib/libcxx/include/__algorithm/is_permutation.h b/lib/libcxx/include/__algorithm/is_permutation.h index cdd7420484..06a4949e21 100644 --- a/lib/libcxx/include/__algorithm/is_permutation.h +++ b/lib/libcxx/include/__algorithm/is_permutation.h @@ -11,10 +11,16 @@ #define _LIBCPP___ALGORITHM_IS_PERMUTATION_H #include <__algorithm/comp.h> +#include <__algorithm/iterator_operations.h> #include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__iterator/concepts.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> +#include <__utility/move.h> +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,140 +28,211 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 bool -is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _BinaryPredicate __pred) { - // shorten sequences as much as possible by lopping of any equal prefix - for (; __first1 != __last1; ++__first1, (void)++__first2) +template +struct _ConstTimeDistance : false_type {}; + +#if _LIBCPP_STD_VER > 17 + +template +struct _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2, __enable_if_t< + sized_sentinel_for<_Sent1, _Iter1> && + sized_sentinel_for<_Sent2, _Iter2> +>> : true_type {}; + +#else + +template +struct _ConstTimeDistance<_Iter1, _Iter1, _Iter2, _Iter2, __enable_if_t< + is_same::iterator_category, random_access_iterator_tag>::value && + is_same::iterator_category, random_access_iterator_tag>::value +> > : true_type {}; + +#endif // _LIBCPP_STD_VER > 17 + +// Internal functions + +// For each element in [f1, l1) see if there are the same number of equal elements in [f2, l2) +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__is_permutation_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) { + using _D1 = __iter_diff_t<_Iter1>; + + for (auto __i = __first1; __i != __last1; ++__i) { + // Have we already counted the number of *__i in [f1, l1)? + auto __match = __first1; + for (; __match != __i; ++__match) { + if (std::__invoke(__pred, std::__invoke(__proj1, *__match), std::__invoke(__proj1, *__i))) + break; + } + + if (__match == __i) { + // Count number of *__i in [f2, l2) + _D1 __c2 = 0; + for (auto __j = __first2; __j != __last2; ++__j) { + if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj2, *__j))) + ++__c2; + } + if (__c2 == 0) + return false; + + // Count number of *__i in [__i, l1) (we can start with 1) + _D1 __c1 = 1; + for (auto __j = _IterOps<_AlgPolicy>::next(__i); __j != __last1; ++__j) { + if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj1, *__j))) + ++__c1; + } + if (__c1 != __c2) + return false; + } + } + + return true; +} + +// 2+1 iterators, predicate. Not used by range algorithms. +template +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__is_permutation(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, + _BinaryPredicate&& __pred) { + // Shorten sequences as much as possible by lopping of any equal prefix. + for (; __first1 != __last1; ++__first1, (void)++__first2) { if (!__pred(*__first1, *__first2)) break; + } + if (__first1 == __last1) return true; // __first1 != __last1 && *__first1 != *__first2 - typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1; - _D1 __l1 = _VSTD::distance(__first1, __last1); + using _D1 = __iter_diff_t<_ForwardIterator1>; + _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); if (__l1 == _D1(1)) return false; - _ForwardIterator2 __last2 = _VSTD::next(__first2, __l1); - // For each element in [f1, l1) see if there are the same number of - // equal elements in [f2, l2) - for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) { - // Have we already counted the number of *__i in [f1, l1)? - _ForwardIterator1 __match = __first1; - for (; __match != __i; ++__match) - if (__pred(*__match, *__i)) - break; - if (__match == __i) { - // Count number of *__i in [f2, l2) - _D1 __c2 = 0; - for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) - if (__pred(*__i, *__j)) - ++__c2; - if (__c2 == 0) - return false; - // Count number of *__i in [__i, l1) (we can start with 1) - _D1 __c1 = 1; - for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j) - if (__pred(*__i, *__j)) - ++__c1; - if (__c1 != __c2) - return false; - } - } - return true; + auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __l1); + + return std::__is_permutation_impl<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __identity(), __identity()); } -template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool -is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { - typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; - typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; - return _VSTD::is_permutation(__first1, __last1, __first2, __equal_to<__v1, __v2>()); -} - -#if _LIBCPP_STD_VER > 11 -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 bool -__is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _BinaryPredicate __pred, forward_iterator_tag, forward_iterator_tag) { - // shorten sequences as much as possible by lopping of any equal prefix - for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) - if (!__pred(*__first1, *__first2)) +// 2+2 iterators, predicate, non-constant time `distance`. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2, + /*_ConstTimeDistance=*/false_type) { + // Shorten sequences as much as possible by lopping of any equal prefix. + while (__first1 != __last1 && __first2 != __last2) { + if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) break; + ++__first1; + ++__first2; + } + if (__first1 == __last1) return __first2 == __last2; - else if (__first2 == __last2) + if (__first2 == __last2) // Second range is shorter return false; - typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1; - _D1 __l1 = _VSTD::distance(__first1, __last1); + using _D1 = __iter_diff_t<_Iter1>; + _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1); - typedef typename iterator_traits<_ForwardIterator2>::difference_type _D2; - _D2 __l2 = _VSTD::distance(__first2, __last2); + using _D2 = __iter_diff_t<_Iter2>; + _D2 __l2 = _IterOps<_AlgPolicy>::distance(__first2, __last2); if (__l1 != __l2) return false; - // For each element in [f1, l1) see if there are the same number of - // equal elements in [f2, l2) - for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) { - // Have we already counted the number of *__i in [f1, l1)? - _ForwardIterator1 __match = __first1; - for (; __match != __i; ++__match) - if (__pred(*__match, *__i)) - break; - if (__match == __i) { - // Count number of *__i in [f2, l2) - _D1 __c2 = 0; - for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j) - if (__pred(*__i, *__j)) - ++__c2; - if (__c2 == 0) - return false; - // Count number of *__i in [__i, l1) (we can start with 1) - _D1 __c1 = 1; - for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j) - if (__pred(*__i, *__j)) - ++__c1; - if (__c1 != __c2) - return false; - } - } - return true; + return std::__is_permutation_impl<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2); } -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 bool __is_permutation(_RandomAccessIterator1 __first1, _RandomAccessIterator2 __last1, - _RandomAccessIterator1 __first2, _RandomAccessIterator2 __last2, - _BinaryPredicate __pred, random_access_iterator_tag, - random_access_iterator_tag) { - if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2)) +// 2+2 iterators, predicate, specialization for constant-time `distance` call. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2, + /*_ConstTimeDistance=*/true_type) { + if (std::distance(__first1, __last1) != std::distance(__first2, __last2)) return false; - return _VSTD::is_permutation<_RandomAccessIterator1, _RandomAccessIterator2, - _BinaryPredicate&>(__first1, __last1, __first2, __pred); + return std::__is_permutation<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2, + /*_ConstTimeDistance=*/false_type()); } +// 2+2 iterators, predicate +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) { + return std::__is_permutation<_AlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __proj1, __proj2, + _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2>()); +} + +// Public interface + +// 2+1 iterators, predicate template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, - _ForwardIterator2 __last2, _BinaryPredicate __pred) { - return _VSTD::__is_permutation<_BinaryPredicate&>( - __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_ForwardIterator1>::iterator_category(), - typename iterator_traits<_ForwardIterator2>::iterator_category()); + _BinaryPredicate __pred) { + static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, + "The predicate has to be callable"); + + return std::__is_permutation<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), __pred); } +// 2+1 iterators template -_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { + using __v1 = __iter_value_type<_ForwardIterator1>; + using __v2 = __iter_value_type<_ForwardIterator2>; + return std::is_permutation(__first1, __last1, __first2, __equal_to<__v1, __v2>()); +} + +#if _LIBCPP_STD_VER > 11 + +// 2+2 iterators +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) { - typedef typename iterator_traits<_ForwardIterator1>::value_type __v1; - typedef typename iterator_traits<_ForwardIterator2>::value_type __v2; - return _VSTD::__is_permutation(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>(), - typename iterator_traits<_ForwardIterator1>::iterator_category(), - typename iterator_traits<_ForwardIterator2>::iterator_category()); + using __v1 = __iter_value_type<_ForwardIterator1>; + using __v2 = __iter_value_type<_ForwardIterator2>; + + return std::__is_permutation<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __equal_to<__v1, __v2>(), __identity(), __identity()); } -#endif + +// 2+2 iterators, predicate +template +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool +is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, + _ForwardIterator2 __last2, _BinaryPredicate __pred) { + static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value, + "The predicate has to be callable"); + + return std::__is_permutation<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), + __pred, __identity(), __identity()); +} + +#endif // _LIBCPP_STD_VER > 11 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/iterator_operations.h b/lib/libcxx/include/__algorithm/iterator_operations.h index e060574652..af46187873 100644 --- a/lib/libcxx/include/__algorithm/iterator_operations.h +++ b/lib/libcxx/include/__algorithm/iterator_operations.h @@ -10,13 +10,16 @@ #define _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H #include <__algorithm/iter_swap.h> +#include <__algorithm/ranges_iterator_concept.h> #include <__config> #include <__iterator/advance.h> #include <__iterator/distance.h> +#include <__iterator/incrementable_traits.h> #include <__iterator/iter_move.h> #include <__iterator/iter_swap.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> +#include <__iterator/prev.h> #include <__iterator/readable_traits.h> #include <__utility/declval.h> #include <__utility/forward.h> @@ -40,11 +43,18 @@ struct _IterOps<_RangeAlgPolicy> { template using __value_type = iter_value_t<_Iter>; + template + using __iterator_category = ranges::__iterator_concept<_Iter>; + + template + using __difference_type = iter_difference_t<_Iter>; + static constexpr auto advance = ranges::advance; static constexpr auto distance = ranges::distance; static constexpr auto __iter_move = ranges::iter_move; static constexpr auto iter_swap = ranges::iter_swap; static constexpr auto next = ranges::next; + static constexpr auto prev = ranges::prev; static constexpr auto __advance_to = ranges::advance; }; @@ -58,6 +68,12 @@ struct _IterOps<_ClassicAlgPolicy> { template using __value_type = typename iterator_traits<_Iter>::value_type; + template + using __iterator_category = typename iterator_traits<_Iter>::iterator_category; + + template + using __difference_type = typename iterator_traits<_Iter>::difference_type; + // advance template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 @@ -132,10 +148,18 @@ struct _IterOps<_ClassicAlgPolicy> { template _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 __uncvref_t<_Iter> next(_Iter&& __it, - typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1){ + typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1) { return std::next(std::forward<_Iter>(__it), __n); } + // prev + template + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 + __uncvref_t<_Iter> prev(_Iter&& __iter, + typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1) { + return std::prev(std::forward<_Iter>(__iter), __n); + } + template _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11 void __advance_to(_Iter& __first, _Iter __last) { diff --git a/lib/libcxx/include/__algorithm/move.h b/lib/libcxx/include/__algorithm/move.h index 0b08d31c17..c090faf6b6 100644 --- a/lib/libcxx/include/__algorithm/move.h +++ b/lib/libcxx/include/__algorithm/move.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_MOVE_H #define _LIBCPP___ALGORITHM_MOVE_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/unwrap_iter.h> #include <__config> #include <__iterator/iterator_traits.h> @@ -26,18 +27,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD // move -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 pair<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { while (__first != __last) { - *__result = std::move(*__first); + *__result = _IterOps<_AlgPolicy>::__iter_move(__first); ++__first; ++__result; } return std::make_pair(std::move(__first), std::move(__result)); } -template ::type, _OutType>::value && is_trivially_move_assignable<_OutType>::value> > @@ -49,7 +51,7 @@ pair<_InType*, _OutType*> __move_impl(_InType* __first, _InType* __last, _OutTyp && !is_trivially_copyable<_InType>::value #endif ) - return std::__move_impl<_InType*, _InType*, _OutType*>(__first, __last, __result); + return std::__move_impl<_AlgPolicy, _InType*, _InType*, _OutType*>(__first, __last, __result); const size_t __n = static_cast(__last - __first); ::__builtin_memmove(__result, __first, __n * sizeof(_OutType)); return std::make_pair(__first + __n, __result + __n); @@ -65,7 +67,8 @@ template struct __is_trivially_move_assignable_unwrapped : __is_trivially_move_assignable_unwrapped_impl(std::declval<_Iter>()))> {}; -template ::value_type>::type, typename iterator_traits<_OutIter>::value_type>::value @@ -81,33 +84,34 @@ __move_impl(reverse_iterator<_InIter> __first, auto __last_base = std::__unwrap_iter(__last.base()); auto __result_base = std::__unwrap_iter(__result.base()); auto __result_first = __result_base - (__first_base - __last_base); - std::__move_impl(__last_base, __first_base, __result_first); + std::__move_impl<_AlgPolicy>(__last_base, __first_base, __result_first); return std::make_pair(__last, reverse_iterator<_OutIter>(std::__rewrap_iter(__result.base(), __result_first))); } -template +template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __enable_if_t::value && is_copy_constructible<_Sent>::value && is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> > __move(_InIter __first, _Sent __last, _OutIter __result) { - auto __ret = std::__move_impl(std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result)); + auto __ret = std::__move_impl<_AlgPolicy>( + std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result)); return std::make_pair(std::__rewrap_iter(__first, __ret.first), std::__rewrap_iter(__result, __ret.second)); } -template +template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 __enable_if_t::value || !is_copy_constructible<_Sent>::value || !is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> > __move(_InIter __first, _Sent __last, _OutIter __result) { - return std::__move_impl(std::move(__first), std::move(__last), std::move(__result)); + return std::__move_impl<_AlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); } template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - return std::__move(__first, __last, __result).second; + return std::__move<_ClassicAlgPolicy>(__first, __last, __result).second; } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/move_backward.h b/lib/libcxx/include/__algorithm/move_backward.h index a56f6b826c..626e250b6d 100644 --- a/lib/libcxx/include/__algorithm/move_backward.h +++ b/lib/libcxx/include/__algorithm/move_backward.h @@ -9,6 +9,7 @@ #ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H #define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/unwrap_iter.h> #include <__config> #include <__utility/move.h> @@ -21,25 +22,25 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _OutputIterator __move_backward_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { while (__first != __last) - *--__result = _VSTD::move(*--__last); + *--__result = _IterOps<_AlgPolicy>::__iter_move(--__last); return __result; } -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _OutputIterator -__move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) +__move_backward_impl(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - return _VSTD::__move_backward_constexpr(__first, __last, __result); + return _VSTD::__move_backward_constexpr<_AlgPolicy>(__first, __last, __result); } -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 typename enable_if < @@ -47,7 +48,7 @@ typename enable_if is_trivially_move_assignable<_Up>::value, _Up* >::type -__move_backward(_Tp* __first, _Tp* __last, _Up* __result) +__move_backward_impl(_Tp* __first, _Tp* __last, _Up* __result) { const size_t __n = static_cast(__last - __first); if (__n > 0) @@ -58,20 +59,29 @@ __move_backward(_Tp* __first, _Tp* __last, _Up* __result) return __result; } +template +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +_BidirectionalIterator2 +__move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, + _BidirectionalIterator2 __result) +{ + if (__libcpp_is_constant_evaluated()) { + return _VSTD::__move_backward_constexpr<_AlgPolicy>(__first, __last, __result); + } else { + return _VSTD::__rewrap_iter(__result, + _VSTD::__move_backward_impl<_AlgPolicy>(_VSTD::__unwrap_iter(__first), + _VSTD::__unwrap_iter(__last), + _VSTD::__unwrap_iter(__result))); + } +} + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _BidirectionalIterator2 move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) { - if (__libcpp_is_constant_evaluated()) { - return _VSTD::__move_backward_constexpr(__first, __last, __result); - } else { - return _VSTD::__rewrap_iter(__result, - _VSTD::__move_backward(_VSTD::__unwrap_iter(__first), - _VSTD::__unwrap_iter(__last), - _VSTD::__unwrap_iter(__result))); - } + return std::__move_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/next_permutation.h b/lib/libcxx/include/__algorithm/next_permutation.h index 05e56f4a17..b58dcf4e1a 100644 --- a/lib/libcxx/include/__algorithm/next_permutation.h +++ b/lib/libcxx/include/__algorithm/next_permutation.h @@ -11,10 +11,12 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/reverse.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <__utility/swap.h> +#include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,29 +24,34 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 bool -__next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 +pair<_BidirectionalIterator, bool> +__next_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) { - _BidirectionalIterator __i = __last; + using _Result = pair<_BidirectionalIterator, bool>; + + _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); + _BidirectionalIterator __i = __last_iter; if (__first == __last || __first == --__i) - return false; + return _Result(std::move(__last_iter), false); + while (true) { _BidirectionalIterator __ip1 = __i; if (__comp(*--__i, *__ip1)) { - _BidirectionalIterator __j = __last; + _BidirectionalIterator __j = __last_iter; while (!__comp(*__i, *--__j)) ; - swap(*__i, *__j); - _VSTD::reverse(__ip1, __last); - return true; + _IterOps<_AlgPolicy>::iter_swap(__i, __j); + std::__reverse<_AlgPolicy>(__ip1, __last_iter); + return _Result(std::move(__last_iter), true); } if (__i == __first) { - _VSTD::reverse(__first, __last); - return false; + std::__reverse<_AlgPolicy>(__first, __last_iter); + return _Result(std::move(__last_iter), false); } } } @@ -54,8 +61,9 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__next_permutation<_Comp_ref>(__first, __last, __comp); + using _Comp_ref = typename __comp_ref_type<_Compare>::type; + return std::__next_permutation<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), static_cast<_Comp_ref>(__comp)).second; } template diff --git a/lib/libcxx/include/__algorithm/prev_permutation.h b/lib/libcxx/include/__algorithm/prev_permutation.h index 9dbc1dad01..698506372b 100644 --- a/lib/libcxx/include/__algorithm/prev_permutation.h +++ b/lib/libcxx/include/__algorithm/prev_permutation.h @@ -11,10 +11,12 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/reverse.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <__utility/swap.h> +#include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -22,29 +24,34 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template -_LIBCPP_CONSTEXPR_AFTER_CXX17 bool -__prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) +template +_LIBCPP_CONSTEXPR_AFTER_CXX17 +pair<_BidirectionalIterator, bool> +__prev_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp) { - _BidirectionalIterator __i = __last; + using _Result = pair<_BidirectionalIterator, bool>; + + _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last); + _BidirectionalIterator __i = __last_iter; if (__first == __last || __first == --__i) - return false; + return _Result(std::move(__last_iter), false); + while (true) { _BidirectionalIterator __ip1 = __i; if (__comp(*__ip1, *--__i)) { - _BidirectionalIterator __j = __last; + _BidirectionalIterator __j = __last_iter; while (!__comp(*--__j, *__i)) ; - swap(*__i, *__j); - _VSTD::reverse(__ip1, __last); - return true; + _IterOps<_AlgPolicy>::iter_swap(__i, __j); + std::__reverse<_AlgPolicy>(__ip1, __last_iter); + return _Result(std::move(__last_iter), true); } if (__i == __first) { - _VSTD::reverse(__first, __last); - return false; + std::__reverse<_AlgPolicy>(__first, __last_iter); + return _Result(std::move(__last_iter), false); } } } @@ -54,8 +61,9 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) { - typedef typename __comp_ref_type<_Compare>::type _Comp_ref; - return _VSTD::__prev_permutation<_Comp_ref>(__first, __last, __comp); + using _Comp_ref = typename __comp_ref_type<_Compare>::type; + return std::__prev_permutation<_ClassicAlgPolicy>( + std::move(__first), std::move(__last), static_cast<_Comp_ref>(__comp)).second; } template diff --git a/lib/libcxx/include/__algorithm/ranges_clamp.h b/lib/libcxx/include/__algorithm/ranges_clamp.h new file mode 100644 index 0000000000..bdde97e178 --- /dev/null +++ b/lib/libcxx/include/__algorithm/ranges_clamp.h @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// 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_CLAMP_H +#define _LIBCPP___ALGORITHM_RANGES_CLAMP_H + +#include <__assert> +#include <__config> +#include <__functional/identity.h> +#include <__functional/invoke.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__utility/forward.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __clamp { +struct __fn { + + template > _Comp = ranges::less> + _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"); + + if (std::invoke(__comp, std::invoke(__proj, __value), std::invoke(__proj, __low))) + return __low; + else if (std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __value))) + return __high; + else + return __value; + } + +}; +} // namespace __clamp + +inline namespace __cpo { + inline constexpr auto clamp = __clamp::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_CLAMP_H diff --git a/lib/libcxx/include/__algorithm/ranges_is_permutation.h b/lib/libcxx/include/__algorithm/ranges_is_permutation.h new file mode 100644 index 0000000000..41e302fe99 --- /dev/null +++ b/lib/libcxx/include/__algorithm/ranges_is_permutation.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_RANGES_IS_PERMUTATION_H +#define _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H + +#include <__algorithm/is_permutation.h> +#include <__algorithm/iterator_operations.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/distance.h> +#include <__iterator/projected.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 > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __is_permutation { +struct __fn { + + template + _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); + } + + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + class _Proj1 = identity, + class _Proj2 = identity, + indirect_equivalence_relation, + projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> + _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); + } + + template , _Proj1>, projected, _Proj2>> _Pred = ranges::equal_to> + _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); + } +}; +} // namespace __is_permutation + +inline namespace __cpo { + inline constexpr auto is_permutation = __is_permutation::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H diff --git a/lib/libcxx/include/__algorithm/ranges_move.h b/lib/libcxx/include/__algorithm/ranges_move.h index ad4342d7c9..9e1d4c72fb 100644 --- a/lib/libcxx/include/__algorithm/ranges_move.h +++ b/lib/libcxx/include/__algorithm/ranges_move.h @@ -10,6 +10,7 @@ #define _LIBCPP___ALGORITHM_RANGES_MOVE_H #include <__algorithm/in_out_result.h> +#include <__algorithm/iterator_operations.h> #include <__algorithm/move.h> #include <__config> #include <__iterator/concepts.h> @@ -36,24 +37,12 @@ namespace __move { struct __fn { template - requires __iter_move::__move_deref<_InIter> // check that we are allowed to std::move() the value _LIBCPP_HIDE_FROM_ABI constexpr static move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { - auto __ret = std::__move(std::move(__first), std::move(__last), std::move(__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 - _LIBCPP_HIDE_FROM_ABI constexpr static - move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) { - while (__first != __last) { - *__result = ranges::iter_move(__first); - ++__first; - ++__result; - } - return {std::move(__first), std::move(__result)}; - } - template _Sent, weakly_incrementable _OutIter> requires indirectly_movable<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI constexpr diff --git a/lib/libcxx/include/__algorithm/ranges_move_backward.h b/lib/libcxx/include/__algorithm/ranges_move_backward.h index b3dfa71396..583a6bf29d 100644 --- a/lib/libcxx/include/__algorithm/ranges_move_backward.h +++ b/lib/libcxx/include/__algorithm/ranges_move_backward.h @@ -40,10 +40,11 @@ struct __fn { template _LIBCPP_HIDE_FROM_ABI constexpr static move_backward_result<_InIter, _OutIter> __move_backward_impl(_InIter __first, _Sent __last, _OutIter __result) { - auto __ret = ranges::move(std::make_reverse_iterator(ranges::next(__first, __last)), + auto __last_iter = ranges::next(__first, std::move(__last)); + auto __ret = ranges::move(std::make_reverse_iterator(__last_iter), std::make_reverse_iterator(__first), std::make_reverse_iterator(__result)); - return {std::move(__ret.in.base()), std::move(__ret.out.base())}; + return {std::move(__last_iter), std::move(__ret.out.base())}; } template _Sent, bidirectional_iterator _OutIter> diff --git a/lib/libcxx/include/__algorithm/ranges_next_permutation.h b/lib/libcxx/include/__algorithm/ranges_next_permutation.h new file mode 100644 index 0000000000..34c5fee040 --- /dev/null +++ b/lib/libcxx/include/__algorithm/ranges_next_permutation.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___ALGORITHM_RANGES_NEXT_PERMUTATION_H +#define _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H + +#include <__algorithm/in_found_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/next_permutation.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using next_permutation_result = in_found_result<_InIter>; + +namespace __next_permutation { + +struct __fn { + template _Sent, class _Comp = ranges::less, class _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr next_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__next_permutation<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr next_permutation_result> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__next_permutation<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } +}; + +} // namespace __next_permutation + +inline namespace __cpo { +constexpr inline auto next_permutation = __next_permutation::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H diff --git a/lib/libcxx/include/__algorithm/ranges_prev_permutation.h b/lib/libcxx/include/__algorithm/ranges_prev_permutation.h new file mode 100644 index 0000000000..58da606d07 --- /dev/null +++ b/lib/libcxx/include/__algorithm/ranges_prev_permutation.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_RANGES_PREV_PERMUTATION_H +#define _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H + +#include <__algorithm/in_found_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/make_projected.h> +#include <__algorithm/prev_permutation.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/sortable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +template +using prev_permutation_result = in_found_result<_InIter>; + +namespace __prev_permutation { + +struct __fn { + + template _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 { + auto __result = std::__prev_permutation<_RangeAlgPolicy>( + std::move(__first), std::move(__last), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } + + template + requires sortable, _Comp, _Proj> + _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result> + operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const { + auto __result = std::__prev_permutation<_RangeAlgPolicy>( + ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj)); + return {std::move(__result.first), std::move(__result.second)}; + } + +}; + +} // namespace __prev_permutation + +inline namespace __cpo { +constexpr inline auto prev_permutation = __prev_permutation::__fn{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H diff --git a/lib/libcxx/include/__algorithm/ranges_remove_copy.h b/lib/libcxx/include/__algorithm/ranges_remove_copy.h index 16e9009e7e..a8144ce0ec 100644 --- a/lib/libcxx/include/__algorithm/ranges_remove_copy.h +++ b/lib/libcxx/include/__algorithm/ranges_remove_copy.h @@ -10,19 +10,16 @@ #define _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_H #include <__algorithm/in_out_result.h> -#include <__algorithm/make_projected.h> -#include <__algorithm/remove_copy.h> +#include <__algorithm/ranges_remove_copy_if.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> -#include <__iterator/iterator_traits.h> #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> -#include <__utility/forward.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -40,32 +37,30 @@ using remove_copy_result = in_out_result<_InIter, _OutIter>; namespace __remove_copy { -struct __fn { + struct __fn { + template _Sent, + weakly_incrementable _OutIter, + class _Type, + class _Proj = identity> + requires indirectly_copyable<_InIter, _OutIter> && + indirect_binary_predicate, 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 _Sent, weakly_incrementable _OutIter, class _Type, - class _Proj = identity> - requires indirectly_copyable<_InIter, _OutIter> && - indirect_binary_predicate, 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 { - // TODO: implement - (void)__first; (void)__last; (void)__result; (void)__value; (void)__proj; - return {}; - } - - template - requires indirectly_copyable, _OutIter> && - indirect_binary_predicate, _Proj>, const _Type*> - _LIBCPP_HIDE_FROM_ABI constexpr - remove_copy_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, const _Type& __value, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__result; (void)__value; (void)__proj; - return {}; - } - -}; + template + requires indirectly_copyable, _OutIter> && + indirect_binary_predicate, _Proj>, const _Type*> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result, _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 diff --git a/lib/libcxx/include/__algorithm/ranges_remove_copy_if.h b/lib/libcxx/include/__algorithm/ranges_remove_copy_if.h index 4eafe425b8..3f56693fa1 100644 --- a/lib/libcxx/include/__algorithm/ranges_remove_copy_if.h +++ b/lib/libcxx/include/__algorithm/ranges_remove_copy_if.h @@ -38,33 +38,43 @@ namespace ranges { template using remove_copy_if_result = in_out_result<_InIter, _OutIter>; +template +_LIBCPP_HIDE_FROM_ABI constexpr in_out_result<_InIter, _OutIter> +__remove_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))) { + *__result = *__first; + ++__result; + } + } + return {std::move(__first), std::move(__result)}; +} + namespace __remove_copy_if { -struct __fn { + struct __fn { + template _Sent, + weakly_incrementable _OutIter, + class _Proj = identity, + indirect_unary_predicate> _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 _Sent, weakly_incrementable _OutIter, - class _Proj = identity, indirect_unary_predicate> _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 { - // TODO: implement - (void)__first; (void)__last; (void)__result; (void)__pred; (void)__proj; - return {}; - } - - template , _Proj>> _Pred> - requires indirectly_copyable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - remove_copy_if_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, _Pred __pred, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__result; (void)__pred; (void)__proj; - return {}; - } - -}; + template , _Proj>> _Pred> + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result, _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 diff --git a/lib/libcxx/include/__algorithm/ranges_replace_copy.h b/lib/libcxx/include/__algorithm/ranges_replace_copy.h index 19ef635d6f..7d59dbe7db 100644 --- a/lib/libcxx/include/__algorithm/ranges_replace_copy.h +++ b/lib/libcxx/include/__algorithm/ranges_replace_copy.h @@ -10,19 +10,16 @@ #define _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_H #include <__algorithm/in_out_result.h> -#include <__algorithm/make_projected.h> -#include <__algorithm/replace_copy.h> +#include <__algorithm/ranges_replace_copy_if.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> #include <__functional/ranges_operations.h> #include <__iterator/concepts.h> -#include <__iterator/iterator_traits.h> #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> -#include <__utility/forward.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -40,35 +37,45 @@ using replace_copy_result = in_out_result<_InIter, _OutIter>; namespace __replace_copy { -struct __fn { - - template _Sent, class _Type1, class _Type2, - output_iterator _OutIter, class _Proj = identity> - requires indirectly_copyable<_InIter, _OutIter> && - indirect_binary_predicate, const _Type1*> - _LIBCPP_HIDE_FROM_ABI constexpr - replace_copy_result<_InIter, _OutIter> - operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type1& __old_value, const _Type2& __new_value, + struct __fn { + template _Sent, + class _OldType, + class _NewType, + output_iterator _OutIter, + class _Proj = identity> + requires indirectly_copyable<_InIter, _OutIter> && + indirect_binary_predicate, 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 { - // TODO: implement - (void)__first; (void)__last; (void)__result; (void)__old_value; (void)__new_value; (void)__proj; - return {}; - } + 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 _OutIter, - class _Proj = identity> - requires indirectly_copyable, _OutIter> && - indirect_binary_predicate, _Proj>, const _Type1*> - _LIBCPP_HIDE_FROM_ABI constexpr - replace_copy_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, const _Type1& __old_value, const _Type2& __new_value, + template _OutIter, + class _Proj = identity> + requires indirectly_copyable, _OutIter> && + indirect_binary_predicate, _Proj>, const _OldType*> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result, _OutIter> + operator()(_Range&& __range, + _OutIter __result, + const _OldType& __old_value, + const _NewType& __new_value, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__result; (void)__old_value; (void)__new_value; (void)__proj; - return {}; - } - -}; + 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 diff --git a/lib/libcxx/include/__algorithm/ranges_replace_copy_if.h b/lib/libcxx/include/__algorithm/ranges_replace_copy_if.h index 2a908e2057..7602e8a144 100644 --- a/lib/libcxx/include/__algorithm/ranges_replace_copy_if.h +++ b/lib/libcxx/include/__algorithm/ranges_replace_copy_if.h @@ -10,19 +10,14 @@ #define _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_IF_H #include <__algorithm/in_out_result.h> -#include <__algorithm/make_projected.h> -#include <__algorithm/replace_copy_if.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> -#include <__functional/ranges_operations.h> #include <__iterator/concepts.h> -#include <__iterator/iterator_traits.h> #include <__iterator/projected.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/dangling.h> -#include <__utility/forward.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -38,34 +33,51 @@ namespace ranges { template using replace_copy_if_result = in_out_result<_InIter, _OutIter>; +template +_LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> __replace_copy_if_impl( + _InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, const _Type& __new_value, _Proj& __proj) { + while (__first != __last) { + if (std::invoke(__pred, std::invoke(__proj, *__first))) + *__result = __new_value; + else + *__result = *__first; + + ++__first; + ++__result; + } + + return {std::move(__first), std::move(__result)}; +} + namespace __replace_copy_if { -struct __fn { + struct __fn { + template _Sent, + class _Type, + output_iterator _OutIter, + class _Proj = identity, + indirect_unary_predicate> _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 _Sent, class _Type, output_iterator _OutIter, - class _Proj = identity, indirect_unary_predicate> _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 { - // TODO: implement - (void)__first; (void)__last; (void)__result; (void)__pred; (void)__new_value; (void)__proj; - return {}; - } - - template _OutIter, class _Proj = identity, - indirect_unary_predicate, _Proj>> _Pred> - requires indirectly_copyable, _OutIter> - _LIBCPP_HIDE_FROM_ABI constexpr - replace_copy_if_result, _OutIter> - operator()(_Range&& __range, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const { - // TODO: implement - (void)__range; (void)__result; (void)__pred; (void)__new_value; (void)__proj; - return {}; - } - -}; + template _OutIter, + class _Proj = identity, + indirect_unary_predicate, _Proj>> _Pred> + requires indirectly_copyable, _OutIter> + _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result, _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 diff --git a/lib/libcxx/include/__algorithm/ranges_rotate.h b/lib/libcxx/include/__algorithm/ranges_rotate.h new file mode 100644 index 0000000000..1cd69a141f --- /dev/null +++ b/lib/libcxx/include/__algorithm/ranges_rotate.h @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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_ROTATE_H +#define _LIBCPP___ALGORITHM_RANGES_ROTATE_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/ranges_iterator_concept.h> +#include <__algorithm/rotate.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/permutable.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/subrange.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __rotate { + +struct __fn { + + template + _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 _Sent> + _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 + requires permutable> + _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{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_H diff --git a/lib/libcxx/include/__algorithm/ranges_sample.h b/lib/libcxx/include/__algorithm/ranges_sample.h new file mode 100644 index 0000000000..a8477f8037 --- /dev/null +++ b/lib/libcxx/include/__algorithm/ranges_sample.h @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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_SAMPLE_H +#define _LIBCPP___ALGORITHM_RANGES_SAMPLE_H + +#include <__algorithm/iterator_operations.h> +#include <__algorithm/sample.h> +#include <__algorithm/uniform_random_bit_generator_adaptor.h> +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__random/uniform_random_bit_generator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { +namespace __sample { + +struct __fn { + + template _Sent, weakly_incrementable _OutIter, class _Gen> + requires (forward_iterator<_Iter> || random_access_iterator<_OutIter>) && + indirectly_copyable<_Iter, _OutIter> && + uniform_random_bit_generator> + _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 + requires (forward_range<_Range> || random_access_iterator<_OutIter>) && + indirectly_copyable, _OutIter> && + uniform_random_bit_generator> + _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{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) + +#endif // _LIBCPP___ALGORITHM_RANGES_SAMPLE_H diff --git a/lib/libcxx/include/__algorithm/ranges_shuffle.h b/lib/libcxx/include/__algorithm/ranges_shuffle.h index b101a8582e..9b7f81e489 100644 --- a/lib/libcxx/include/__algorithm/ranges_shuffle.h +++ b/lib/libcxx/include/__algorithm/ranges_shuffle.h @@ -11,6 +11,7 @@ #include <__algorithm/iterator_operations.h> #include <__algorithm/shuffle.h> +#include <__algorithm/uniform_random_bit_generator_adaptor.h> #include <__config> #include <__functional/invoke.h> #include <__functional/ranges_operations.h> @@ -32,43 +33,12 @@ #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __shuffle { struct __fn { - // `std::shuffle` is more constrained than `std::ranges::shuffle`. `std::ranges::shuffle` only requires the given - // generator to satisfy the `std::uniform_random_bit_generator` concept. `std::shuffle` requires the given - // generator to meet the uniform random bit generator requirements; these requirements include satisfying - // `std::uniform_random_bit_generator` and add a requirement for the generator to provide a nested `result_type` - // typedef (see `[rand.req.urng]`). - // - // To reuse the implementation from `std::shuffle`, make the given generator meet the classic requirements by wrapping - // it into an adaptor type that forwards all of its interface and adds the required typedef. - template - class _ClassicGenAdaptor { - private: - // The generator is not required to be copyable or movable, so it has to be stored as a reference. - _Gen& __gen; - - public: - using result_type = invoke_result_t<_Gen&>; - - _LIBCPP_HIDE_FROM_ABI - static constexpr auto min() { return __uncvref_t<_Gen>::min(); } - _LIBCPP_HIDE_FROM_ABI - static constexpr auto max() { return __uncvref_t<_Gen>::max(); } - - _LIBCPP_HIDE_FROM_ABI - constexpr explicit _ClassicGenAdaptor(_Gen& __g) : __gen(__g) {} - - _LIBCPP_HIDE_FROM_ABI - constexpr auto operator()() const { return __gen(); } - }; template _Sent, class _Gen> requires permutable<_Iter> && uniform_random_bit_generator> @@ -96,8 +66,6 @@ inline namespace __cpo { _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) #endif // _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H diff --git a/lib/libcxx/include/__algorithm/ranges_swap_ranges.h b/lib/libcxx/include/__algorithm/ranges_swap_ranges.h index 3254e1c60a..d980fdec2c 100644 --- a/lib/libcxx/include/__algorithm/ranges_swap_ranges.h +++ b/lib/libcxx/include/__algorithm/ranges_swap_ranges.h @@ -10,6 +10,8 @@ #define _LIBCPP___ALGORITHM_RANGES_SWAP_RANGES_H #include <__algorithm/in_in_result.h> +#include <__algorithm/iterator_operations.h> +#include <__algorithm/swap_ranges.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/iter_swap.h> @@ -38,12 +40,9 @@ struct __fn { 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 { - while (__first1 != __last1 && __first2 != __last2) { - ranges::iter_swap(__first1, __first2); - ++__first1; - ++__first2; - } - return {_VSTD::move(__first1), _VSTD::move(__first2)}; + auto __ret = std::__swap_ranges<_RangeAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2)); + return {std::move(__ret.first), std::move(__ret.second)}; } template diff --git a/lib/libcxx/include/__algorithm/reverse.h b/lib/libcxx/include/__algorithm/reverse.h index 0202cd7408..6484c73752 100644 --- a/lib/libcxx/include/__algorithm/reverse.h +++ b/lib/libcxx/include/__algorithm/reverse.h @@ -10,8 +10,10 @@ #define _LIBCPP___ALGORITHM_REVERSE_H #include <__algorithm/iter_swap.h> +#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -19,28 +21,35 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void -__reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, bidirectional_iterator_tag) +__reverse_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, bidirectional_iterator_tag) { while (__first != __last) { if (__first == --__last) break; - _VSTD::iter_swap(__first, __last); + _IterOps<_AlgPolicy>::iter_swap(__first, __last); ++__first; } } -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void -__reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag) +__reverse_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag) { if (__first != __last) for (; __first < --__last; ++__first) - _VSTD::iter_swap(__first, __last); + _IterOps<_AlgPolicy>::iter_swap(__first, __last); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 +void __reverse(_BidirectionalIterator __first, _Sentinel __last) { + using _IterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_BidirectionalIterator>; + std::__reverse_impl<_AlgPolicy>(std::move(__first), std::move(__last), _IterCategory()); } template @@ -48,7 +57,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) { - _VSTD::__reverse(__first, __last, typename iterator_traits<_BidirectionalIterator>::iterator_category()); + std::__reverse<_ClassicAlgPolicy>(std::move(__first), std::move(__last)); } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/rotate.h b/lib/libcxx/include/__algorithm/rotate.h index fcf8444a65..beb5409d5b 100644 --- a/lib/libcxx/include/__algorithm/rotate.h +++ b/lib/libcxx/include/__algorithm/rotate.h @@ -15,10 +15,8 @@ #include <__algorithm/swap_ranges.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <__iterator/next.h> -#include <__iterator/prev.h> #include <__utility/move.h> -#include <__utility/swap.h> +#include <__utility/pair.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -32,9 +30,11 @@ _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator __rotate_left(_ForwardIterator __first, _ForwardIterator __last) { typedef typename iterator_traits<_ForwardIterator>::value_type value_type; - value_type __tmp = _IterOps<_AlgPolicy>::__iter_move(__first); - // TODO(ranges): pass `_AlgPolicy` to `move`. - _ForwardIterator __lm1 = _VSTD::move(_VSTD::next(__first), __last, __first); + using _Ops = _IterOps<_AlgPolicy>; + + value_type __tmp = _Ops::__iter_move(__first); + _ForwardIterator __lm1 = std::__move<_AlgPolicy>( + _Ops::next(__first), __last, __first).second; *__lm1 = _VSTD::move(__tmp); return __lm1; } @@ -44,11 +44,11 @@ _LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator __rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) { typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; - // TODO(ranges): pass `_AlgPolicy` to `prev`. - _BidirectionalIterator __lm1 = _VSTD::prev(__last); - value_type __tmp = _IterOps<_AlgPolicy>::__iter_move(__lm1); - // TODO(ranges): pass `_AlgPolicy` to `move_backward`. - _BidirectionalIterator __fp1 = _VSTD::move_backward(__first, __lm1, __last); + using _Ops = _IterOps<_AlgPolicy>; + + _BidirectionalIterator __lm1 = _Ops::prev(__last); + value_type __tmp = _Ops::__iter_move(__lm1); + _BidirectionalIterator __fp1 = std::__move_backward<_AlgPolicy>(__first, __lm1, std::move(__last)); *__first = _VSTD::move(__tmp); return __fp1; } @@ -108,26 +108,26 @@ __rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Ran { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; + using _Ops = _IterOps<_AlgPolicy>; const difference_type __m1 = __middle - __first; - const difference_type __m2 = __last - __middle; + const difference_type __m2 = _Ops::distance(__middle, __last); if (__m1 == __m2) { - // TODO(ranges): pass `_AlgPolicy` to `swap_ranges`. - _VSTD::swap_ranges(__first, __middle, __middle); + std::__swap_ranges<_AlgPolicy>(__first, __middle, __middle, __last); return __middle; } const difference_type __g = _VSTD::__algo_gcd(__m1, __m2); for (_RandomAccessIterator __p = __first + __g; __p != __first;) { - value_type __t(_IterOps<_AlgPolicy>::__iter_move(--__p)); + value_type __t(_Ops::__iter_move(--__p)); _RandomAccessIterator __p1 = __p; _RandomAccessIterator __p2 = __p1 + __m1; do { - *__p1 = _IterOps<_AlgPolicy>::__iter_move(__p2); + *__p1 = _Ops::__iter_move(__p2); __p1 = __p2; - const difference_type __d = __last - __p2; + const difference_type __d = _Ops::distance(__p2, __last); if (__m1 < __d) __p2 += __m1; else @@ -188,16 +188,23 @@ __rotate_impl(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Ra return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last); } -template +template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 -_RandomAccessIterator __rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, - _RandomAccessIterator __last, _IterCategory __iter_category) { - if (__first == __middle) - return __last; - if (__middle == __last) - return __first; +pair<_Iterator, _Iterator> +__rotate(_Iterator __first, _Iterator __middle, _Sentinel __last) { + using _Ret = pair<_Iterator, _Iterator>; + _Iterator __last_iter = _IterOps<_AlgPolicy>::next(__middle, __last); - return std::__rotate_impl<_AlgPolicy>(std::move(__first), std::move(__middle), std::move(__last), __iter_category); + if (__first == __middle) + return _Ret(__last_iter, __last_iter); + if (__middle == __last) + return _Ret(std::move(__first), std::move(__last_iter)); + + using _IterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_Iterator>; + auto __result = std::__rotate_impl<_AlgPolicy>( + std::move(__first), std::move(__middle), __last_iter, _IterCategory()); + + return _Ret(std::move(__result), std::move(__last_iter)); } template @@ -205,8 +212,8 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { - return std::__rotate<_ClassicAlgPolicy>(__first, __middle, __last, - typename iterator_traits<_ForwardIterator>::iterator_category()); + return std::__rotate<_ClassicAlgPolicy>( + std::move(__first), std::move(__middle), std::move(__last)).first; } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/sample.h b/lib/libcxx/include/__algorithm/sample.h index e04466a08d..f403ba6125 100644 --- a/lib/libcxx/include/__algorithm/sample.h +++ b/lib/libcxx/include/__algorithm/sample.h @@ -9,12 +9,14 @@ #ifndef _LIBCPP___ALGORITHM_SAMPLE_H #define _LIBCPP___ALGORITHM_SAMPLE_H +#include <__algorithm/iterator_operations.h> #include <__algorithm/min.h> #include <__assert> #include <__config> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__random/uniform_int_distribution.h> +#include <__utility/move.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -26,13 +28,14 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -template _LIBCPP_INLINE_VISIBILITY _SampleIterator __sample(_PopulationIterator __first, - _PopulationIterator __last, _SampleIterator __output_iter, + _PopulationSentinel __last, _SampleIterator __output_iter, _Distance __n, - _UniformRandomNumberGenerator & __g, + _UniformRandomNumberGenerator& __g, input_iterator_tag) { _Distance __k = 0; @@ -47,15 +50,16 @@ _SampleIterator __sample(_PopulationIterator __first, return __output_iter + _VSTD::min(__n, __k); } -template _LIBCPP_INLINE_VISIBILITY _SampleIterator __sample(_PopulationIterator __first, - _PopulationIterator __last, _SampleIterator __output_iter, + _PopulationSentinel __last, _SampleIterator __output_iter, _Distance __n, _UniformRandomNumberGenerator& __g, forward_iterator_tag) { - _Distance __unsampled_sz = _VSTD::distance(__first, __last); + _Distance __unsampled_sz = _IterOps<_AlgPolicy>::distance(__first, __last); for (__n = _VSTD::min(__n, __unsampled_sz); __n != 0; ++__first) { _Distance __r = uniform_int_distribution<_Distance>(0, --__unsampled_sz)(__g); if (__r < __n) { @@ -66,24 +70,22 @@ _SampleIterator __sample(_PopulationIterator __first, return __output_iter; } -template _LIBCPP_INLINE_VISIBILITY _SampleIterator __sample(_PopulationIterator __first, - _PopulationIterator __last, _SampleIterator __output_iter, + _PopulationSentinel __last, _SampleIterator __output_iter, _Distance __n, _UniformRandomNumberGenerator& __g) { - typedef typename iterator_traits<_PopulationIterator>::iterator_category - _PopCategory; - typedef typename iterator_traits<_PopulationIterator>::difference_type - _Difference; - static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value || - __is_cpp17_random_access_iterator<_SampleIterator>::value, - "SampleIterator must meet the requirements of RandomAccessIterator"); - typedef typename common_type<_Distance, _Difference>::type _CommonType; _LIBCPP_ASSERT(__n >= 0, "N must be a positive number."); - return _VSTD::__sample( - __first, __last, __output_iter, _CommonType(__n), - __g, _PopCategory()); + + using _PopIterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_PopulationIterator>; + using _Difference = typename _IterOps<_AlgPolicy>::template __difference_type<_PopulationIterator>; + using _CommonType = typename common_type<_Distance, _Difference>::type; + + return std::__sample<_AlgPolicy>( + std::move(__first), std::move(__last), std::move(__output_iter), _CommonType(__n), + __g, _PopIterCategory()); } #if _LIBCPP_STD_VER > 14 @@ -93,8 +95,14 @@ inline _LIBCPP_INLINE_VISIBILITY _SampleIterator sample(_PopulationIterator __first, _PopulationIterator __last, _SampleIterator __output_iter, _Distance __n, _UniformRandomNumberGenerator&& __g) { - return _VSTD::__sample(__first, __last, __output_iter, __n, __g); + static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value || + __is_cpp17_random_access_iterator<_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 _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/stable_partition.h b/lib/libcxx/include/__algorithm/stable_partition.h index e5ad48b2ed..c7aa3f07a8 100644 --- a/lib/libcxx/include/__algorithm/stable_partition.h +++ b/lib/libcxx/include/__algorithm/stable_partition.h @@ -108,7 +108,7 @@ __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Pred __second_half_done: // TTTFFFFFTTTTTFFFFF // f ff m sf l - return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false, __fit); + return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first; // TTTTTTTTFFFFFFFFFF // | } @@ -253,7 +253,7 @@ __first_half_done: __second_half_done: // TTTFFFFFTTTTTFFFFF // f ff m sf l - return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false, __bit); + return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first; // TTTTTTTTFFFFFFFFFF // | } diff --git a/lib/libcxx/include/__algorithm/swap_ranges.h b/lib/libcxx/include/__algorithm/swap_ranges.h index 0422265bb4..0cff519a8d 100644 --- a/lib/libcxx/include/__algorithm/swap_ranges.h +++ b/lib/libcxx/include/__algorithm/swap_ranges.h @@ -9,8 +9,10 @@ #ifndef _LIBCPP___ALGORITHM_SWAP_RANGES_H #define _LIBCPP___ALGORITHM_SWAP_RANGES_H +#include <__algorithm/iterator_operations.h> #include <__config> -#include <__utility/swap.h> +#include <__utility/move.h> +#include <__utility/pair.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -18,12 +20,39 @@ _LIBCPP_BEGIN_NAMESPACE_STD +// 2+2 iterators: the shorter size will be used. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 +pair<_ForwardIterator1, _ForwardIterator2> +__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _Sentinel2 __last2) { + while (__first1 != __last1 && __first2 != __last2) { + _IterOps<_AlgPolicy>::iter_swap(__first1, __first2); + ++__first1; + ++__first2; + } + + return pair<_ForwardIterator1, _ForwardIterator2>(std::move(__first1), std::move(__first2)); +} + +// 2+1 iterators: size2 >= size1. +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 +pair<_ForwardIterator1, _ForwardIterator2> +__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2) { + while (__first1 != __last1) { + _IterOps<_AlgPolicy>::iter_swap(__first1, __first2); + ++__first1; + ++__first2; + } + + return pair<_ForwardIterator1, _ForwardIterator2>(std::move(__first1), std::move(__first2)); +} + template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator2 swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) { - for (; __first1 != __last1; ++__first1, (void)++__first2) - swap(*__first1, *__first2); - return __first2; + return std::__swap_ranges<_ClassicAlgPolicy>( + std::move(__first1), std::move(__last1), std::move(__first2)).second; } _LIBCPP_END_NAMESPACE_STD diff --git a/lib/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h b/lib/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h new file mode 100644 index 0000000000..04a67752dd --- /dev/null +++ b/lib/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.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_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H +#define _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H + +#include <__config> +#include <__functional/invoke.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 17 + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Range versions of random algorithms (e.g. `std::shuffle`) are less constrained than their classic counterparts. +// Range algorithms only require the given generator to satisfy the `std::uniform_random_bit_generator` concept. +// Classic algorithms require the given generator to meet the uniform random bit generator requirements; these +// requirements include satisfying `std::uniform_random_bit_generator` and add a requirement for the generator to +// provide a nested `result_type` typedef (see `[rand.req.urng]`). +// +// To be able to reuse classic implementations, make the given generator meet the classic requirements by wrapping +// it into an adaptor type that forwards all of its interface and adds the required typedef. +template +class _ClassicGenAdaptor { +private: + // The generator is not required to be copyable or movable, so it has to be stored as a reference. + _Gen& __gen; + +public: + using result_type = invoke_result_t<_Gen&>; + + _LIBCPP_HIDE_FROM_ABI + static constexpr auto min() { return __uncvref_t<_Gen>::min(); } + _LIBCPP_HIDE_FROM_ABI + static constexpr auto max() { return __uncvref_t<_Gen>::max(); } + + _LIBCPP_HIDE_FROM_ABI + constexpr explicit _ClassicGenAdaptor(_Gen& __g) : __gen(__g) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr auto operator()() const { return __gen(); } +}; + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_STD_VER > 17 + +#endif // _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H diff --git a/lib/libcxx/include/__availability b/lib/libcxx/include/__availability index d64bde1253..72ff663334 100644 --- a/lib/libcxx/include/__availability +++ b/lib/libcxx/include/__availability @@ -166,11 +166,11 @@ // user has provided their own). // // Users can pass -D_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED - // to the compiler to tell the library to ignore the fact that the - // default function isn't available on their deployment target. Note that - // defining this macro but failing to define a custom function will lead to - // a load-time error on back-deployment targets, so it should be avoided. -# define _LIBCPP_AVAILABILITY_DEFAULT_VERBOSE_ABORT + // to the compiler to tell the library not to define its own verbose abort. + // Note that defining this macro but failing to define a custom function + // will lead to a load-time error on back-deployment targets, so it should + // be avoided. +// # define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY #elif defined(__APPLE__) @@ -271,8 +271,8 @@ __attribute__((unavailable)) # define _LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format -# define _LIBCPP_AVAILABILITY_DEFAULT_VERBOSE_ABORT \ - __attribute__((unavailable)) +# define _LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY + #else // ...New vendors can add availability markup here... @@ -296,14 +296,4 @@ # define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS #endif -// Define the special verbose termination function availability attribute, which can be silenced by -// users if they provide their own custom function. The rest of the code should not use the -// *_DEFAULT_* macro directly, since that would make it ignore the fact that the user provided -// a custom function. -#if defined(_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED) -# define _LIBCPP_AVAILABILITY_VERBOSE_ABORT /* nothing */ -#else -# define _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_AVAILABILITY_DEFAULT_VERBOSE_ABORT -#endif - #endif // _LIBCPP___AVAILABILITY diff --git a/lib/libcxx/include/__iterator/incrementable_traits.h b/lib/libcxx/include/__iterator/incrementable_traits.h index 4109b58d46..e6a5ed720f 100644 --- a/lib/libcxx/include/__iterator/incrementable_traits.h +++ b/lib/libcxx/include/__iterator/incrementable_traits.h @@ -13,6 +13,7 @@ #include <__config> #include <__type_traits/is_primary_template.h> #include +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/lib/libcxx/include/__iterator/iterator_traits.h b/lib/libcxx/include/__iterator/iterator_traits.h index 254f8c2339..0cc64adc0d 100644 --- a/lib/libcxx/include/__iterator/iterator_traits.h +++ b/lib/libcxx/include/__iterator/iterator_traits.h @@ -14,6 +14,7 @@ #include <__iterator/incrementable_traits.h> #include <__iterator/readable_traits.h> #include +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -507,6 +508,12 @@ using __iterator_category_type = typename iterator_traits<_Iter>::iterator_categ template using __iterator_pointer_type = typename iterator_traits<_Iter>::pointer; +template +using __iter_diff_t = typename iterator_traits<_Iter>::difference_type; + +template +using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___ITERATOR_ITERATOR_TRAITS_H diff --git a/lib/libcxx/include/__iterator/reverse_iterator.h b/lib/libcxx/include/__iterator/reverse_iterator.h index abc8896c0a..7b002205f3 100644 --- a/lib/libcxx/include/__iterator/reverse_iterator.h +++ b/lib/libcxx/include/__iterator/reverse_iterator.h @@ -363,7 +363,7 @@ class __unconstrained_reverse_iterator { _Iter __iter_; public: - static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value); + static_assert(__is_cpp17_bidirectional_iterator<_Iter>::value || bidirectional_iterator<_Iter>); using iterator_type = _Iter; using iterator_category = @@ -391,6 +391,14 @@ public: } } + _LIBCPP_HIDE_FROM_ABI friend constexpr + iter_rvalue_reference_t<_Iter> iter_move(const __unconstrained_reverse_iterator& __i) + noexcept(is_nothrow_copy_constructible_v<_Iter> && + noexcept(ranges::iter_move(--declval<_Iter&>()))) { + auto __tmp = __i.base(); + return ranges::iter_move(--__tmp); + } + _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator& operator++() { --__iter_; return *this; diff --git a/lib/libcxx/include/__memory/pointer_traits.h b/lib/libcxx/include/__memory/pointer_traits.h index c4cd56a21f..348f7323a4 100644 --- a/lib/libcxx/include/__memory/pointer_traits.h +++ b/lib/libcxx/include/__memory/pointer_traits.h @@ -12,6 +12,7 @@ #include <__config> #include <__memory/addressof.h> +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -171,9 +172,30 @@ _Tp* __to_address(_Tp* __p) _NOEXCEPT { return __p; } +template +struct _HasToAddress : false_type {}; + +template +struct _HasToAddress<_Pointer, + decltype((void)pointer_traits<_Pointer>::to_address(declval())) +> : true_type {}; + +template +struct _HasArrow : false_type {}; + +template +struct _HasArrow<_Pointer, + decltype((void)declval().operator->()) +> : true_type {}; + +template +struct _IsFancyPointer { + static const bool value = _HasArrow<_Pointer>::value || _HasToAddress<_Pointer>::value; +}; + // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers template ::value && !is_array<_Pointer>::value && !is_function<_Pointer>::value + _And, _IsFancyPointer<_Pointer> >::value > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename decay::__call(declval()))>::type @@ -208,7 +230,7 @@ auto to_address(_Tp *__p) noexcept { template inline _LIBCPP_INLINE_VISIBILITY constexpr -auto to_address(const _Pointer& __p) noexcept { +auto to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p)) { return _VSTD::__to_address(__p); } #endif diff --git a/lib/libcxx/include/__ranges/size.h b/lib/libcxx/include/__ranges/size.h index 32ca4b854b..0e6d295651 100644 --- a/lib/libcxx/include/__ranges/size.h +++ b/lib/libcxx/include/__ranges/size.h @@ -16,6 +16,7 @@ #include <__ranges/access.h> #include <__utility/auto_cast.h> #include +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/lib/libcxx/include/__verbose_abort b/lib/libcxx/include/__verbose_abort index 489047c74c..3c9cba824c 100644 --- a/lib/libcxx/include/__verbose_abort +++ b/lib/libcxx/include/__verbose_abort @@ -17,11 +17,35 @@ # pragma GCC system_header #endif +// Provide a default implementation of __libcpp_verbose_abort if we know that neither the built +// library not the user is providing one. Otherwise, just declare it and use the one from the +// built library or the one provided by the user. +// +// We can't provide a great implementation because it needs to be pretty much +// dependency-free (this is included everywhere else in the library). +#if defined(_LIBCPP_HAS_NO_VERBOSE_ABORT_IN_LIBRARY) && !defined(_LIBCPP_AVAILABILITY_CUSTOM_VERBOSE_ABORT_PROVIDED) + +extern "C" void abort(); + _LIBCPP_BEGIN_NAMESPACE_STD -_LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) +_LIBCPP_NORETURN _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) _LIBCPP_HIDE_FROM_ABI inline +void __libcpp_verbose_abort(const char *, ...) { + ::abort(); + __builtin_unreachable(); // never reached, but needed to tell the compiler that the function never returns +} + +_LIBCPP_END_NAMESPACE_STD + +#else + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_NORETURN _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) void __libcpp_verbose_abort(const char *__format, ...); _LIBCPP_END_NAMESPACE_STD +#endif + #endif // _LIBCPP___VERBOSE_ABORT diff --git a/lib/libcxx/include/algorithm b/lib/libcxx/include/algorithm index 92e9327442..69ada03874 100644 --- a/lib/libcxx/include/algorithm +++ b/lib/libcxx/include/algorithm @@ -593,6 +593,11 @@ namespace ranges { constexpr borrowed_iterator_t ranges::replace_if(R&& r, Pred pred, const T& new_value, Proj proj = {}); // since C++20 + template> Comp = ranges::less> + constexpr const T& + ranges::clamp(const T& v, const T& lo, const T& hi, Comp comp = {}, Proj proj = {}); // since C++20 + template S1, input_iterator I2, sentinel_for S2, class Proj1 = identity, class Proj2 = identity, indirect_strict_weak_order, @@ -745,6 +750,13 @@ namespace ranges { constexpr ranges::reverse_copy_result, O> ranges::reverse_copy(R&& r, O result); // since C++20 + template S> + constexpr subrange rotate(I first, I middle, S last); // since C++20 + + template + requires permutable> + constexpr borrowed_subrange_t rotate(R&& r, iterator_t middle); // Since C++20 + template using rotate_copy_result = in_out_result<_InIter, _OutIter>; // since C++20 @@ -758,6 +770,18 @@ namespace ranges { constexpr ranges::rotate_copy_result, O> ranges::rotate_copy(R&& r, iterator_t middle, O result); // since C++20 + template S, weakly_incrementable O, class Gen> + requires (forward_iterator || random_access_iterator) && + indirectly_copyable && + uniform_random_bit_generator> + O sample(I first, S last, O out, iter_difference_t n, Gen&& g); // Since C++20 + + template + requires (forward_range || random_access_iterator) && + indirectly_copyable, O> && + uniform_random_bit_generator> + O sample(R&& r, O out, range_difference_t n, Gen&& g); // Since C++20 + template S, class Gen> requires permutable && uniform_random_bit_generator> @@ -768,6 +792,21 @@ namespace ranges { uniform_random_bit_generator> borrowed_iterator_t shuffle(R&& r, Gen&& g); // Since C++20 + template S1, forward_iterator I2, + sentinel_for S2, class Proj1 = identity, class Proj2 = identity, + indirect_equivalence_relation, + projected> 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 + + template, Proj1>, + projected, Proj2>> Pred = ranges::equal_to> + constexpr bool ranges::is_permutation(R1&& r1, R2&& r2, Pred pred = {}, + Proj1 proj1 = {}, Proj2 proj2 = {}); // Since C++20 + template S1, forward_iterator I2, sentinel_for S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> @@ -912,8 +951,108 @@ namespace ranges { indirectly_copyable_storable, O>) constexpr unique_copy_result, O> unique_copy(R&& r, O result, C comp = {}, Proj proj = {}); // Since C++20 + + template + using remove_copy_result = in_out_result; // Since C++20 + + template S, weakly_incrementable O, class T, + class Proj = identity> + indirect_binary_predicate, const T*> + constexpr remove_copy_result + remove_copy(I first, S last, O result, const T& value, Proj proj = {}); // Since C++20 + + template + requires indirectly_copyable, O> && + indirect_binary_predicate, Proj>, const T*> + constexpr remove_copy_result, O> + remove_copy(R&& r, O result, const T& value, Proj proj = {}); // Since C++20 + + template + using remove_copy_if_result = in_out_result; // Since C++20 + + template S, weakly_incrementable O, + class Proj = identity, indirect_unary_predicate> Pred> + requires indirectly_copyable + constexpr remove_copy_if_result + remove_copy_if(I first, S last, O result, Pred pred, Proj proj = {}); // Since C++20 + + template, Proj>> Pred> + requires indirectly_copyable, O> + constexpr remove_copy_if_result, O> + remove_copy_if(R&& r, O result, Pred pred, Proj proj = {}); // Since C++20 + + template + using replace_copy_result = in_out_result; // Since C++20 + + template S, class T1, class T2, + output_iterator O, class Proj = identity> + requires indirectly_copyable && + indirect_binary_predicate, const T1*> + constexpr replace_copy_result + replace_copy(I first, S last, O result, const T1& old_value, const T2& new_value, + Proj proj = {}); // Since C++20 + + template O, + class Proj = identity> + requires indirectly_copyable, O> && + indirect_binary_predicate, Proj>, const T1*> + constexpr replace_copy_result, O> + replace_copy(R&& r, O result, const T1& old_value, const T2& new_value, + Proj proj = {}); // Since C++20 + + template + using replace_copy_if_result = in_out_result; // Since C++20 + + template S, class T, output_iterator O, + class Proj = identity, indirect_unary_predicate> Pred> + requires indirectly_copyable + constexpr replace_copy_if_result + replace_copy_if(I first, S last, O result, Pred pred, const T& new_value, + Proj proj = {}); // Since C++20 + + template O, class Proj = identity, + indirect_unary_predicate, Proj>> Pred> + requires indirectly_copyable, O> + constexpr replace_copy_if_result, O> + replace_copy_if(R&& r, O result, Pred pred, const T& new_value, + Proj proj = {}); // Since C++20 + + template + using prev_permutation_result = in_found_result; // Since C++20 + + template S, class Comp = ranges::less, + class Proj = identity> + requires sortable + constexpr ranges::prev_permutation_result + ranges::prev_permutation(I first, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + + template + requires sortable, Comp, Proj> + constexpr ranges::prev_permutation_result> + ranges::prev_permutation(R&& r, Comp comp = {}, Proj proj = {}); // Since C++20 + + template + using next_permutation_result = in_found_result; // Since C++20 + + template S, class Comp = ranges::less, + class Proj = identity> + requires sortable + constexpr ranges::next_permutation_result + ranges::next_permutation(I first, S last, Comp comp = {}, Proj proj = {}); // Since C++20 + + template + requires sortable, Comp, Proj> + constexpr ranges::next_permutation_result> + ranges::next_permutation(R&& r, Comp comp = {}, Proj proj = {}); // Since C++20 + } +template constexpr bool // constexpr in C++20 all_of(InputIterator first, InputIterator last, Predicate pred); @@ -1645,6 +1784,7 @@ template #include <__algorithm/ranges_all_of.h> #include <__algorithm/ranges_any_of.h> #include <__algorithm/ranges_binary_search.h> +#include <__algorithm/ranges_clamp.h> #include <__algorithm/ranges_copy.h> #include <__algorithm/ranges_copy_backward.h> #include <__algorithm/ranges_copy_if.h> @@ -1669,6 +1809,7 @@ template #include <__algorithm/ranges_is_heap.h> #include <__algorithm/ranges_is_heap_until.h> #include <__algorithm/ranges_is_partitioned.h> +#include <__algorithm/ranges_is_permutation.h> #include <__algorithm/ranges_is_sorted.h> #include <__algorithm/ranges_is_sorted_until.h> #include <__algorithm/ranges_lexicographical_compare.h> @@ -1684,6 +1825,7 @@ template #include <__algorithm/ranges_mismatch.h> #include <__algorithm/ranges_move.h> #include <__algorithm/ranges_move_backward.h> +#include <__algorithm/ranges_next_permutation.h> #include <__algorithm/ranges_none_of.h> #include <__algorithm/ranges_nth_element.h> #include <__algorithm/ranges_partial_sort.h> @@ -1692,14 +1834,21 @@ template #include <__algorithm/ranges_partition_copy.h> #include <__algorithm/ranges_partition_point.h> #include <__algorithm/ranges_pop_heap.h> +#include <__algorithm/ranges_prev_permutation.h> #include <__algorithm/ranges_push_heap.h> #include <__algorithm/ranges_remove.h> +#include <__algorithm/ranges_remove_copy.h> +#include <__algorithm/ranges_remove_copy_if.h> #include <__algorithm/ranges_remove_if.h> #include <__algorithm/ranges_replace.h> +#include <__algorithm/ranges_replace_copy.h> +#include <__algorithm/ranges_replace_copy_if.h> #include <__algorithm/ranges_replace_if.h> #include <__algorithm/ranges_reverse.h> #include <__algorithm/ranges_reverse_copy.h> +#include <__algorithm/ranges_rotate.h> #include <__algorithm/ranges_rotate_copy.h> +#include <__algorithm/ranges_sample.h> #include <__algorithm/ranges_search.h> #include <__algorithm/ranges_search_n.h> #include <__algorithm/ranges_set_difference.h> diff --git a/lib/libcxx/include/format b/lib/libcxx/include/format index d2ec8fc233..6b14570bc6 100644 --- a/lib/libcxx/include/format +++ b/lib/libcxx/include/format @@ -23,16 +23,23 @@ namespace std { using format_args = basic_format_args; using wformat_args = basic_format_args; - // [format.fmt.string], class template basic-format-string + // [format.fmt.string], class template basic_format_string template - struct basic-format-string; // exposition only + struct basic_format_string { // since C++23, exposition only before C++23 + private: + basic_string_view str; // exposition only + public: + template consteval basic_format_string(const T& s); + + constexpr basic_string_view get() const noexcept { return str; } + }; template - using format-string = // exposition only - basic-format-string...>; + using format_string = // since C++23, exposition only before C++23 + basic_format_string...>; template - using wformat-string = // exposition only - basic-format-string...>; + using wformat_string = // since C++23, exposition only before C++23 + basic_format_string...>; // [format.functions], formatting functions template @@ -233,7 +240,7 @@ private: }; // Dummy format_context only providing the parts used during constant -// validation of the basic-format-string. +// validation of the basic_format_string. template struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context { public: @@ -468,17 +475,21 @@ __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { } // namespace __format template -struct _LIBCPP_TEMPLATE_VIS __basic_format_string { - basic_string_view<_CharT> __str_; - +struct _LIBCPP_TEMPLATE_VIS basic_format_string { template requires convertible_to> - consteval __basic_format_string(const _Tp& __str) : __str_{__str} { + consteval basic_format_string(const _Tp& __str) : __str_{__str} { __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)}, _Context{__types_.data(), __handles_.data(), sizeof...(_Args)}); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept { + return __str_; + } + private: + basic_string_view<_CharT> __str_; + using _Context = __format::__compile_time_basic_format_context<_CharT>; static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ @@ -510,11 +521,11 @@ private: }; template -using __format_string_t = __basic_format_string...>; +using format_string = basic_format_string...>; #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template -using __wformat_string_t = __basic_format_string...>; +using wformat_string = basic_format_string...>; #endif template @@ -555,16 +566,16 @@ vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, +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...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_, +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 @@ -586,16 +597,16 @@ vformat(wstring_view __fmt, wformat_args __args) { #endif template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(__format_string_t<_Args...> __fmt, +_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(__fmt.__str_, _VSTD::make_format_args(__args...)); + return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring -format(__wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(__fmt.__str_, _VSTD::make_wformat_args(__args...)); +format(wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -611,16 +622,16 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_format_args(__args...)); +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __wformat_string_t<_Args...> __fmt, +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_wformat_args(__args...)); + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -634,15 +645,15 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(__format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); +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 template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(__wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); +formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); } #endif @@ -686,16 +697,16 @@ _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt v template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, +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...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_, +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 @@ -720,17 +731,17 @@ vformat(locale __loc, wstring_view __fmt, wformat_args __args) { template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, - __format_string_t<_Args...> __fmt, + format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, + return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring -format(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_, +format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { + return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -748,18 +759,18 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __format_string_t<_Args...> __fmt, +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), _VSTD::make_format_args(__args...)); } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS template _OutIt, class... _Args> _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __wformat_string_t<_Args...> __fmt, +format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_, + return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), _VSTD::make_wformat_args(__args...)); } #endif @@ -775,15 +786,15 @@ _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_ template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)}); +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 template _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)}); +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 diff --git a/lib/libcxx/include/span b/lib/libcxx/include/span index 00793a210c..67d2ac241f 100644 --- a/lib/libcxx/include/span +++ b/lib/libcxx/include/span @@ -453,9 +453,10 @@ public: : __data{_VSTD::to_address(__first)}, __size{__count} {} template <__span_compatible_iterator _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_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)"); + } template _LIBCPP_INLINE_VISIBILITY diff --git a/lib/libcxx/include/version b/lib/libcxx/include/version index 1df51fa1cb..8ffb1747eb 100644 --- a/lib/libcxx/include/version +++ b/lib/libcxx/include/version @@ -331,8 +331,8 @@ __cpp_lib_void_t 201411L # define __cpp_lib_erase_if 202002L # undef __cpp_lib_execution // # define __cpp_lib_execution 201902L -# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) -// # define __cpp_lib_format 202106L +# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) +# define __cpp_lib_format 202106L # endif # define __cpp_lib_generic_unordered_lookup 201811L # define __cpp_lib_int_pow2 202002L @@ -351,7 +351,9 @@ __cpp_lib_void_t 201411L # define __cpp_lib_list_remove_return_type 201806L # define __cpp_lib_math_constants 201907L // # define __cpp_lib_polymorphic_allocator 201902L -// # define __cpp_lib_ranges 201811L +# if !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) +# define __cpp_lib_ranges 201811L +# endif # define __cpp_lib_remove_cvref 201711L # if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore) # define __cpp_lib_semaphore 201907L