#ifndef ENTT_CORE_ITERATOR_HPP #define ENTT_CORE_ITERATOR_HPP #include #include #include #include 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(std::is_nothrow_move_constructible_v) : value{std::move(val)} {} /** * @brief Access operator for accessing wrapped values. * @return A pointer to the wrapped value. */ [[nodiscard]] constexpr pointer operator->() noexcept { return std::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 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. * @tparam Sentinel Type of sentinel. */ template struct iterable_adaptor final { /*! @brief Value type. */ using value_type = typename std::iterator_traits::value_type; /*! @brief Iterator type. */ using iterator = It; /*! @brief Sentinel type. */ using sentinel = Sentinel; /*! @brief Default constructor. */ constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v &&std::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(std::is_nothrow_move_constructible_v &&std::is_nothrow_move_constructible_v) : first{std::move(from)}, last{std::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