diff --git a/include/iterator.hpp b/include/iterator.hpp index 949acfa..e46b96b 100644 --- a/include/iterator.hpp +++ b/include/iterator.hpp @@ -1,6 +1,11 @@ #pragma once +#include +#include +#include #include +#include +#include namespace util { @@ -32,4 +37,150 @@ class Range { auto end() const -> const Iterator { return m_end; } }; +template struct BaseIterator { + using value_type = V; + using reference = V &; + using difference_type = std::ptrdiff_t; + + I base_iter; + + BaseIterator(const I &iter) : base_iter(iter) {} + BaseIterator(I &&iter) : base_iter(std::move(iter)) {} +}; + +template +struct InputOrOutputIterator : public BaseIterator { + InputOrOutputIterator(const I &iter) : BaseIterator(iter) {} + InputOrOutputIterator(I &&iter) : BaseIterator(std::move(iter)) {} + + auto constexpr operator*() const -> void {} + + auto constexpr operator++(int) -> InputOrOutputIterator { + const auto ret = *this; + this->base_iter++; + return ret; + } + auto constexpr operator++() -> InputOrOutputIterator & { + this ++; + return *this; + } +}; + +template +struct InputIterator : public InputOrOutputIterator, + public std::input_iterator_tag { + InputIterator(const I &iter) : BaseIterator(iter) {} + InputIterator(I &&iter) : BaseIterator(std::move(iter)) {} + + auto constexpr operator*() const -> const V & { return *this->base_iter; } +}; + +template +struct OutputIterator : public InputOrOutputIterator, + public std::output_iterator_tag { + OutputIterator(const I &iter) : BaseIterator(iter) {} + OutputIterator(I &&iter) : BaseIterator(std::move(iter)) {} + + auto constexpr operator*() -> V & { return *this->base_iter; } +}; + +template +struct ForwardIterator : public InputIterator, + public std::forward_iterator_tag { + ForwardIterator(const I &iter) : BaseIterator(iter) {} + ForwardIterator(I &&iter) : BaseIterator(std::move(iter)) {} + + auto constexpr operator==(const ForwardIterator &rhs) const -> bool { + return this->base_iter == rhs.base_iter; + } +}; + +template +struct BidirectionalIterator : public ForwardIterator, + public std::bidirectional_iterator_tag { + BidirectionalIterator(const I &iter) : BaseIterator(iter) {} + BidirectionalIterator(I &&iter) : BaseIterator(std::move(iter)) {} + + auto constexpr operator--(int) -> BidirectionalIterator { + const auto ret = *this; + this->base_iter--; + return ret; + } + auto constexpr operator--() -> BidirectionalIterator & { + this --; + return *this; + } +}; + +template +struct RandomAccessIterator : public BidirectionalIterator, + public std::random_access_iterator_tag { + using difference_type = typename BaseIterator::difference_type; + + RandomAccessIterator(const I &iter) : BaseIterator(iter) {} + RandomAccessIterator(I &&iter) : BaseIterator(std::move(iter)) {} + + auto constexpr operator<=>(const RandomAccessIterator &rhs) const + -> std::strong_ordering { + return this->base_iter <=> rhs.base_iter; + } + + auto constexpr operator-(const RandomAccessIterator &rhs) const + -> difference_type { + return this->base_iter - rhs.base_iter; + } + auto constexpr operator+(const difference_type &n) const + -> RandomAccessIterator { + return RandomAccessIterator(this->base_iter + n); + } + friend auto constexpr operator+(const difference_type &n, + const RandomAccessIterator &rhs) + -> RandomAccessIterator { + return rhs + n; + } + auto constexpr operator-(const difference_type &n) const + -> RandomAccessIterator { + return RandomAccessIterator(this->base_iter - n); + } + + auto operator+=(const difference_type &n) -> RandomAccessIterator & { + *this = RandomAccessIterator(this->base_iter + n); + return *this; + } + auto operator-=(const difference_type &n) -> RandomAccessIterator & { + *this = RandomAccessIterator(this->base_iter - n); + return *this; + } + + auto constexpr operator[](const difference_type &n) const -> const V & { + return this->base_iter[n]; + } + auto operator[](const difference_type &n) -> V & { + return this->base_iter[n]; + } +}; + +template +using Iterator = std::conditional_t< + std::random_access_iterator, + RandomAccessIterator, I>, + std::conditional_t< + std::bidirectional_iterator, + BidirectionalIterator, I>, + std::conditional_t< + std::forward_iterator, ForwardIterator, I>, + std::conditional_t< + std::output_iterator())>, + OutputIterator, I>, + std::conditional_t< + std::input_iterator, + InputIterator, I>, + std::conditional_t< + std::input_or_output_iterator, + InputOrOutputIterator, I>, + RandomAccessIterator>>>>>>; + +template +using RangeIterator = Iterator>; + } // namespace util