shared.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Filip Matzner 2017
  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_EXPERIMENTAL_VIEW_SHARED_HPP
  14. #define RANGES_V3_EXPERIMENTAL_VIEW_SHARED_HPP
  15. #include <memory>
  16. #include <type_traits>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/functional/compose.hpp>
  19. #include <range/v3/range/access.hpp>
  20. #include <range/v3/range/concepts.hpp>
  21. #include <range/v3/range/primitives.hpp>
  22. #include <range/v3/view/all.hpp>
  23. #include <range/v3/detail/prologue.hpp>
  24. namespace ranges
  25. {
  26. /// \addtogroup group-views
  27. /// @{
  28. namespace experimental
  29. {
  30. template<typename Rng>
  31. struct shared_view
  32. : view_interface<shared_view<Rng>, range_cardinality<Rng>::value>
  33. {
  34. private:
  35. // shared storage
  36. std::shared_ptr<Rng> rng_ptr_;
  37. public:
  38. shared_view() = default;
  39. // construct from a range rvalue
  40. explicit shared_view(Rng rng)
  41. : rng_ptr_{std::make_shared<Rng>(std::move(rng))}
  42. {}
  43. // use the stored range's begin and end
  44. iterator_t<Rng> begin() const
  45. {
  46. return ranges::begin(*rng_ptr_);
  47. }
  48. sentinel_t<Rng> end() const
  49. {
  50. return ranges::end(*rng_ptr_);
  51. }
  52. CPP_auto_member
  53. auto CPP_fun(size)()(const
  54. requires sized_range<Rng>)
  55. {
  56. return ranges::size(*rng_ptr_);
  57. }
  58. };
  59. template<typename SharedFn>
  60. struct shared_closure;
  61. struct RANGES_STRUCT_WITH_ADL_BARRIER(shared_closure_base)
  62. {
  63. // Piping requires viewable_ranges.
  64. template(typename Rng, typename SharedFn)(
  65. requires range<Rng> AND (!viewable_range<Rng>) AND
  66. constructible_from<detail::decay_t<Rng>, Rng>)
  67. friend constexpr auto operator|(Rng && rng, shared_closure<SharedFn> vw)
  68. {
  69. return static_cast<SharedFn &&>(vw)(static_cast<Rng &&>(rng));
  70. }
  71. template<typename SharedFn, typename Pipeable>
  72. friend constexpr auto operator|(shared_closure<SharedFn> sh, Pipeable pipe)
  73. -> CPP_broken_friend_ret(shared_closure<composed<Pipeable, SharedFn>>)(
  74. requires (is_pipeable_v<Pipeable>))
  75. {
  76. return shared_closure<composed<Pipeable, SharedFn>>{compose(
  77. static_cast<Pipeable &&>(pipe), static_cast<SharedFn &&>(sh))};
  78. }
  79. };
  80. template<typename SharedFn>
  81. struct shared_closure
  82. : shared_closure_base
  83. , SharedFn
  84. {
  85. shared_closure() = default;
  86. constexpr explicit shared_closure(SharedFn fn)
  87. : SharedFn(static_cast<SharedFn &&>(fn))
  88. {}
  89. };
  90. namespace views
  91. {
  92. struct shared_fn
  93. {
  94. template(typename Rng)(
  95. requires range<Rng> AND (!viewable_range<Rng>)AND
  96. constructible_from<detail::decay_t<Rng>, Rng>)
  97. shared_view<detail::decay_t<Rng>> operator()(Rng && rng) const
  98. {
  99. return shared_view<detail::decay_t<Rng>>{static_cast<Rng &&>(rng)};
  100. }
  101. };
  102. /// \relates shared_fn
  103. /// \ingroup group-views
  104. RANGES_INLINE_VARIABLE(shared_closure<shared_fn>, shared)
  105. } // namespace views
  106. } // namespace experimental
  107. template<typename SharedFn>
  108. RANGES_INLINE_VAR constexpr bool
  109. is_pipeable_v<experimental::shared_closure<SharedFn>> = true;
  110. /// @}
  111. } // namespace ranges
  112. #include <range/v3/detail/epilogue.hpp>
  113. #endif