repeat_n.hpp 3.5 KB

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