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.

134 line
4.0KB

  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_TAIL_HPP
  14. #define RANGES_V3_VIEW_TAIL_HPP
  15. #include <type_traits>
  16. #include <utility>
  17. #include <range/v3/range_fwd.hpp>
  18. #include <range/v3/iterator/operations.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. namespace detail
  30. {
  31. template<typename T>
  32. constexpr T prev_or_zero_(T n)
  33. {
  34. return n == 0 ? T(0) : T(n - 1);
  35. }
  36. } // namespace detail
  37. /// \addtogroup group-views
  38. /// @{
  39. template<typename Rng>
  40. struct tail_view
  41. : view_interface<tail_view<Rng>,
  42. (range_cardinality<Rng>::value >= 0)
  43. ? detail::prev_or_zero_(range_cardinality<Rng>::value)
  44. : range_cardinality<Rng>::value>
  45. {
  46. private:
  47. Rng rng_;
  48. public:
  49. tail_view() = default;
  50. tail_view(Rng rng)
  51. : rng_(static_cast<Rng &&>(rng))
  52. {
  53. CPP_assert(input_range<Rng>);
  54. }
  55. iterator_t<Rng> begin()
  56. {
  57. return next(ranges::begin(rng_), 1, ranges::end(rng_));
  58. }
  59. template<bool Const = true>
  60. auto begin() const -> CPP_ret(iterator_t<meta::const_if_c<Const, Rng>>)( //
  61. requires Const && range<meta::const_if_c<Const, Rng>>)
  62. {
  63. return next(ranges::begin(rng_), 1, ranges::end(rng_));
  64. }
  65. sentinel_t<Rng> end()
  66. {
  67. return ranges::end(rng_);
  68. }
  69. template<bool Const = true>
  70. auto end() const -> CPP_ret(sentinel_t<meta::const_if_c<Const, Rng>>)( //
  71. requires Const && range<meta::const_if_c<Const, Rng>>)
  72. {
  73. return ranges::end(rng_);
  74. }
  75. CPP_member
  76. constexpr auto CPP_fun(size)()(requires sized_range<Rng>)
  77. {
  78. using size_type = range_size_t<Rng>;
  79. return range_cardinality<Rng>::value >= 0
  80. ? detail::prev_or_zero_((size_type)range_cardinality<Rng>::value)
  81. : detail::prev_or_zero_(ranges::size(rng_));
  82. }
  83. CPP_member
  84. constexpr auto CPP_fun(size)()(const requires sized_range<Rng const>)
  85. {
  86. using size_type = range_size_t<Rng>;
  87. return range_cardinality<Rng>::value >= 0
  88. ? detail::prev_or_zero_((size_type)range_cardinality<Rng>::value)
  89. : detail::prev_or_zero_(ranges::size(rng_));
  90. }
  91. Rng base() const
  92. {
  93. return rng_;
  94. }
  95. };
  96. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  97. CPP_template(typename Rng)(requires viewable_range<Rng>) tail_view(Rng &&)
  98. ->tail_view<views::all_t<Rng>>;
  99. #endif
  100. namespace views
  101. {
  102. struct tail_fn
  103. {
  104. template<typename Rng>
  105. auto operator()(Rng && rng) const
  106. -> CPP_ret(meta::if_c<range_cardinality<Rng>::value == 0, all_t<Rng>,
  107. tail_view<all_t<Rng>>>)( //
  108. requires viewable_range<Rng> && input_range<Rng>)
  109. {
  110. return all(static_cast<Rng &&>(rng));
  111. }
  112. };
  113. /// \relates tail_fn
  114. /// \ingroup group-views
  115. RANGES_INLINE_VARIABLE(view<tail_fn>, tail)
  116. } // namespace views
  117. /// @}
  118. } // namespace ranges
  119. #include <range/v3/detail/satisfy_boost_range.hpp>
  120. RANGES_SATISFY_BOOST_RANGE(::ranges::tail_view)
  121. #endif