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.

113 lines
3.1KB

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