diff --git a/TODO b/TODO index bf1cbbccf..073051497 100644 --- a/TODO +++ b/TODO @@ -9,6 +9,7 @@ DOC: * storage * custom storage/view * examples (and credits) from @alanjfs :) +* document iterator.hpp (see core.md) WIP: * handle: replace visit with an iterable object diff --git a/src/entt/core/iterator.hpp b/src/entt/core/iterator.hpp index ee37577fa..78c530706 100644 --- a/src/entt/core/iterator.hpp +++ b/src/entt/core/iterator.hpp @@ -38,6 +38,90 @@ private: Type value; }; +/** + * @brief Plain iota iterator (waiting for C++20). + * @tparam Type Value type. + */ +template +class iota_iterator final { + static_assert(std::is_integral_v, "Not an integral type"); + +public: + /*! @brief Value type, likely an integral one. */ + using value_type = Type; + /*! @brief Invalid pointer type. */ + using pointer = void; + /*! @brief Non-reference type, same as value type. */ + using reference = value_type; + /*! @brief Difference type. */ + using difference_type = std::ptrdiff_t; + /*! @brief Iterator category. */ + using iterator_category = std::input_iterator_tag; + + /*! @brief Default constructor. */ + constexpr iota_iterator() noexcept + : current{} {} + + /** + * @brief Constructs an iota iterator from a given value. + * @param init The initial value assigned to the iota iterator. + */ + constexpr iota_iterator(const value_type init) noexcept + : current{init} {} + + /** + * @brief Pre-increment operator. + * @return This iota iterator. + */ + constexpr iota_iterator &operator++() noexcept { + return ++current, *this; + } + + /** + * @brief Post-increment operator. + * @return This iota iterator. + */ + constexpr iota_iterator operator++(int) noexcept { + iota_iterator orig = *this; + return ++(*this), orig; + } + + /** + * @brief Dereference operator. + * @return The underlying value. + */ + [[nodiscard]] constexpr reference operator*() const noexcept { + return current; + } + +private: + value_type current; +}; + +/** + * @brief Comparison operator. + * @tparam Type Value type of the iota iterator. + * @param lhs A properly initialized iota iterator. + * @param rhs A properly initialized iota iterator. + * @return True if the two iterators are identical, false otherwise. + */ +template +[[nodiscard]] constexpr bool operator==(const iota_iterator &lhs, const iota_iterator &rhs) noexcept { + return *lhs == *rhs; +} + +/** + * @brief Comparison operator. + * @tparam Type Value type of the iota iterator. + * @param lhs A properly initialized iota iterator. + * @param rhs A properly initialized iota iterator. + * @return True if the two iterators differ, false otherwise. + */ +template +[[nodiscard]] constexpr bool operator!=(const iota_iterator &lhs, const iota_iterator &rhs) noexcept { + return !(lhs == rhs); +} + /** * @brief Utility class to create an iterable object from a pair of iterators. * @tparam It Type of iterator. diff --git a/test/entt/core/iterator.cpp b/test/entt/core/iterator.cpp index cf346d3ef..d3c00447f 100644 --- a/test/entt/core/iterator.cpp +++ b/test/entt/core/iterator.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -17,6 +18,20 @@ TEST(InputIteratorPointer, Functionalities) { ASSERT_EQ(ptr->value, 42); } +TEST(IotaIterator, Functionalities) { + entt::iota_iterator first{}; + const entt::iota_iterator last{2u}; + + ASSERT_NE(first, last); + ASSERT_FALSE(first == last); + ASSERT_TRUE(first != last); + + ASSERT_EQ(*first++, 0u); + ASSERT_EQ(*first, 1u); + ASSERT_EQ(*++first, *last); + ASSERT_EQ(*first, 2u); +} + TEST(IterableAdaptor, Functionalities) { std::vector vec{1, 2}; entt::iterable_adaptor iterable{vec.begin(), vec.end()};