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.

194 lines
6.6KB

  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_VIEW_TAKE_WHILE_HPP
  14. #define RANGES_V3_VIEW_TAKE_WHILE_HPP
  15. #include <type_traits>
  16. #include <utility>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/functional/bind_back.hpp>
  20. #include <range/v3/functional/compose.hpp>
  21. #include <range/v3/functional/indirect.hpp>
  22. #include <range/v3/functional/invoke.hpp>
  23. #include <range/v3/iterator/concepts.hpp>
  24. #include <range/v3/range/concepts.hpp>
  25. #include <range/v3/utility/semiregular_box.hpp>
  26. #include <range/v3/utility/static_const.hpp>
  27. #include <range/v3/view/adaptor.hpp>
  28. #include <range/v3/view/view.hpp>
  29. namespace ranges
  30. {
  31. /// \addtogroup group-views
  32. /// @{
  33. template<typename Rng, typename Pred>
  34. struct iter_take_while_view
  35. : view_adaptor<iter_take_while_view<Rng, Pred>, Rng,
  36. is_finite<Rng>::value ? finite : unknown>
  37. {
  38. private:
  39. friend range_access;
  40. RANGES_NO_UNIQUE_ADDRESS semiregular_box_t<Pred> pred_;
  41. template<bool IsConst>
  42. struct sentinel_adaptor : adaptor_base
  43. {
  44. private:
  45. friend struct sentinel_adaptor<!IsConst>;
  46. using CRng = meta::const_if_c<IsConst, Rng>;
  47. semiregular_box_ref_or_val_t<Pred, IsConst> pred_;
  48. public:
  49. sentinel_adaptor() = default;
  50. sentinel_adaptor(semiregular_box_ref_or_val_t<Pred, IsConst> pred)
  51. : pred_(std::move(pred))
  52. {}
  53. CPP_template(bool Other)( //
  54. requires IsConst && (!Other))
  55. sentinel_adaptor(sentinel_adaptor<Other> that)
  56. : pred_(std::move(that.pred_))
  57. {}
  58. bool empty(iterator_t<CRng> const & it, sentinel_t<CRng> const & last) const
  59. {
  60. return it == last || !invoke(pred_, it);
  61. }
  62. };
  63. sentinel_adaptor<false> end_adaptor()
  64. {
  65. return {pred_};
  66. }
  67. template<bool Const = true>
  68. auto end_adaptor() const -> CPP_ret(sentinel_adaptor<Const>)( //
  69. requires Const && range<meta::const_if_c<Const, Rng>> &&
  70. invocable<Pred const &, iterator_t<meta::const_if_c<Const, Rng>>>)
  71. {
  72. return {pred_};
  73. }
  74. public:
  75. iter_take_while_view() = default;
  76. constexpr iter_take_while_view(Rng rng, Pred pred)
  77. : iter_take_while_view::view_adaptor{std::move(rng)}
  78. , pred_(std::move(pred))
  79. {}
  80. };
  81. template<typename Rng, typename Pred>
  82. struct take_while_view : iter_take_while_view<Rng, indirected<Pred>>
  83. {
  84. take_while_view() = default;
  85. constexpr take_while_view(Rng rng, Pred pred)
  86. : iter_take_while_view<Rng, indirected<Pred>>{std::move(rng),
  87. indirect(std::move(pred))}
  88. {}
  89. };
  90. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  91. CPP_template(typename Rng, typename Fun)(requires copy_constructible<Fun>)
  92. take_while_view(Rng &&, Fun)
  93. ->take_while_view<views::all_t<Rng>, Fun>;
  94. #endif
  95. namespace views
  96. {
  97. struct iter_take_while_fn
  98. {
  99. private:
  100. friend view_access;
  101. template<typename Pred>
  102. static constexpr auto bind(iter_take_while_fn iter_take_while, Pred pred)
  103. {
  104. return make_pipeable(bind_back(iter_take_while, std::move(pred)));
  105. }
  106. public:
  107. template<typename Rng, typename Pred>
  108. constexpr auto operator()(Rng && rng, Pred pred) const
  109. -> CPP_ret(iter_take_while_view<all_t<Rng>, Pred>)( //
  110. requires viewable_range<Rng> && input_range<Rng> &&
  111. predicate<Pred &, iterator_t<Rng>> && copy_constructible<Pred>)
  112. {
  113. return {all(static_cast<Rng &&>(rng)), std::move(pred)};
  114. }
  115. };
  116. struct take_while_fn
  117. {
  118. private:
  119. friend view_access;
  120. template<typename Pred>
  121. static constexpr auto bind(take_while_fn take_while, Pred pred)
  122. {
  123. return make_pipeable(bind_back(take_while, std::move(pred)));
  124. }
  125. template<typename Pred, typename Proj>
  126. static constexpr auto bind(take_while_fn take_while, Pred pred, Proj proj)
  127. {
  128. return make_pipeable(
  129. bind_back(take_while, std::move(pred), std::move(proj)));
  130. }
  131. public:
  132. template<typename Rng, typename Pred>
  133. constexpr auto operator()(Rng && rng, Pred pred) const
  134. -> CPP_ret(take_while_view<all_t<Rng>, Pred>)( //
  135. requires viewable_range<Rng> && input_range<Rng> &&
  136. indirect_unary_predicate<Pred &, iterator_t<Rng>>)
  137. {
  138. return {all(static_cast<Rng &&>(rng)), std::move(pred)};
  139. }
  140. template<typename Rng, typename Pred, typename Proj>
  141. constexpr auto operator()(Rng && rng, Pred pred, Proj proj) const
  142. -> CPP_ret(take_while_view<all_t<Rng>, composed<Pred, Proj>>)( //
  143. requires viewable_range<Rng> && input_range<Rng> &&
  144. indirect_unary_predicate<composed<Pred, Proj> &, iterator_t<Rng>>)
  145. {
  146. return {all(static_cast<Rng &&>(rng)),
  147. compose(std::move(pred), std::move(proj))};
  148. }
  149. };
  150. /// \relates iter_take_while_fn
  151. /// \ingroup group-views
  152. RANGES_INLINE_VARIABLE(view<iter_take_while_fn>, iter_take_while)
  153. /// \relates take_while_fn
  154. /// \ingroup group-views
  155. RANGES_INLINE_VARIABLE(view<take_while_fn>, take_while)
  156. } // namespace views
  157. namespace cpp20
  158. {
  159. namespace views
  160. {
  161. using ranges::views::take_while;
  162. }
  163. CPP_template(typename Rng, typename Pred)( //
  164. requires viewable_range<Rng> && input_range<Rng> &&
  165. predicate<Pred &, iterator_t<Rng>> && copy_constructible<Pred>) //
  166. using take_while_view = ranges::take_while_view<Rng, Pred>;
  167. } // namespace cpp20
  168. /// @}
  169. } // namespace ranges
  170. #include <range/v3/detail/satisfy_boost_range.hpp>
  171. RANGES_SATISFY_BOOST_RANGE(::ranges::iter_take_while_view)
  172. RANGES_SATISFY_BOOST_RANGE(::ranges::take_while_view)
  173. #endif