enumerate_view.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2024 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Use, modification and distribution is subject to the Boost Software License,
  4. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_GEOMETRY_VIEWS_ENUMERATE_VIEW_HPP
  7. #define BOOST_GEOMETRY_VIEWS_ENUMERATE_VIEW_HPP
  8. #include <boost/iterator/iterator_facade.hpp>
  9. #include <boost/iterator/iterator_categories.hpp>
  10. #include <boost/range/begin.hpp>
  11. #include <boost/range/end.hpp>
  12. #include <boost/range/difference_type.hpp>
  13. #include <boost/range/reference.hpp>
  14. #include <boost/range/value_type.hpp>
  15. #include <boost/geometry/util/type_traits_std.hpp>
  16. namespace boost { namespace geometry
  17. {
  18. namespace util
  19. {
  20. // This view is a range of values, each with an index
  21. // It is used to iterate over a range, and to get the index of the value
  22. // It is used in the enumerate function
  23. // The typename Range can either be const or non-const
  24. template <typename Range>
  25. struct enumerated_view
  26. {
  27. // The return value of the iterator
  28. struct value_with_index
  29. {
  30. using type = util::transcribe_const_t
  31. <
  32. Range,
  33. typename boost::range_value<Range>::type
  34. >;
  35. // Member variable index contains the zero-based index of the value in the range
  36. std::size_t const index;
  37. // Member variable value contains a const or non-const reference to the value itself
  38. type& value;
  39. };
  40. private:
  41. // Iterator implementation, not exposed.
  42. struct enumerating_iterator
  43. : public boost::iterator_facade
  44. <
  45. enumerating_iterator,
  46. value_with_index const,
  47. boost::random_access_traversal_tag,
  48. value_with_index const,
  49. typename boost::range_difference<Range>::type
  50. >
  51. {
  52. using reference = value_with_index;
  53. using difference_type = typename boost::range_difference<Range>::type;
  54. // Constructor with the range it handles
  55. explicit inline enumerating_iterator(Range& range)
  56. : m_begin(boost::begin(range))
  57. , m_end(boost::end(range))
  58. , m_iterator(boost::begin(range))
  59. {}
  60. // Constructor to indicate the end of a range
  61. explicit inline enumerating_iterator(Range& range, bool)
  62. : m_begin(boost::begin(range))
  63. , m_end(boost::end(range))
  64. , m_iterator(boost::end(range))
  65. {}
  66. // There is no default constructor
  67. enumerating_iterator() = delete;
  68. inline reference dereference() const
  69. {
  70. constexpr difference_type zero = 0;
  71. const std::size_t index = (std::max)(zero, std::distance(m_begin, m_iterator));
  72. const value_with_index result{index, *m_iterator};
  73. return result;
  74. }
  75. inline difference_type distance_to(enumerating_iterator const& other) const
  76. {
  77. return std::distance(other.m_iterator, m_iterator);
  78. }
  79. inline bool equal(enumerating_iterator const& other) const
  80. {
  81. return
  82. m_begin == other.m_begin
  83. && m_end == other.m_end
  84. && m_iterator == other.m_iterator;
  85. }
  86. inline void increment()
  87. {
  88. ++m_iterator;
  89. }
  90. inline void decrement()
  91. {
  92. --m_iterator;
  93. }
  94. inline void advance(difference_type n)
  95. {
  96. std::advance(m_iterator, n);
  97. }
  98. const typename boost::range_iterator<Range>::type m_begin;
  99. const typename boost::range_iterator<Range>::type m_end;
  100. typename boost::range_iterator<Range>::type m_iterator;
  101. };
  102. public:
  103. using iterator = enumerating_iterator;
  104. using const_iterator = enumerating_iterator;
  105. explicit inline enumerated_view(Range& range)
  106. : m_begin(range)
  107. , m_end(range, true)
  108. {}
  109. inline iterator begin() const { return m_begin; }
  110. inline iterator end() const { return m_end; }
  111. private:
  112. const iterator m_begin;
  113. const iterator m_end;
  114. };
  115. // Helper function to create the enumerated view, for a const range
  116. template <typename Range>
  117. inline auto enumerate(Range const& range)
  118. {
  119. return util::enumerated_view<Range const>(range);
  120. }
  121. // Helper function to create the enumerated view, for a non-const range
  122. template <typename Range>
  123. inline auto enumerate(Range& range)
  124. {
  125. return util::enumerated_view<Range>(range);
  126. }
  127. }}} // boost::geometry::util
  128. #endif // BOOST_GEOMETRY_VIEWS_ENUMERATE_VIEW_HPP