You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 5 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-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. #ifndef RANGES_V3_ACTION_SLICE_HPP
  14. #define RANGES_V3_ACTION_SLICE_HPP
  15. #include <meta/meta.hpp>
  16. #include <range/v3/range_fwd.hpp>
  17. #include <range/v3/action/action.hpp>
  18. #include <range/v3/action/erase.hpp>
  19. #include <range/v3/functional/bind_back.hpp>
  20. #include <range/v3/iterator/concepts.hpp>
  21. #include <range/v3/iterator/operations.hpp>
  22. #include <range/v3/iterator/traits.hpp>
  23. #include <range/v3/utility/static_const.hpp>
  24. #include <range/v3/view/interface.hpp>
  25. namespace ranges
  26. {
  27. /// \addtogroup group-actions
  28. /// @{
  29. namespace actions
  30. {
  31. struct slice_fn
  32. {
  33. private:
  34. friend action_access;
  35. template<typename D>
  36. using diff_t = range_difference_t<D>;
  37. // Overloads for the pipe syntax: rng | actions::slice(from, to)
  38. template<typename D>
  39. static auto CPP_fun(bind)(slice_fn slice, D from, D to)( //
  40. requires integral<D>)
  41. {
  42. return bind_back(slice, from, to);
  43. }
  44. template<typename D>
  45. static auto CPP_fun(bind)(slice_fn slice, D from, detail::from_end_<D> to)( //
  46. requires integral<D>)
  47. {
  48. return bind_back(slice, from, to);
  49. }
  50. template<typename D>
  51. static auto CPP_fun(bind)(slice_fn slice, detail::from_end_<D> from,
  52. detail::from_end_<D> to)( //
  53. requires integral<D>)
  54. {
  55. return bind_back(slice, from, to);
  56. }
  57. template<typename D>
  58. static auto CPP_fun(bind)(slice_fn slice, D from, end_fn const & to)( //
  59. requires integral<D>)
  60. {
  61. return bind_back(slice, from, to);
  62. }
  63. template<typename D>
  64. static auto CPP_fun(bind)(slice_fn slice, detail::from_end_<D> from,
  65. end_fn const & to)( //
  66. requires integral<D>)
  67. {
  68. return bind_back(slice, from, to);
  69. }
  70. public:
  71. template<typename Rng, typename I = iterator_t<Rng>>
  72. auto operator()(Rng && rng, diff_t<Rng> from, diff_t<Rng> to) const
  73. -> CPP_ret(Rng)( //
  74. requires forward_range<Rng> && erasable_range<Rng &, I, I>)
  75. {
  76. RANGES_EXPECT(0 <= from && 0 <= to && from <= to);
  77. RANGES_EXPECT(!sized_range<Rng> || to <= distance(rng));
  78. ranges::actions::erase(rng, begin(rng), next(begin(rng), from));
  79. ranges::actions::erase(rng, next(begin(rng), to - from), end(rng));
  80. return static_cast<Rng &&>(rng);
  81. }
  82. template<typename Rng, typename I = iterator_t<Rng>>
  83. auto operator()(Rng && rng, diff_t<Rng> from,
  84. detail::from_end_<diff_t<Rng>> to) const -> CPP_ret(Rng)( //
  85. requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>)
  86. {
  87. RANGES_EXPECT(0 <= from && to.dist_ <= 0);
  88. RANGES_EXPECT(!sized_range<Rng> || from - to.dist_ <= distance(rng));
  89. ranges::actions::erase(rng, begin(rng), next(begin(rng), from));
  90. if(to.dist_ != 0)
  91. {
  92. auto const last = next(begin(rng), end(rng));
  93. ranges::actions::erase(rng, prev(last, -to.dist_), last);
  94. }
  95. return static_cast<Rng &&>(rng);
  96. }
  97. template<typename Rng, typename I = iterator_t<Rng>>
  98. auto operator()(Rng && rng, detail::from_end_<diff_t<Rng>> from,
  99. detail::from_end_<diff_t<Rng>> to) const -> CPP_ret(Rng)( //
  100. requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>)
  101. {
  102. RANGES_EXPECT(from.dist_ <= 0 && to.dist_ <= 0 && from.dist_ <= to.dist_);
  103. RANGES_EXPECT(!sized_range<Rng> || 0 <= distance(rng) + from.dist_);
  104. auto last = next(begin(rng), end(rng));
  105. ranges::actions::erase(rng, prev(last, -to.dist_), last);
  106. last = next(begin(rng), end(rng));
  107. ranges::actions::erase(
  108. rng, begin(rng), prev(last, to.dist_ - from.dist_));
  109. return static_cast<Rng &&>(rng);
  110. }
  111. template<typename Rng, typename I = iterator_t<Rng>>
  112. auto operator()(Rng && rng, diff_t<Rng> from, end_fn const &) const
  113. -> CPP_ret(Rng)( //
  114. requires forward_range<Rng> && erasable_range<Rng &, I, I>)
  115. {
  116. RANGES_EXPECT(0 <= from);
  117. RANGES_EXPECT(!sized_range<Rng> || from <= distance(rng));
  118. ranges::actions::erase(rng, begin(rng), next(begin(rng), from));
  119. return static_cast<Rng &&>(rng);
  120. }
  121. template<typename Rng, typename I = iterator_t<Rng>>
  122. auto operator()(Rng && rng, detail::from_end_<diff_t<Rng>> from,
  123. end_fn const &) const -> CPP_ret(Rng)( //
  124. requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>)
  125. {
  126. RANGES_EXPECT(from.dist_ <= 0);
  127. RANGES_EXPECT(!sized_range<Rng> || 0 <= distance(rng) + from.dist_);
  128. auto const last = next(begin(rng), end(rng));
  129. ranges::actions::erase(rng, begin(rng), prev(last, -from.dist_));
  130. return static_cast<Rng &&>(rng);
  131. }
  132. };
  133. /// \ingroup group-actions
  134. /// \relates slice_fn
  135. /// \sa action
  136. RANGES_INLINE_VARIABLE(action<slice_fn>, slice)
  137. } // namespace actions
  138. /// @}
  139. } // namespace ranges
  140. #endif