#ifndef ENTT_CORE_ITERATOR_HPP #define ENTT_CORE_ITERATOR_HPP #include "../stl/concepts.hpp" #include "../stl/cstddef.hpp" #include "../stl/iterator.hpp" #include "../stl/memory.hpp" #include "../stl/type_traits.hpp" #include "../stl/utility.hpp" namespace entt { /** * @brief Helper type to use as pointer with input iterators. * @tparam Type of wrapped value. */ template struct input_iterator_pointer final { /*! @brief Value type. */ using value_type = Type; /*! @brief Pointer type. */ using pointer = Type *; /*! @brief Reference type. */ using reference = Type &; /** * @brief Constructs a proxy object by move. * @param val Value to use to initialize the proxy object. */ constexpr input_iterator_pointer(value_type &&val) noexcept(stl::is_nothrow_move_constructible_v) : value{stl::move(val)} {} /** * @brief Access operator for accessing wrapped values. * @return A pointer to the wrapped value. */ [[nodiscard]] constexpr pointer operator->() noexcept { return stl::addressof(value); } /** * @brief Dereference operator for accessing wrapped values. * @return A reference to the wrapped value. */ [[nodiscard]] constexpr reference operator*() noexcept { return value; } private: Type value; }; /** * @brief Plain iota iterator (waiting for C++20). * @tparam Type Value type. */ template struct iota_iterator final { /*! @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 = stl::ptrdiff_t; /*! @brief Iterator category. */ using iterator_category = stl::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 { const iota_iterator orig = *this; return ++(*this), orig; } /** * @brief Dereference operator. * @return The underlying value. */ [[nodiscard]] constexpr reference operator*() const noexcept { return current; } /** * @brief Comparison operator. * @param other A properly initialized iota iterator. * @return True if the two iterators are identical, false otherwise. */ [[nodiscard]] constexpr bool operator==(const iota_iterator &other) const noexcept { return current == other.current; } private: value_type current; }; /** * @brief Utility class to create an iterable object from a pair of iterators. * @tparam It Type of iterator. * @tparam Sentinel Type of sentinel. */ template Sentinel = It> struct iterable_adaptor final { /*! @brief Value type. */ using value_type = stl::iterator_traits::value_type; /*! @brief Iterator type. */ using iterator = It; /*! @brief Sentinel type. */ using sentinel = Sentinel; /*! @brief Default constructor. */ constexpr iterable_adaptor() noexcept(stl::is_nothrow_default_constructible_v && stl::is_nothrow_default_constructible_v) : first{}, last{} {} /** * @brief Creates an iterable object from a pair of iterators. * @param from Begin iterator. * @param to End iterator. */ constexpr iterable_adaptor(iterator from, sentinel to) noexcept(stl::is_nothrow_move_constructible_v && stl::is_nothrow_move_constructible_v) : first{stl::move(from)}, last{stl::move(to)} {} /** * @brief Returns an iterator to the beginning. * @return An iterator to the first element of the range. */ [[nodiscard]] constexpr iterator begin() const noexcept { return first; } /** * @brief Returns an iterator to the end. * @return An iterator to the element following the last element of the * range. */ [[nodiscard]] constexpr sentinel end() const noexcept { return last; } /*! @copydoc begin */ [[nodiscard]] constexpr iterator cbegin() const noexcept { return begin(); } /*! @copydoc end */ [[nodiscard]] constexpr sentinel cend() const noexcept { return end(); } private: It first; Sentinel last; }; } // namespace entt #endif