partition.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2014-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. //===-------------------------- algorithm ---------------------------------===//
  14. //
  15. // The LLVM Compiler Infrastructure
  16. //
  17. // This file is dual licensed under the MIT and the University of Illinois Open
  18. // Source Licenses. See LICENSE.TXT for details.
  19. //
  20. //===----------------------------------------------------------------------===//
  21. #ifndef RANGES_V3_ALGORITHM_PARTITION_HPP
  22. #define RANGES_V3_ALGORITHM_PARTITION_HPP
  23. #include <meta/meta.hpp>
  24. #include <range/v3/range_fwd.hpp>
  25. #include <range/v3/functional/identity.hpp>
  26. #include <range/v3/functional/invoke.hpp>
  27. #include <range/v3/iterator/concepts.hpp>
  28. #include <range/v3/iterator/operations.hpp>
  29. #include <range/v3/iterator/traits.hpp>
  30. #include <range/v3/range/access.hpp>
  31. #include <range/v3/range/concepts.hpp>
  32. #include <range/v3/range/dangling.hpp>
  33. #include <range/v3/range/traits.hpp>
  34. #include <range/v3/utility/static_const.hpp>
  35. #include <range/v3/utility/swap.hpp>
  36. #include <range/v3/detail/prologue.hpp>
  37. namespace ranges
  38. {
  39. /// \addtogroup group-algorithms
  40. /// @{
  41. /// \cond
  42. namespace detail
  43. {
  44. template<typename I, typename S, typename C, typename P>
  45. constexpr I partition_impl(I first, S last, C pred, P proj, std::forward_iterator_tag)
  46. {
  47. while(true)
  48. {
  49. if(first == last)
  50. return first;
  51. if(!invoke(pred, invoke(proj, *first)))
  52. break;
  53. ++first;
  54. }
  55. for(I p = first; ++p != last;)
  56. {
  57. if(invoke(pred, invoke(proj, *p)))
  58. {
  59. ranges::iter_swap(first, p);
  60. ++first;
  61. }
  62. }
  63. return first;
  64. }
  65. template<typename I, typename S, typename C, typename P>
  66. constexpr I partition_impl(I first, S end_, C pred, P proj, std::bidirectional_iterator_tag)
  67. {
  68. I last = ranges::next(first, end_);
  69. while(true)
  70. {
  71. while(true)
  72. {
  73. if(first == last)
  74. return first;
  75. if(!invoke(pred, invoke(proj, *first)))
  76. break;
  77. ++first;
  78. }
  79. do
  80. {
  81. if(first == --last)
  82. return first;
  83. } while(!invoke(pred, invoke(proj, *last)));
  84. ranges::iter_swap(first, last);
  85. ++first;
  86. }
  87. }
  88. } // namespace detail
  89. /// \endcond
  90. RANGES_FUNC_BEGIN(partition)
  91. /// \brief function template \c partition
  92. template(typename I, typename S, typename C, typename P = identity)(
  93. requires permutable<I> AND sentinel_for<S, I> AND
  94. indirect_unary_predicate<C, projected<I, P>>)
  95. constexpr I RANGES_FUNC(partition)(I first, S last, C pred, P proj = P{})
  96. {
  97. return detail::partition_impl(std::move(first),
  98. std::move(last),
  99. std::move(pred),
  100. std::move(proj),
  101. iterator_tag_of<I>());
  102. }
  103. /// \overload
  104. template(typename Rng, typename C, typename P = identity)(
  105. requires forward_range<Rng> AND permutable<iterator_t<Rng>> AND
  106. indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>)
  107. constexpr borrowed_iterator_t<Rng> RANGES_FUNC(partition)(Rng && rng, C pred, P proj = P{})
  108. {
  109. return detail::partition_impl(begin(rng),
  110. end(rng),
  111. std::move(pred),
  112. std::move(proj),
  113. iterator_tag_of<iterator_t<Rng>>());
  114. }
  115. RANGES_FUNC_END(partition)
  116. namespace cpp20
  117. {
  118. using ranges::partition;
  119. }
  120. /// @}
  121. } // namespace ranges
  122. #include <range/v3/detail/epilogue.hpp>
  123. #endif