iterator.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #ifndef ENTT_CORE_ITERATOR_HPP
  2. #define ENTT_CORE_ITERATOR_HPP
  3. #include <iterator>
  4. #include <memory>
  5. #include <type_traits>
  6. #include <utility>
  7. namespace entt {
  8. /**
  9. * @brief Helper type to use as pointer with input iterators.
  10. * @tparam Type of wrapped value.
  11. */
  12. template<typename Type>
  13. struct input_iterator_pointer final {
  14. /*! @brief Value type. */
  15. using value_type = Type;
  16. /*! @brief Pointer type. */
  17. using pointer = Type *;
  18. /*! @brief Reference type. */
  19. using reference = Type &;
  20. /**
  21. * @brief Constructs a proxy object by move.
  22. * @param val Value to use to initialize the proxy object.
  23. */
  24. constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>)
  25. : value{std::move(val)} {}
  26. /**
  27. * @brief Access operator for accessing wrapped values.
  28. * @return A pointer to the wrapped value.
  29. */
  30. [[nodiscard]] constexpr pointer operator->() noexcept {
  31. return std::addressof(value);
  32. }
  33. /**
  34. * @brief Dereference operator for accessing wrapped values.
  35. * @return A reference to the wrapped value.
  36. */
  37. [[nodiscard]] constexpr reference operator*() noexcept {
  38. return value;
  39. }
  40. private:
  41. Type value;
  42. };
  43. /**
  44. * @brief Plain iota iterator (waiting for C++20).
  45. * @tparam Type Value type.
  46. */
  47. template<typename Type>
  48. class iota_iterator final {
  49. static_assert(std::is_integral_v<Type>, "Not an integral type");
  50. public:
  51. /*! @brief Value type, likely an integral one. */
  52. using value_type = Type;
  53. /*! @brief Invalid pointer type. */
  54. using pointer = void;
  55. /*! @brief Non-reference type, same as value type. */
  56. using reference = value_type;
  57. /*! @brief Difference type. */
  58. using difference_type = std::ptrdiff_t;
  59. /*! @brief Iterator category. */
  60. using iterator_category = std::input_iterator_tag;
  61. /*! @brief Default constructor. */
  62. constexpr iota_iterator() noexcept
  63. : current{} {}
  64. /**
  65. * @brief Constructs an iota iterator from a given value.
  66. * @param init The initial value assigned to the iota iterator.
  67. */
  68. constexpr iota_iterator(const value_type init) noexcept
  69. : current{init} {}
  70. /**
  71. * @brief Pre-increment operator.
  72. * @return This iota iterator.
  73. */
  74. constexpr iota_iterator &operator++() noexcept {
  75. return ++current, *this;
  76. }
  77. /**
  78. * @brief Post-increment operator.
  79. * @return This iota iterator.
  80. */
  81. constexpr iota_iterator operator++(int) noexcept {
  82. iota_iterator orig = *this;
  83. return ++(*this), orig;
  84. }
  85. /**
  86. * @brief Dereference operator.
  87. * @return The underlying value.
  88. */
  89. [[nodiscard]] constexpr reference operator*() const noexcept {
  90. return current;
  91. }
  92. private:
  93. value_type current;
  94. };
  95. /**
  96. * @brief Comparison operator.
  97. * @tparam Type Value type of the iota iterator.
  98. * @param lhs A properly initialized iota iterator.
  99. * @param rhs A properly initialized iota iterator.
  100. * @return True if the two iterators are identical, false otherwise.
  101. */
  102. template<typename Type>
  103. [[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
  104. return *lhs == *rhs;
  105. }
  106. /**
  107. * @brief Comparison operator.
  108. * @tparam Type Value type of the iota iterator.
  109. * @param lhs A properly initialized iota iterator.
  110. * @param rhs A properly initialized iota iterator.
  111. * @return True if the two iterators differ, false otherwise.
  112. */
  113. template<typename Type>
  114. [[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept {
  115. return !(lhs == rhs);
  116. }
  117. /**
  118. * @brief Utility class to create an iterable object from a pair of iterators.
  119. * @tparam It Type of iterator.
  120. * @tparam Sentinel Type of sentinel.
  121. */
  122. template<typename It, typename Sentinel = It>
  123. struct iterable_adaptor final {
  124. /*! @brief Value type. */
  125. using value_type = typename std::iterator_traits<It>::value_type;
  126. /*! @brief Iterator type. */
  127. using iterator = It;
  128. /*! @brief Sentinel type. */
  129. using sentinel = Sentinel;
  130. /*! @brief Default constructor. */
  131. constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> &&std::is_nothrow_default_constructible_v<sentinel>)
  132. : first{},
  133. last{} {}
  134. /**
  135. * @brief Creates an iterable object from a pair of iterators.
  136. * @param from Begin iterator.
  137. * @param to End iterator.
  138. */
  139. constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> &&std::is_nothrow_move_constructible_v<sentinel>)
  140. : first{std::move(from)},
  141. last{std::move(to)} {}
  142. /**
  143. * @brief Returns an iterator to the beginning.
  144. * @return An iterator to the first element of the range.
  145. */
  146. [[nodiscard]] constexpr iterator begin() const noexcept {
  147. return first;
  148. }
  149. /**
  150. * @brief Returns an iterator to the end.
  151. * @return An iterator to the element following the last element of the
  152. * range.
  153. */
  154. [[nodiscard]] constexpr sentinel end() const noexcept {
  155. return last;
  156. }
  157. /*! @copydoc begin */
  158. [[nodiscard]] constexpr iterator cbegin() const noexcept {
  159. return begin();
  160. }
  161. /*! @copydoc end */
  162. [[nodiscard]] constexpr sentinel cend() const noexcept {
  163. return end();
  164. }
  165. private:
  166. It first;
  167. Sentinel last;
  168. };
  169. } // namespace entt
  170. #endif