partition.h 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef _LIBCPP___ALGORITHM_PARTITION_H
  9. #define _LIBCPP___ALGORITHM_PARTITION_H
  10. #include <__algorithm/iterator_operations.h>
  11. #include <__config>
  12. #include <__iterator/iterator_traits.h>
  13. #include <__utility/move.h>
  14. #include <__utility/pair.h>
  15. #include <type_traits>
  16. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  17. # pragma GCC system_header
  18. #endif
  19. _LIBCPP_BEGIN_NAMESPACE_STD
  20. template <class _Predicate, class _AlgPolicy, class _ForwardIterator, class _Sentinel>
  21. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator>
  22. __partition_impl(_ForwardIterator __first, _Sentinel __last, _Predicate __pred, forward_iterator_tag)
  23. {
  24. while (true)
  25. {
  26. if (__first == __last)
  27. return std::make_pair(std::move(__first), std::move(__first));
  28. if (!__pred(*__first))
  29. break;
  30. ++__first;
  31. }
  32. _ForwardIterator __p = __first;
  33. while (++__p != __last)
  34. {
  35. if (__pred(*__p))
  36. {
  37. _IterOps<_AlgPolicy>::iter_swap(__first, __p);
  38. ++__first;
  39. }
  40. }
  41. return std::make_pair(std::move(__first), std::move(__p));
  42. }
  43. template <class _Predicate, class _AlgPolicy, class _BidirectionalIterator, class _Sentinel>
  44. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, _BidirectionalIterator>
  45. __partition_impl(_BidirectionalIterator __first, _Sentinel __sentinel, _Predicate __pred,
  46. bidirectional_iterator_tag)
  47. {
  48. _BidirectionalIterator __original_last = _IterOps<_AlgPolicy>::next(__first, __sentinel);
  49. _BidirectionalIterator __last = __original_last;
  50. while (true)
  51. {
  52. while (true)
  53. {
  54. if (__first == __last)
  55. return std::make_pair(std::move(__first), std::move(__original_last));
  56. if (!__pred(*__first))
  57. break;
  58. ++__first;
  59. }
  60. do
  61. {
  62. if (__first == --__last)
  63. return std::make_pair(std::move(__first), std::move(__original_last));
  64. } while (!__pred(*__last));
  65. _IterOps<_AlgPolicy>::iter_swap(__first, __last);
  66. ++__first;
  67. }
  68. }
  69. template <class _AlgPolicy, class _ForwardIterator, class _Sentinel, class _Predicate, class _IterCategory>
  70. inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
  71. pair<_ForwardIterator, _ForwardIterator> __partition(
  72. _ForwardIterator __first, _Sentinel __last, _Predicate&& __pred, _IterCategory __iter_category) {
  73. return std::__partition_impl<__remove_cvref_t<_Predicate>&, _AlgPolicy>(
  74. std::move(__first), std::move(__last), __pred, __iter_category);
  75. }
  76. template <class _ForwardIterator, class _Predicate>
  77. inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
  78. _ForwardIterator
  79. partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
  80. {
  81. using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category;
  82. auto __result = std::__partition<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred, _IterCategory());
  83. return __result.first;
  84. }
  85. _LIBCPP_END_NAMESPACE_STD
  86. #endif // _LIBCPP___ALGORITHM_PARTITION_H