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) {}
61 template<
typename Container>
62 constexpr range(Container& c): mBegin(c.begin()), mEnd(c.end()) {
67 template<
typename Container>
68 constexpr range(
const Container& c): mBegin(c.begin()), mEnd(c.end()) {
73 constexpr bool empty()
const noexcept {
74 return mBegin == mEnd;
78 constexpr std::size_t size()
const noexcept {
79 return std::distance(mBegin, mEnd);
83 constexpr Iterator& begin()
noexcept {
88 constexpr Iterator& end()
noexcept {
93 constexpr Iterator begin()
const noexcept {
98 constexpr Iterator end()
const noexcept {
103 constexpr const auto& first()
const {
108 constexpr const auto& last()
const {
109 return *std::prev(mEnd);
113 constexpr bool operator==(
const range& rhs)
const noexcept;
116 constexpr bool operator!=(
const range& rhs)
const noexcept {
117 return !(*
this == rhs);
121 template<
typename Container>
122 range(Container& c) ->
range<
decltype(c.begin())>;
124 template<
typename Container>
125 range(
const Container& c) ->
range<
decltype(c.begin())>;
130 template<
typename Container>
131 using const_iterator_if_const = std::conditional_t<std::is_const_v<Container>,
132 typename Container::const_iterator,
133 typename Container::iterator>;
153 template<
typename... Containers>
156 using iterator_parallel = std::tuple<decltype(std::declval<Containers>().begin())...>;
158 iterator_parallel begins_;
159 iterator_parallel ends_;
163 iterator_parallel iterators_;
165 iterator(iterator_parallel iterators) : iterators_(std::move(iterators)) {}
167 iterator& operator++()
noexcept {
168 std::apply([](
auto&&... v) {
174 std::tuple<decltype(*std::declval<Containers>().begin())&...>
operator*()
noexcept {
175 return std::apply([](
auto&&... v) {
176 return std::tuple<decltype(*std::declval<Containers>().begin())&...>((*v)...);
180 bool operator==(
const iterator& rhs)
const noexcept {
181 return iterators_ == rhs.iterators_;
184 bool operator!=(
const iterator& rhs)
const noexcept {
185 return iterators_ != rhs.iterators_;
189 zip(Containers&... c): begins_(c.begin()...), ends_(c.end()...) {
202 template<
typename Iterator,
class =
void>
203 static constexpr bool is_forward_iterator =
true;
205 template<
typename Iterator>
206 static constexpr bool is_forward_iterator<std::reverse_iterator<Iterator>> =
false;
220 template<
typename Iterator>
221 auto reverse_iterator_direction(Iterator iterator)
noexcept ->
222 decltype((iterator + 1).base())
requires (!impl::is_forward_iterator<Iterator>) {
223 return (iterator + 1).base();
226 template<
typename Iterator>
227 auto reverse_iterator_direction(Iterator iterator)
noexcept ->
228 decltype(std::make_reverse_iterator(std::declval<Iterator>()))
requires (impl::is_forward_iterator<Iterator>) {
230 return std::make_reverse_iterator(iterator + 1);
234template<
typename Iterator>
235inline constexpr bool aui::range<Iterator>::operator==(
const range& rhs)
const noexcept {
236 if (size() != rhs.size()) {
239 for (
const auto&[l, r] :
aui::zip(*
this, rhs)) {
248inline std::ostream& operator<<(std::ostream& os,
aui::range<T> range) {
251 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:154