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.

220 lines
6.7KB

  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_COMMON_HPP
  14. #define RANGES_V3_VIEW_COMMON_HPP
  15. #include <type_traits>
  16. #include <range/v3/range_fwd.hpp>
  17. #include <range/v3/iterator/common_iterator.hpp>
  18. #include <range/v3/iterator/concepts.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/range/traits.hpp>
  23. #include <range/v3/utility/static_const.hpp>
  24. #include <range/v3/view/all.hpp>
  25. #include <range/v3/view/interface.hpp>
  26. #include <range/v3/view/view.hpp>
  27. namespace ranges
  28. {
  29. /// \addtogroup group-views
  30. /// @{
  31. namespace detail
  32. {
  33. /// \cond
  34. // clang-format off
  35. CPP_def
  36. (
  37. template(typename R)
  38. concept random_access_and_sized_range,
  39. random_access_range<R> && sized_range<R>
  40. );
  41. // clang-format on
  42. template<typename R>
  43. using common_view_iterator_t =
  44. meta::if_c<random_access_and_sized_range<R>, iterator_t<R>,
  45. common_iterator_t<iterator_t<R>, sentinel_t<R>>>;
  46. template<typename Rng>
  47. struct is_common_range : meta::bool_<common_range<Rng>>
  48. {};
  49. /// \endcond
  50. } // namespace detail
  51. template<typename Rng, bool = detail::is_common_range<Rng>::value>
  52. struct common_view : view_interface<common_view<Rng>, range_cardinality<Rng>::value>
  53. {
  54. private:
  55. CPP_assert(view_<Rng>);
  56. CPP_assert(!(common_range<Rng> && view_<Rng>));
  57. Rng rng_;
  58. sentinel_t<Rng> end_(std::false_type)
  59. {
  60. return ranges::end(rng_);
  61. }
  62. iterator_t<Rng> end_(std::true_type)
  63. {
  64. return ranges::begin(rng_) + ranges::distance(rng_);
  65. }
  66. template<bool Const = true>
  67. auto end_(std::false_type) const
  68. -> CPP_ret(sentinel_t<meta::const_if_c<Const, Rng>>)( //
  69. requires Const && range<meta::const_if_c<Const, Rng>>)
  70. {
  71. return ranges::end(rng_);
  72. }
  73. template<bool Const = true>
  74. auto end_(std::true_type) const
  75. -> CPP_ret(iterator_t<meta::const_if_c<Const, Rng>>)( //
  76. requires Const && range<meta::const_if_c<Const, Rng>>)
  77. {
  78. return ranges::begin(rng_) + ranges::distance(rng_);
  79. }
  80. public:
  81. common_view() = default;
  82. explicit common_view(Rng rng)
  83. : rng_(detail::move(rng))
  84. {}
  85. Rng base() const
  86. {
  87. return rng_;
  88. }
  89. detail::common_view_iterator_t<Rng> begin()
  90. {
  91. return detail::common_view_iterator_t<Rng>{ranges::begin(rng_)};
  92. }
  93. detail::common_view_iterator_t<Rng> end()
  94. {
  95. return detail::common_view_iterator_t<Rng>{
  96. end_(meta::bool_<detail::random_access_and_sized_range<Rng>>{})};
  97. }
  98. CPP_member
  99. auto CPP_fun(size)()(requires sized_range<Rng>)
  100. {
  101. return ranges::size(rng_);
  102. }
  103. template<bool Const = true>
  104. auto begin() const
  105. -> CPP_ret(detail::common_view_iterator_t<meta::const_if_c<Const, Rng>>)( //
  106. requires range<meta::const_if_c<Const, Rng>>)
  107. {
  108. return detail::common_view_iterator_t<meta::const_if_c<Const, Rng>>{
  109. ranges::begin(rng_)};
  110. }
  111. template<bool Const = true>
  112. auto end() const
  113. -> CPP_ret(detail::common_view_iterator_t<meta::const_if_c<Const, Rng>>)( //
  114. requires range<meta::const_if_c<Const, Rng>>)
  115. {
  116. return detail::common_view_iterator_t<meta::const_if_c<Const, Rng>>{
  117. end_(meta::bool_<detail::random_access_and_sized_range<
  118. meta::const_if_c<Const, Rng>>>{})};
  119. }
  120. CPP_member
  121. auto CPP_fun(size)()(const requires sized_range<Rng const>)
  122. {
  123. return ranges::size(rng_);
  124. }
  125. };
  126. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  127. CPP_template(typename Rng)(requires !common_range<Rng>) common_view(Rng &&)
  128. ->common_view<views::all_t<Rng>>;
  129. #endif
  130. template<typename Rng>
  131. struct common_view<Rng, true> : identity_adaptor<Rng>
  132. {
  133. CPP_assert(common_range<Rng>);
  134. using identity_adaptor<Rng>::identity_adaptor;
  135. };
  136. namespace views
  137. {
  138. struct cpp20_common_fn
  139. {
  140. template<typename Rng>
  141. auto operator()(Rng && rng) const -> CPP_ret(common_view<all_t<Rng>>)( //
  142. requires viewable_range<Rng> && (!common_range<Rng>))
  143. {
  144. return common_view<all_t<Rng>>{all(static_cast<Rng &&>(rng))};
  145. }
  146. };
  147. struct common_fn
  148. {
  149. template<typename Rng>
  150. auto operator()(Rng && rng) const -> CPP_ret(common_view<all_t<Rng>>)( //
  151. requires viewable_range<Rng>)
  152. {
  153. return common_view<all_t<Rng>>{all(static_cast<Rng &&>(rng))};
  154. }
  155. };
  156. /// \relates common_fn
  157. /// \ingroup group-views
  158. RANGES_INLINE_VARIABLE(view<common_fn>, common)
  159. } // namespace views
  160. /// @}
  161. /// \cond
  162. template<typename Rng>
  163. using bounded_view RANGES_DEPRECATED(
  164. "The name bounded_view is deprecated. "
  165. "Please use common_view instead.") = common_view<Rng>;
  166. /// \endcond
  167. namespace views
  168. {
  169. /// \cond
  170. namespace
  171. {
  172. RANGES_DEPRECATED(
  173. "The name views::bounded is deprecated. "
  174. "Please use views::common instead.")
  175. RANGES_INLINE_VAR constexpr auto & bounded = common;
  176. } // namespace
  177. template<typename Rng>
  178. using bounded_t RANGES_DEPRECATED("The name views::bounded_t is deprecated.") =
  179. decltype(common(std::declval<Rng>()));
  180. /// \endcond
  181. } // namespace views
  182. namespace cpp20
  183. {
  184. namespace views
  185. {
  186. RANGES_INLINE_VARIABLE(ranges::views::view<ranges::views::cpp20_common_fn>,
  187. common)
  188. }
  189. CPP_template(typename Rng)( //
  190. requires view_<Rng> && (!common_range<Rng>)) //
  191. using common_view = ranges::common_view<Rng>;
  192. } // namespace cpp20
  193. } // namespace ranges
  194. #include <range/v3/detail/satisfy_boost_range.hpp>
  195. RANGES_SATISFY_BOOST_RANGE(::ranges::common_view)
  196. #endif