enumerate.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Casey Carter 2018-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_ENUMERATE_HPP
  14. #define RANGES_V3_VIEW_ENUMERATE_HPP
  15. #include <range/v3/core.hpp>
  16. #include <range/v3/iterator/unreachable_sentinel.hpp>
  17. #include <range/v3/view/all.hpp>
  18. #include <range/v3/view/facade.hpp>
  19. #include <range/v3/view/zip.hpp>
  20. #include <range/v3/detail/prologue.hpp>
  21. namespace ranges
  22. {
  23. /// \cond
  24. namespace detail
  25. {
  26. // Counts from zero up.
  27. // See https://github.com/ericniebler/range-v3/issues/1141
  28. // for why we don't just use iota_view.
  29. template<typename Size, typename Diff>
  30. struct index_view : view_facade<index_view<Size, Diff>, infinite>
  31. {
  32. private:
  33. friend range_access;
  34. struct cursor
  35. {
  36. using difference_type = Diff;
  37. private:
  38. friend range_access;
  39. Size index_{0};
  40. Size read() const
  41. {
  42. return index_;
  43. }
  44. void next()
  45. {
  46. ++index_;
  47. }
  48. bool equal(cursor const & that) const
  49. {
  50. return that.index_ == index_;
  51. }
  52. void prev()
  53. {
  54. --index_;
  55. }
  56. void advance(Diff n)
  57. {
  58. index_ += static_cast<Size>(n);
  59. }
  60. Diff distance_to(cursor const & that) const
  61. {
  62. return static_cast<Diff>(static_cast<Diff>(that.index_) -
  63. static_cast<Diff>(index_));
  64. }
  65. public:
  66. cursor() = default;
  67. };
  68. cursor begin_cursor() const
  69. {
  70. return cursor{};
  71. }
  72. unreachable_sentinel_t end_cursor() const
  73. {
  74. return unreachable;
  75. }
  76. public:
  77. index_view() = default;
  78. };
  79. } // namespace detail
  80. template<typename Size, typename Diff>
  81. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<detail::index_view<Size, Diff>> =
  82. true;
  83. /// \endcond
  84. /// \addtogroup group-views
  85. /// @{
  86. namespace views
  87. {
  88. /// Lazily pairs each element in a source range with
  89. /// its corresponding index.
  90. struct enumerate_fn
  91. {
  92. template(typename Rng)(
  93. requires viewable_range<Rng>)
  94. auto operator()(Rng && rng) const
  95. {
  96. using D = range_difference_t<Rng>;
  97. using S = detail::iter_size_t<iterator_t<Rng>>;
  98. return zip(detail::index_view<S, D>(), all(static_cast<Rng &&>(rng)));
  99. }
  100. };
  101. /// \relates enumerate_fn
  102. /// \ingroup group-views
  103. RANGES_INLINE_VARIABLE(view_closure<enumerate_fn>, enumerate)
  104. } // namespace views
  105. /// @}
  106. } // namespace ranges
  107. #include <range/v3/detail/epilogue.hpp>
  108. #endif