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.

130 lines
3.5KB

  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-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_REPEAT_N_HPP
  14. #define RANGES_V3_VIEW_REPEAT_N_HPP
  15. #include <utility>
  16. #include <range/v3/range_fwd.hpp>
  17. #include <range/v3/iterator/default_sentinel.hpp>
  18. #include <range/v3/range/concepts.hpp>
  19. #include <range/v3/utility/semiregular_box.hpp>
  20. #include <range/v3/utility/static_const.hpp>
  21. #include <range/v3/view/facade.hpp>
  22. namespace ranges
  23. {
  24. /// \addtogroup group-views
  25. /// @{
  26. // Ordinarily, a view shouldn't contain its elements. This is so that copying
  27. // and assigning ranges is O(1), and also so that in the event of element
  28. // mutation, all the copies of the range see the mutation the same way. The
  29. // repeat_n_view *does* own its lone element, though. This is OK because:
  30. // - O(N) copying is fine when N==1 as it is in this case, and
  31. // - The element is immutable, so there is no potential for incorrect
  32. // semantics.
  33. template<typename Val>
  34. struct repeat_n_view : view_facade<repeat_n_view<Val>, finite>
  35. {
  36. private:
  37. friend range_access;
  38. semiregular_box_t<Val> value_;
  39. std::ptrdiff_t n_;
  40. struct cursor
  41. {
  42. private:
  43. Val const * value_;
  44. std::ptrdiff_t n_;
  45. public:
  46. cursor() = default;
  47. cursor(Val const & value, std::ptrdiff_t n)
  48. : value_(std::addressof(value))
  49. , n_(n)
  50. {}
  51. Val const & read() const
  52. {
  53. return *value_;
  54. }
  55. constexpr bool equal(default_sentinel_t) const
  56. {
  57. return 0 == n_;
  58. }
  59. bool equal(cursor const & that) const
  60. {
  61. return n_ == that.n_;
  62. }
  63. void next()
  64. {
  65. RANGES_EXPECT(0 != n_);
  66. --n_;
  67. }
  68. void prev()
  69. {
  70. ++n_;
  71. }
  72. void advance(std::ptrdiff_t n)
  73. {
  74. n_ -= n;
  75. }
  76. std::ptrdiff_t distance_to(cursor const & that) const
  77. {
  78. return n_ - that.n_;
  79. }
  80. };
  81. cursor begin_cursor() const
  82. {
  83. return {value_, n_};
  84. }
  85. public:
  86. repeat_n_view() = default;
  87. constexpr repeat_n_view(Val value, std::ptrdiff_t n)
  88. : value_(detail::move(value))
  89. , n_((RANGES_EXPECT(0 <= n), n))
  90. {}
  91. constexpr std::size_t size() const
  92. {
  93. return static_cast<std::size_t>(n_);
  94. }
  95. };
  96. namespace views
  97. {
  98. struct repeat_n_fn
  99. {
  100. template<typename Val>
  101. auto operator()(Val value, std::ptrdiff_t n) const
  102. -> CPP_ret(repeat_n_view<Val>)( //
  103. requires copy_constructible<Val>)
  104. {
  105. return repeat_n_view<Val>{std::move(value), n};
  106. }
  107. };
  108. /// \relates repeat_n_fn
  109. /// \ingroup group-views
  110. RANGES_INLINE_VARIABLE(repeat_n_fn, repeat_n)
  111. } // namespace views
  112. /// @}
  113. } // namespace ranges
  114. #include <range/v3/detail/satisfy_boost_range.hpp>
  115. RANGES_SATISFY_BOOST_RANGE(::ranges::repeat_n_view)
  116. #endif