19#include "parameter_pack.h"
34 struct reverse_iterator_wrap {
39 explicit reverse_iterator_wrap(
const T& mIterable) : mIterable(&mIterable) {}
42 return mIterable->rbegin();
45 return mIterable->rend();
49 template<
typename Iterator>
55 constexpr range(Iterator mBegin, Iterator mEnd) : mBegin(mBegin), mEnd(mEnd) {}
58 if constexpr (
requires { std::distance(mBegin, mEnd); }) {
63 template<
typename Container>
64 constexpr range(Container& c): mBegin(c.begin()), mEnd(c.end()) {
69 template<
typename Container>
70 constexpr range(
const Container& c): mBegin(c.begin()), mEnd(c.end()) {
75 constexpr bool empty()
const noexcept {
76 return mBegin == mEnd;
80 constexpr std::size_t size()
const noexcept requires requires { std::distance(mBegin, mEnd); } {
81 return std::distance(mBegin, mEnd);
85 constexpr Iterator& begin()
noexcept {
90 constexpr Iterator& end()
noexcept {
95 constexpr Iterator begin()
const noexcept {
100 constexpr Iterator end()
const noexcept {
105 constexpr const auto& first()
const {
110 constexpr const auto& last()
const {
111 return *std::prev(mEnd);
115 constexpr bool operator==(
const range& rhs)
const noexcept;
118 constexpr bool operator!=(
const range& rhs)
const noexcept {
119 return !(*
this == rhs);
123 template<
typename Container>
124 range(Container& c) ->
range<
decltype(c.begin())>;
126 template<
typename Container>
127 range(
const Container& c) ->
range<
decltype(c.begin())>;
132 template<
typename Container>
133 using const_iterator_if_const = std::conditional_t<std::is_const_v<Container>,
134 typename Container::const_iterator,
135 typename Container::iterator>;
155 template<
typename... Containers>
158 using iterator_parallel = std::tuple<decltype(std::declval<Containers>().begin())...>;
160 iterator_parallel begins_;
161 iterator_parallel ends_;
165 iterator_parallel iterators_;
167 iterator(iterator_parallel iterators) : iterators_(std::move(iterators)) {}
169 iterator& operator++()
noexcept {
170 std::apply([](
auto&&... v) {
176 std::tuple<decltype(*std::declval<Containers>().begin())&...>
operator*()
noexcept {
177 return std::apply([](
auto&&... v) {
178 return std::tuple<decltype(*std::declval<Containers>().begin())&...>((*v)...);
182 bool operator==(
const iterator& rhs)
const noexcept {
183 return iterators_ == rhs.iterators_;
186 bool operator!=(
const iterator& rhs)
const noexcept {
187 return iterators_ != rhs.iterators_;
191 zip(Containers&... c): begins_(c.begin()...), ends_(c.end()...) {
204 template<
typename Iterator,
class =
void>
205 static constexpr bool is_forward_iterator =
true;
207 template<
typename Iterator>
208 static constexpr bool is_forward_iterator<std::reverse_iterator<Iterator>> =
false;
222 template<
typename Iterator>
223 auto reverse_iterator_direction(Iterator iterator)
noexcept ->
224 decltype((iterator + 1).base())
requires (!impl::is_forward_iterator<Iterator>) {
225 return (iterator + 1).base();
228 template<
typename Iterator>
229 auto reverse_iterator_direction(Iterator iterator)
noexcept ->
230 decltype(std::make_reverse_iterator(std::declval<Iterator>()))
requires (impl::is_forward_iterator<Iterator>) {
232 return std::make_reverse_iterator(iterator + 1);
236template<
typename Iterator>
237inline constexpr bool aui::range<Iterator>::operator==(
const range& rhs)
const noexcept {
238 if (size() != rhs.size()) {
241 for (
const auto&[l, r] :
aui::zip(*
this, rhs)) {
250inline std::ostream& operator<<(std::ostream& os,
aui::range<T> range) {
253 for (
const auto& v : range) {
#define AUI_NO_OPTIMIZE_OUT(object)
Forbids object from being optimized out by compiler.
Definition macros.h:40
Definition iterators.h:50
Iterates multiple containers in parallel.
Definition iterators.h:156