diff --git a/src/entt/core/iterator.hpp b/src/entt/core/iterator.hpp index 1588c8043..41c744241 100644 --- a/src/entt/core/iterator.hpp +++ b/src/entt/core/iterator.hpp @@ -1,6 +1,7 @@ #ifndef ENTT_CORE_ITERATOR_HPP #define ENTT_CORE_ITERATOR_HPP +#include #include #include #include "../config/config.h" @@ -53,6 +54,63 @@ private: Type value; }; +/** + * @brief Utility class to create an iterable object from a pair of iterators. + * @tparam It Type of iterators. + */ +template +struct iterable_adaptor final { + /*! @brief Type of the objects returned during iteration. */ + using value_type = typename std::iterator_traits::value_type; + /*! @brief Iterator type. */ + using iterator = It; + /*! @brief Const iterator type. */ + using const_iterator = It; + + /*! @brief Default constructor. */ + iterable_adaptor() = default; + + /** + * @brief Creates an iterable object from a pair of iterators. + * @param from Begin iterator. + * @param to End iterator. + */ + iterable_adaptor(It from, It to) + : first{from}, + last{to} {} + + /** + * @brief Returns an iterator to the beginning. + * @return An iterator to the first element of the range. + */ + [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT { + return first; + } + + /*! @copydoc begin */ + [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT { + return begin(); + } + + /** + * @brief Returns an iterator to the end. + * @return An iterator to the element following the last element of the + * range. + */ + [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT { + return last; + } + + /*! @copydoc end */ + [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT { + return end(); + } + +private: + It first; + It last; +}; + } // namespace entt #endif diff --git a/test/entt/core/iterator.cpp b/test/entt/core/iterator.cpp index b15d6ae24..4ea1678c7 100644 --- a/test/entt/core/iterator.cpp +++ b/test/entt/core/iterator.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -20,3 +21,19 @@ TEST(Iterator, InputIteratorPointer) { ASSERT_EQ(instance.value, 0); ASSERT_EQ(ptr->value, 42); } + +TEST(Iterator, IterableAdaptor) { + std::vector vec{1, 2}; + entt::iterable_adaptor iterable{vec.begin(), vec.end()}; + decltype(iterable) other{}; + + ASSERT_NO_THROW(other = iterable); + ASSERT_NO_THROW(std::swap(other, iterable)); + + ASSERT_EQ(iterable.begin(), vec.begin()); + ASSERT_EQ(iterable.end(), vec.end()); + + ASSERT_EQ(*iterable.cbegin(), 1); + ASSERT_EQ(*++iterable.cbegin(), 2); + ASSERT_EQ(++iterable.cbegin(), --iterable.end()); +}