19#include "parameter_pack.h"
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)) {}
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()...) {
193 iterator begin() noexcept {
194 return iterator(begins_);
196 iterator end() noexcept {
197 return iterator(ends_);
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 std::enable_if_t<!impl::is_forward_iterator<Iterator>,
223 decltype((iterator + 1).base())
225 return (iterator + 1).base();
228 template<
typename Iterator>
229 auto reverse_iterator_direction(Iterator iterator)
noexcept ->
230 std::enable_if_t<impl::is_forward_iterator<Iterator>,
231 decltype(std::make_reverse_iterator(std::declval<Iterator>()))
234 return std::make_reverse_iterator(iterator + 1);
238template<
typename Iterator>
240 if (size() != rhs.size()) {
243 for (
const auto&[l, r] :
aui::zip(*
this, rhs)) {
252inline std::ostream& operator<<(std::ostream& os,
aui::range<T> range) {
255 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
Definition: iterators.h:34
Definition: iterators.h:162
Iterates multiple containers in parallel.
Definition: iterators.h:154