view.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. #ifndef RANGES_V3_VIEW_VIEW_HPP
  14. #define RANGES_V3_VIEW_VIEW_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/compose.hpp>
  20. #include <range/v3/functional/concepts.hpp>
  21. #include <range/v3/functional/pipeable.hpp>
  22. #include <range/v3/functional/reference_wrapper.hpp>
  23. #include <range/v3/range/concepts.hpp>
  24. #include <range/v3/range/traits.hpp>
  25. #include <range/v3/utility/static_const.hpp>
  26. #include <range/v3/detail/prologue.hpp>
  27. namespace ranges
  28. {
  29. /// \addtogroup group-views
  30. /// @{
  31. /// \cond
  32. namespace detail
  33. {
  34. struct dereference_fn
  35. {
  36. // clang-format off
  37. template<typename I>
  38. constexpr auto CPP_auto_fun(operator())(I &&i) (const)
  39. (
  40. return *(I &&) i
  41. )
  42. // clang-format on
  43. };
  44. struct view_closure_base_
  45. {};
  46. } // namespace detail
  47. /// \endcond
  48. // clang-format off
  49. /// \concept simple_view_impl_
  50. /// \brief The \c simple_view_impl_ concept
  51. template(typename Rng)(
  52. concept (simple_view_impl_)(Rng),
  53. same_as<iterator_t<Rng>, iterator_t<Rng const>> AND
  54. same_as<sentinel_t<Rng>, sentinel_t<Rng const>>);
  55. /// \concept simple_view_
  56. /// \brief The \c simple_view_ concept
  57. template<typename Rng>
  58. CPP_concept simple_view_ =
  59. view_<Rng> &&
  60. range<Rng const> &&
  61. CPP_concept_ref(ranges::simple_view_impl_, Rng);
  62. /// \concept invocable_view_closure_
  63. /// \brief The \c invocable_view_closure_ concept
  64. template(typename ViewFn, typename Rng)(
  65. concept (invocable_view_closure_)(ViewFn, Rng),
  66. !derived_from<invoke_result_t<ViewFn, Rng>, detail::view_closure_base_>);
  67. /// \concept invocable_view_closure
  68. /// \brief The \c invocable_view_closure concept
  69. template<typename ViewFn, typename Rng>
  70. CPP_concept invocable_view_closure =
  71. invocable<ViewFn, Rng> &&
  72. CPP_concept_ref(ranges::invocable_view_closure_, ViewFn, Rng);
  73. // clang-format on
  74. template<typename Rng>
  75. constexpr bool simple_view() noexcept
  76. {
  77. return (bool)simple_view_<Rng>;
  78. }
  79. struct make_view_closure_fn
  80. {
  81. template<typename Fun>
  82. constexpr views::view_closure<Fun> operator()(Fun fun) const
  83. {
  84. return views::view_closure<Fun>{static_cast<Fun &&>(fun)};
  85. }
  86. };
  87. /// \ingroup group-views
  88. /// \sa make_view_closure_fn
  89. RANGES_INLINE_VARIABLE(make_view_closure_fn, make_view_closure)
  90. namespace views
  91. {
  92. struct RANGES_STRUCT_WITH_ADL_BARRIER(view_closure_base)
  93. : detail::view_closure_base_
  94. {
  95. // Piping requires viewable_ranges. Pipeing a value into a closure
  96. // should not yield another closure.
  97. template(typename Rng, typename ViewFn)(
  98. requires viewable_range<Rng> AND
  99. invocable_view_closure<ViewFn, Rng>)
  100. friend constexpr auto operator|(Rng && rng, view_closure<ViewFn> vw)
  101. {
  102. return static_cast<ViewFn &&>(vw)(static_cast<Rng &&>(rng));
  103. }
  104. #ifndef RANGES_WORKAROUND_CLANG_43400
  105. // This overload is deleted because when piping a range into an
  106. // view, it must be moved in.
  107. template<typename Rng, typename ViewFn> // **************************
  108. friend constexpr auto // **************************
  109. operator|(Rng &&, view_closure<ViewFn> const &) // ******* READ THIS ********
  110. // **** IF YOUR COMPILE *****
  111. -> CPP_broken_friend_ret(Rng)( // ****** BREAKS HERE *******
  112. requires range<Rng> && // **************************
  113. (!viewable_range<Rng>)) = delete; // **************************
  114. // **************************************************************************
  115. // * When piping a range into an adaptor, the range must satisfy the *
  116. // * "viewable_range" concept. A range is viewable when either or both *
  117. // * of these things are true: *
  118. // * - The range is an lvalue (not a temporary object), OR *
  119. // * - The range is a view (not a container). *
  120. // **************************************************************************
  121. #endif
  122. template<typename ViewFn, typename Pipeable>
  123. friend constexpr auto operator|(view_closure<ViewFn> vw, Pipeable pipe)
  124. -> CPP_broken_friend_ret(view_closure<composed<Pipeable, ViewFn>>)(
  125. requires (is_pipeable_v<Pipeable>))
  126. {
  127. return make_view_closure(
  128. compose(static_cast<Pipeable &&>(pipe), static_cast<ViewFn &&>(vw)));
  129. }
  130. };
  131. #ifdef RANGES_WORKAROUND_CLANG_43400
  132. namespace RANGES_ADL_BARRIER_FOR(view_closure_base)
  133. {
  134. // This overload is deleted because when piping a range into an
  135. // view, it must be moved in.
  136. template(typename Rng, typename ViewFn)( // ************************
  137. requires range<Rng> AND (!viewable_range<Rng>))// ************************
  138. constexpr Rng // ************************
  139. operator|(Rng &&, view_closure<ViewFn> const &) // ****** READ THIS *******
  140. = delete; // *** IF YOUR COMPILE ****
  141. // ***** BREAKS HERE ******
  142. // ************************
  143. // ************************
  144. // ***************************************************************************
  145. // * When piping a range into an adaptor, the range must satisfy the *
  146. // * "viewable_range" concept. A range is viewable when either or both *
  147. // * of these things are true: *
  148. // * - The range is an lvalue (not a temporary object), OR *
  149. // * - The range is a view (not a container). *
  150. // ***************************************************************************
  151. } // namespace )
  152. #endif // RANGES_WORKAROUND_CLANG_43400
  153. template<typename ViewFn>
  154. struct RANGES_EMPTY_BASES view_closure
  155. : view_closure_base
  156. , ViewFn
  157. {
  158. view_closure() = default;
  159. constexpr explicit view_closure(ViewFn fn)
  160. : ViewFn(static_cast<ViewFn &&>(fn))
  161. {}
  162. };
  163. /// \cond
  164. /// DEPRECATED STUFF
  165. struct view_access_
  166. {
  167. template<typename ViewFn>
  168. struct impl
  169. {
  170. // clang-format off
  171. template<typename... Ts, typename V = ViewFn>
  172. static constexpr auto CPP_auto_fun(bind)(Ts &&... ts)
  173. (
  174. return V::bind(static_cast<Ts &&>(ts)...)
  175. )
  176. // clang-format on
  177. };
  178. };
  179. using view_access RANGES_DEPRECATED(
  180. "view_access and views::view<> are deprecated. Please "
  181. "replace view<> with view_closure<> and discontinue use of view_access.") =
  182. view_access_;
  183. template<typename>
  184. struct old_view_;
  185. struct make_view_fn_
  186. {
  187. template<typename Fun>
  188. constexpr old_view_<Fun> operator()(Fun fun) const
  189. {
  190. return old_view_<Fun>{static_cast<Fun &&>(fun)};
  191. }
  192. };
  193. using make_view_fn RANGES_DEPRECATED(
  194. "make_view_fn is deprecated. Please use "
  195. "make_view_closure instead.") = make_view_fn_;
  196. namespace
  197. {
  198. RANGES_DEPRECATED(
  199. "make_view and views::view<> has been deprecated. Please switch to "
  200. "make_view_closure and views::view_closure.")
  201. RANGES_INLINE_VAR constexpr auto & make_view =
  202. static_const<make_view_fn_>::value;
  203. } // namespace
  204. template<typename ViewFn>
  205. struct old_view_ : pipeable_base
  206. {
  207. private:
  208. ViewFn vw_;
  209. friend pipeable_access;
  210. // Piping requires range arguments or lvalue containers.
  211. template(typename Rng, typename Vw)(
  212. requires viewable_range<Rng> AND invocable<ViewFn &, Rng>)
  213. static constexpr auto pipe(Rng && rng, Vw && v)
  214. {
  215. return v.vw_(static_cast<Rng &&>(rng));
  216. }
  217. public:
  218. old_view_() = default;
  219. constexpr explicit old_view_(ViewFn a) noexcept(
  220. std::is_nothrow_move_constructible<ViewFn>::value)
  221. : vw_(std::move(a))
  222. {}
  223. // Calling directly requires a viewable_range.
  224. template(typename Rng, typename... Rest)(
  225. requires viewable_range<Rng> AND invocable<ViewFn const &, Rng, Rest...>)
  226. constexpr invoke_result_t<ViewFn const &, Rng, Rest...> //
  227. operator()(Rng && rng, Rest &&... rest) const
  228. {
  229. return vw_(static_cast<Rng &&>(rng), static_cast<Rest &&>(rest)...);
  230. }
  231. // Currying overload.
  232. // clang-format off
  233. template<typename... Ts, typename V = ViewFn>
  234. constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(const)
  235. (
  236. return make_view_fn_{}(
  237. view_access_::impl<V>::bind(vw_, static_cast<Ts &&>(ts)...))
  238. )
  239. // clang-format on
  240. };
  241. template<typename ViewFn>
  242. using view RANGES_DEPRECATED(
  243. "The views::view<> template is deprecated. Please switch to view_closure") =
  244. old_view_<ViewFn>;
  245. /// \endcond
  246. } // namespace views
  247. template<typename ViewFn>
  248. RANGES_INLINE_VAR constexpr bool is_pipeable_v<views::view_closure<ViewFn>> = true;
  249. /// @}
  250. } // namespace ranges
  251. #include <range/v3/detail/epilogue.hpp>
  252. #endif