#pragma once #include #include #include #include #include #include namespace util { template decltype(auto) get(Ts&&... ts) { return std::get(std::forward_as_tuple(ts...)); } template class Range { Iterator m_begin, m_end; public: Range(const Iterator _begin, const Iterator _end) : m_begin(_begin), m_end(_end) {} Range(const std::pair& t) { m_begin = t.first; m_end = t.second; } template Range(Args&&... args) : m_begin(get<0>(args...)), m_end(get<1>(args...)) {} auto begin() -> Iterator { return m_begin; } auto begin() const -> const Iterator { return m_begin; } auto end() -> Iterator { return m_end; } 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 &; 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 namespace std { template struct iterator_traits> : public iterator_traits {}; } // namespace std