iterator_t (iterator wrapper) class

This commit is contained in:
janis 2022-07-01 01:39:24 +01:00
parent 292f0f4886
commit b872cc940b

View file

@ -37,6 +37,149 @@ class Range {
auto end() const -> const 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 V, typename I = V *> struct BaseIterator { template <typename V, typename I = V *> struct BaseIterator {
using value_type = V; using value_type = V;
using reference = V &; using reference = V &;
@ -184,3 +327,8 @@ template <std::ranges::range R>
using RangeIterator = Iterator<std::ranges::iterator_t<R>>; using RangeIterator = Iterator<std::ranges::iterator_t<R>>;
} // namespace util } // namespace util
namespace std {
template <typename I>
struct iterator_traits<util::iterator_t<I>> : public iterator_traits<I> {};
} // namespace std