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.

generate_n.hpp 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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_GENERATE_N_HPP
  14. #define RANGES_V3_VIEW_GENERATE_N_HPP
  15. #include <type_traits>
  16. #include <utility>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/functional/invoke.hpp>
  20. #include <range/v3/iterator/default_sentinel.hpp>
  21. #include <range/v3/range/primitives.hpp>
  22. #include <range/v3/range/traits.hpp>
  23. #include <range/v3/utility/semiregular_box.hpp>
  24. #include <range/v3/utility/static_const.hpp>
  25. #include <range/v3/view/facade.hpp>
  26. #include <range/v3/view/generate.hpp>
  27. namespace ranges
  28. {
  29. /// \addtogroup group-views
  30. /// @{
  31. template<typename G>
  32. struct generate_n_view : view_facade<generate_n_view<G>, finite>
  33. {
  34. private:
  35. friend range_access;
  36. using result_t = invoke_result_t<G &>;
  37. semiregular_box_t<G> gen_;
  38. detail::non_propagating_cache<result_t> val_;
  39. std::size_t n_;
  40. struct cursor
  41. {
  42. private:
  43. generate_n_view * rng_;
  44. public:
  45. cursor() = default;
  46. explicit cursor(generate_n_view * rng)
  47. : rng_(rng)
  48. {}
  49. bool equal(default_sentinel_t) const
  50. {
  51. return 0 == rng_->n_;
  52. }
  53. result_t && read() const
  54. {
  55. if(!rng_->val_)
  56. rng_->val_.emplace(rng_->gen_());
  57. return static_cast<result_t &&>(static_cast<result_t &>(*rng_->val_));
  58. }
  59. void next()
  60. {
  61. RANGES_EXPECT(0 != rng_->n_);
  62. if(rng_->val_)
  63. rng_->val_.reset();
  64. else
  65. rng_->gen_();
  66. --rng_->n_;
  67. }
  68. };
  69. cursor begin_cursor()
  70. {
  71. return cursor{this};
  72. }
  73. public:
  74. generate_n_view() = default;
  75. explicit generate_n_view(G g, std::size_t n)
  76. : gen_(std::move(g))
  77. , n_(n)
  78. {}
  79. result_t & cached()
  80. {
  81. return *val_;
  82. }
  83. std::size_t size() const
  84. {
  85. return n_;
  86. }
  87. };
  88. namespace views
  89. {
  90. struct generate_n_fn
  91. {
  92. template<typename G>
  93. auto operator()(G g, std::size_t n) const -> CPP_ret(generate_n_view<G>)( //
  94. requires invocable<G &> && copy_constructible<G> &&
  95. std::is_object<detail::decay_t<invoke_result_t<G &>>>::value &&
  96. constructible_from<detail::decay_t<invoke_result_t<G &>>,
  97. invoke_result_t<G &>> &&
  98. assignable_from<detail::decay_t<invoke_result_t<G &>> &,
  99. invoke_result_t<G &>>)
  100. {
  101. return generate_n_view<G>{std::move(g), n};
  102. }
  103. };
  104. /// \relates generate_n_fn
  105. /// \ingroup group-views
  106. RANGES_INLINE_VARIABLE(generate_n_fn, generate_n)
  107. } // namespace views
  108. /// @}
  109. } // namespace ranges
  110. #include <range/v3/detail/satisfy_boost_range.hpp>
  111. RANGES_SATISFY_BOOST_RANGE(::ranges::generate_n_view)
  112. #endif