trim.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Johel Guerrero 2019
  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_VIEW_TRIM_HPP
  14. #define RANGES_V3_VIEW_TRIM_HPP
  15. #include <utility>
  16. #include <concepts/concepts.hpp>
  17. #include <range/v3/algorithm/find_if_not.hpp>
  18. #include <range/v3/detail/config.hpp>
  19. #include <range/v3/functional/bind_back.hpp>
  20. #include <range/v3/functional/compose.hpp>
  21. #include <range/v3/functional/invoke.hpp>
  22. #include <range/v3/iterator/concepts.hpp>
  23. #include <range/v3/range/access.hpp>
  24. #include <range/v3/range/concepts.hpp>
  25. #include <range/v3/range/primitives.hpp>
  26. #include <range/v3/utility/optional.hpp>
  27. #include <range/v3/utility/semiregular_box.hpp>
  28. #include <range/v3/view/all.hpp>
  29. #include <range/v3/view/interface.hpp>
  30. #include <range/v3/view/view.hpp>
  31. #include <range/v3/detail/prologue.hpp>
  32. namespace ranges
  33. {
  34. /// \addtogroup group-views
  35. /// @{
  36. template<typename Rng, typename Pred>
  37. struct trim_view : view_interface<trim_view<Rng, Pred>>
  38. {
  39. private:
  40. Rng rng_;
  41. semiregular_box_t<Pred> pred_;
  42. detail::non_propagating_cache<iterator_t<Rng>> begin_;
  43. detail::non_propagating_cache<iterator_t<Rng>> end_;
  44. public:
  45. CPP_assert(bidirectional_range<Rng> && view_<Rng> && indirect_unary_predicate<
  46. Pred, iterator_t<Rng>> && common_range<Rng>);
  47. trim_view() = default;
  48. constexpr trim_view(Rng rng, Pred pred)
  49. : rng_(std::move(rng))
  50. , pred_(std::move(pred))
  51. {}
  52. iterator_t<Rng> begin()
  53. {
  54. if(!begin_)
  55. begin_ = find_if_not(rng_, std::ref(pred_));
  56. return *begin_;
  57. }
  58. iterator_t<Rng> end()
  59. {
  60. if(!end_)
  61. {
  62. const auto first = begin();
  63. auto last = ranges::end(rng_);
  64. while(last != first)
  65. if(!invoke(pred_, *--last))
  66. {
  67. ++last;
  68. break;
  69. }
  70. end_ = std::move(last);
  71. }
  72. return *end_;
  73. }
  74. Rng base() const
  75. {
  76. return rng_;
  77. }
  78. };
  79. template<typename Rng, typename Pred>
  80. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<trim_view<Rng, Pred>> = //
  81. enable_borrowed_range<Rng>;
  82. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  83. template<typename Rng, typename Pred>
  84. trim_view(Rng &&, Pred) //
  85. -> trim_view<views::all_t<Rng>, Pred>;
  86. #endif
  87. template<typename Rng, typename Pred>
  88. RANGES_INLINE_VAR constexpr bool disable_sized_range<trim_view<Rng, Pred>> = true;
  89. namespace views
  90. {
  91. struct trim_base_fn
  92. {
  93. template(typename Rng, typename Pred)(
  94. requires viewable_range<Rng> AND bidirectional_range<Rng> AND
  95. indirect_unary_predicate<Pred, iterator_t<Rng>> AND
  96. common_range<Rng>)
  97. constexpr trim_view<all_t<Rng>, Pred> //
  98. operator()(Rng && rng, Pred pred) const //
  99. {
  100. return {all(static_cast<Rng &&>(rng)), std::move(pred)};
  101. }
  102. template(typename Rng, typename Pred, typename Proj)(
  103. requires viewable_range<Rng> AND bidirectional_range<Rng> AND
  104. indirect_unary_predicate<composed<Pred, Proj>, iterator_t<Rng>> AND
  105. common_range<Rng>)
  106. constexpr trim_view<all_t<Rng>, composed<Pred, Proj>> //
  107. operator()(Rng && rng, Pred pred, Proj proj) const
  108. {
  109. return {all(static_cast<Rng &&>(rng)),
  110. compose(std::move(pred), std::move(proj))};
  111. }
  112. };
  113. struct trim_bind_fn
  114. {
  115. template<typename Pred>
  116. constexpr auto operator()(Pred pred) const // TODO: underconstrained
  117. {
  118. return make_view_closure(bind_back(trim_base_fn{}, std::move(pred)));
  119. }
  120. template(typename Pred, typename Proj)(
  121. requires (!range<Pred>)) // TODO: underconstrained
  122. constexpr auto operator()(Pred && pred, Proj proj) const
  123. {
  124. return make_view_closure(bind_back(
  125. trim_base_fn{}, static_cast<Pred &&>(pred), std::move(proj)));
  126. }
  127. };
  128. struct RANGES_EMPTY_BASES trim_fn
  129. : trim_base_fn, trim_bind_fn
  130. {
  131. using trim_base_fn::operator();
  132. using trim_bind_fn::operator();
  133. };
  134. /// \relates trim_fn
  135. /// \ingroup group-views
  136. RANGES_INLINE_VARIABLE(trim_fn, trim)
  137. } // namespace views
  138. /// @}
  139. } // namespace ranges
  140. #include <range/v3/detail/epilogue.hpp>
  141. #include <range/v3/detail/satisfy_boost_range.hpp>
  142. RANGES_SATISFY_BOOST_RANGE(::ranges::trim_view)
  143. #endif // RANGES_V3_VIEW_TRIM_HPP