diff --git a/include/iterator.hpp b/include/iterator.hpp index e46b96b..689852f 100644 --- a/include/iterator.hpp +++ b/include/iterator.hpp @@ -37,6 +37,149 @@ class Range { auto end() const -> const Iterator { return m_end; } }; +namespace detail { + +template +requires requires(const C &c) { c.read(); } +using reference_t = decltype(std::declval().read()); + +namespace detail { +template struct deduced_value_t { + template static auto deduce(int) -> typename T::value_type; + template static auto deduce(...) -> std::decay_t>; + + using type = decltype(deduce(0)); +}; +} // namespace detail + +template +requires std::same_as::type, + std::decay_t::type>> +using value_type_t = typename detail::deduced_value_t::type; + +namespace detail { +template struct deduced_difference_t { + template static auto deduce(int) -> typename T::difference_type; + template + static auto deduce(long) -> decltype(std::declval().distance_to( + std::declval())); + template static auto deduce(...) -> std::ptrdiff_t; + + using type = decltype(deduce(0)); +}; +} // namespace detail + +template +using difference_type_t = typename detail::deduced_difference_t::type; + +template struct iterator_traits { + using difference_type = difference_type_t; + using value_type = value_type_t; + using reference = reference_t; +}; +} // namespace detail + +template struct iterator_t { +private: + I base_; + +public: + iterator_t() requires(std::is_default_constructible_v) : base_({}) {} + iterator_t(const I &base) : base_(base) {} + iterator_t(I &&base) : base_(std::move(base)) {} + + auto constexpr base() const -> const I & { return base_; } + auto constexpr base() -> I & { return base_; } + + // input_or_output_iterator + auto constexpr operator++(int) -> iterator_t + requires(std::input_or_output_iterator) { + const auto ret = *this; + base()++; + return ret; + } + auto constexpr operator++() + -> iterator_t &requires(std::input_or_output_iterator) { + this ++; + return *this; + } + + // input_iterator + auto constexpr operator*() const -> const std::iter_reference_t + requires(std::input_iterator) { return *base(); } + + // output_iterator + template + auto constexpr operator*() -> std::iter_reference_t + requires(std::output_iterator) { return *base(); } + + // forward_iterator + auto constexpr operator==(const iterator_t &rhs) const + -> bool requires(std::forward_iterator) { + return base() == rhs.base(); + } + + template S> + auto constexpr operator==(const S &rhs) const + -> bool requires(std::forward_iterator) { + return base() == rhs; + } + + // bidirectional_iterator + auto constexpr operator--(int) -> iterator_t + requires(std::bidirectional_iterator) { + const auto ret = *this; + base()--; + return ret; + } + auto constexpr operator--() + -> iterator_t &requires(std::bidirectional_iterator) { + base()--; + return *this; + } + + // random_access_iterator + auto constexpr operator<=>(const iterator_t &rhs) const + -> std::strong_ordering { + return base() <=> rhs.base(); + } + + auto constexpr operator-(const iterator_t &rhs) const + -> std::iter_difference_t { + return base() - rhs.base(); + } + auto constexpr operator+(const std::iter_difference_t &n) const + -> iterator_t { + return iterator_t(base() + n); + } + friend auto constexpr operator+(const std::iter_difference_t &n, + const iterator_t &rhs) -> iterator_t { + return rhs + n; + } + auto constexpr operator-(const std::iter_difference_t &n) const + -> iterator_t { + return iterator_t(base() - n); + } + + auto operator+=(const std::iter_difference_t &n) -> iterator_t & { + *this = iterator_t(base() + n); + return *this; + } + auto operator-=(const std::iter_difference_t &n) -> iterator_t & { + *this = iterator_t(base() - n); + return *this; + } + + auto constexpr operator[](const std::iter_difference_t &n) const + -> const std::iter_reference_t { + return base()[n]; + } + auto operator[](const std::iter_difference_t &n) + -> std::iter_reference_t { + return base()[n]; + } +}; + template struct BaseIterator { using value_type = V; using reference = V &; @@ -184,3 +327,8 @@ template using RangeIterator = Iterator>; } // namespace util + +namespace std { +template +struct iterator_traits> : public iterator_traits {}; +} // namespace std \ No newline at end of file