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.

152 lines
4.1KB

  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/concepts.hpp>
  20. #include <range/v3/functional/pipeable.hpp>
  21. #include <range/v3/range/concepts.hpp>
  22. #include <range/v3/range/traits.hpp>
  23. #include <range/v3/utility/static_const.hpp>
  24. namespace ranges
  25. {
  26. /// \cond
  27. namespace detail
  28. {
  29. struct null_pipe
  30. {
  31. template<typename Rng>
  32. constexpr void operator()(Rng &&) const
  33. {}
  34. };
  35. struct dereference_fn
  36. {
  37. // clang-format off
  38. template<typename I>
  39. constexpr auto CPP_auto_fun(operator())(I &&i) (const)
  40. (
  41. return *(I &&) i
  42. )
  43. // clang-format on
  44. };
  45. } // namespace detail
  46. /// \endcond
  47. // clang-format off
  48. CPP_def
  49. (
  50. template(typename Rng)
  51. concept simple_view_,
  52. view_<Rng> &&
  53. range<Rng const> &&
  54. same_as<iterator_t<Rng>, iterator_t<Rng const>> &&
  55. same_as<sentinel_t<Rng>, sentinel_t<Rng const>>
  56. );
  57. // clang-format on
  58. template<typename Rng>
  59. constexpr bool simple_view()
  60. {
  61. return (bool)simple_view_<Rng>;
  62. }
  63. namespace views
  64. {
  65. /// \addtogroup group-views
  66. /// @{
  67. struct view_access
  68. {
  69. template<typename View>
  70. struct impl
  71. {
  72. // clang-format off
  73. template<typename... Ts, typename V = View>
  74. static constexpr auto CPP_auto_fun(bind)(Ts &&... ts)
  75. (
  76. return V::bind(static_cast<Ts &&>(ts)...)
  77. )
  78. // clang-format on
  79. };
  80. };
  81. struct make_view_fn
  82. {
  83. template<typename Fun>
  84. constexpr view<Fun> operator()(Fun fun) const
  85. {
  86. return view<Fun>{std::move(fun)};
  87. }
  88. };
  89. /// \ingroup group-views
  90. /// \sa make_view_fn
  91. RANGES_INLINE_VARIABLE(make_view_fn, make_view)
  92. template<typename View>
  93. struct view : pipeable_base
  94. {
  95. private:
  96. View view_;
  97. friend pipeable_access;
  98. // Piping requires range arguments or lvalue containers.
  99. template<typename Rng, typename Vw>
  100. static constexpr auto CPP_fun(pipe)(Rng && rng, Vw && v)( //
  101. requires viewable_range<Rng> && invocable<View &, Rng>)
  102. {
  103. return v.view_(static_cast<Rng &&>(rng));
  104. }
  105. public:
  106. view() = default;
  107. constexpr explicit view(View a) noexcept(
  108. std::is_nothrow_move_constructible<View>::value)
  109. : view_(std::move(a))
  110. {}
  111. // Calling directly requires a viewable_range.
  112. template<typename Rng, typename... Rest>
  113. constexpr auto operator()(Rng && rng, Rest &&... rest) const
  114. -> CPP_ret(invoke_result_t<View const &, Rng, Rest...>)( //
  115. requires viewable_range<Rng> && invocable<View const &, Rng, Rest...>)
  116. {
  117. return view_(static_cast<Rng &&>(rng), static_cast<Rest &&>(rest)...);
  118. }
  119. // Currying overload.
  120. // clang-format off
  121. template<typename... Ts, typename V = View>
  122. constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(const)
  123. (
  124. return make_view(
  125. view_access::impl<V>::bind(view_, static_cast<Ts &&>(ts)...))
  126. )
  127. // clang-format on
  128. };
  129. /// \endcond
  130. } // namespace views
  131. } // namespace ranges
  132. #endif