cpp-utils/include/iterator.hpp

191 lines
5.2 KiB
C++

#pragma once
#include <compare>
#include <cstddef>
#include <iterator>
#include <tuple>
#include <type_traits>
#include <xutility>
namespace util {
template <int I, class... Ts>
decltype(auto) get(Ts&&... ts) {
return std::get<I>(std::forward_as_tuple(ts...));
}
template <class Iterator>
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<const Iterator, const Iterator>& t) {
m_begin = t.first;
m_end = t.second;
}
template <typename... Args>
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 <class C>
requires requires(const C &c) { c.read(); }
using reference_t = decltype(std::declval<const C &>().read());
namespace detail {
template <class C> struct deduced_value_t {
template <class T> static auto deduce(int) -> typename T::value_type;
template <class T> static auto deduce(...) -> std::decay_t<reference_t<T>>;
using type = decltype(deduce<C>(0));
};
} // namespace detail
template <class C>
requires std::same_as<typename detail::deduced_value_t<C>::type,
std::decay_t<typename detail::deduced_value_t<C>::type>>
using value_type_t = typename detail::deduced_value_t<C>::type;
namespace detail {
template <class C> struct deduced_difference_t {
template <class T> static auto deduce(int) -> typename T::difference_type;
template <class T>
static auto deduce(long) -> decltype(std::declval<const T &>().distance_to(
std::declval<const T &>()));
template <class T> static auto deduce(...) -> std::ptrdiff_t;
using type = decltype(deduce<C>(0));
};
} // namespace detail
template <class C>
using difference_type_t = typename detail::deduced_difference_t<C>::type;
template <typename I> struct iterator_traits {
using difference_type = difference_type_t<I>;
using value_type = value_type_t<I>;
using reference = reference_t<I>;
};
} // namespace detail
template <typename I> struct iterator_t {
private:
I base_;
public:
iterator_t() requires(std::is_default_constructible_v<I>) : 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<I>) {
const auto ret = *this;
base()++;
return ret;
}
auto constexpr operator++()
-> iterator_t &requires(std::input_or_output_iterator<I>) {
this ++;
return *this;
}
// input_iterator
auto constexpr operator*() const -> const std::iter_reference_t<I>
requires(std::input_iterator<I>) { return *base(); }
// output_iterator
template <typename T = decltype(*base_)>
auto constexpr operator*() -> std::iter_reference_t<I>
requires(std::output_iterator<I, T>) { return *base(); }
// forward_iterator
auto constexpr operator==(const iterator_t &rhs) const
-> bool requires(std::forward_iterator<I>) {
return base() == rhs.base();
}
template <std::sentinel_for<I> S>
auto constexpr operator==(const S &rhs) const
-> bool requires(std::forward_iterator<I>) {
return base() == rhs;
}
// bidirectional_iterator
auto constexpr operator--(int) -> iterator_t
requires(std::bidirectional_iterator<I>) {
const auto ret = *this;
base()--;
return ret;
}
auto constexpr operator--()
-> iterator_t &requires(std::bidirectional_iterator<I>) {
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<I> {
return base() - rhs.base();
}
auto constexpr operator+(const std::iter_difference_t<I> &n) const
-> iterator_t {
return iterator_t(base() + n);
}
friend auto constexpr operator+(const std::iter_difference_t<I> &n,
const iterator_t &rhs) -> iterator_t {
return rhs + n;
}
auto constexpr operator-(const std::iter_difference_t<I> &n) const
-> iterator_t {
return iterator_t(base() - n);
}
auto operator+=(const std::iter_difference_t<I> &n) -> iterator_t & {
*this = iterator_t(base() + n);
return *this;
}
auto operator-=(const std::iter_difference_t<I> &n) -> iterator_t & {
*this = iterator_t(base() - n);
return *this;
}
auto constexpr operator[](const std::iter_difference_t<I> &n) const
-> const std::iter_reference_t<I> {
return base()[n];
}
auto operator[](const std::iter_difference_t<I> &n)
-> std::iter_reference_t<I> {
return base()[n];
}
};
template <typename T, typename I>
concept iterator = std::same_as<typename iterator_t<I>::value_type, T>;
} // namespace util
namespace std {
template <typename I>
struct iterator_traits<util::iterator_t<I>> : public iterator_traits<I> {};
} // namespace std