neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
zip_iterator.hpp
Go to the documentation of this file.
1// zip_iterator.hpp
2/*
3 * Copyright (c) 2018, 2020 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <neolib/neolib.hpp>
39#include <utility>
40#include <tuple>
41#include <iterator>
42#include <functional>
43
44namespace neolib
45{
46 template <typename... Iterators>
48 {
49 typedef std::tuple<Iterators...> iterators;
50 typedef std::ptrdiff_t difference_type;
51 typedef std::tuple<typename Iterators::value_type...> value_type;
52 typedef std::tuple<typename Iterators::pointer...> pointer;
53 typedef std::tuple<typename Iterators::reference...> reference;
54 typedef typename std::iterator_traits<typename std::tuple_element<0, iterators>::type>::iterator_category iterator_category;
55 };
56
57 template <typename... Iterators>
59 {
60 typedef zip_iterator<Iterators...> self_type;
61 private:
62 typedef zip_iterator_traits<Iterators...> traits;
63 typedef typename traits::iterators iterators;
64 public:
65 typedef typename traits::difference_type difference_type;
66 typedef typename traits::value_type value_type;
67 typedef typename traits::pointer pointer;
68 typedef typename traits::reference reference;
69 typedef typename traits::iterator_category iterator_category;
70 private:
71 template <size_t... Is>
72 struct index_sequence;
73 public:
74 template <typename... Iterators2>
75 zip_iterator(const Iterators2&... iterators) : iContents{ iterators... }
76 {
77 }
78 public:
80 {
81 return reference_helper(std::make_index_sequence<sizeof...(Iterators)>());
82 }
84 {
85 pointer result;
86 set_pointer<0>(result);
87 return result;
88 }
89 self_type& operator++()
90 {
91 increment<0>();
92 return *this;
93 }
94 self_type operator++(int)
95 {
96 self_type old{ *this };
97 increment<0>();
98 return old;
99 }
100 self_type& operator--()
101 {
102 decrement<0>();
103 return *this;
104 }
105 self_type operator--(int)
106 {
107 self_type old{ *this };
108 decrement<0>();
109 return old;
110 }
111 difference_type operator-(const self_type& aOther) const
112 {
113 return std::get<0>(contents()) - std::get<0>(aOther.contents());
114 }
115 self_type operator+(difference_type aAmount) const
116 {
117 self_type result{ *this };
118 result.add<0>(aAmount);
119 return result;
120 }
121 self_type operator-(difference_type aAmount) const
122 {
123 self_type result{ *this };
124 result.subtract<0>(aAmount);
125 return result;
126 }
127 bool operator<(const self_type& aOther) const
128 {
129 return std::get<0>(contents()) < std::get<0>(aOther.contents());
130 }
131 bool operator==(const self_type& aOther) const
132 {
133 return std::get<0>(contents()) == std::get<0>(aOther.contents());
134 }
135 bool operator!=(const self_type& aOther) const
136 {
137 return std::get<0>(contents()) != std::get<0>(aOther.contents());
138 }
139 public:
140 const iterators& contents() const
141 {
142 return iContents;
143 }
144 private:
145 template <std::size_t Index>
146 void increment()
147 {
148 ++std::get<Index>(contents());
149 if constexpr (Index < std::tuple_size<iterators>::value - 1)
150 increment<Index + 1>();
151 }
152 template <std::size_t Index>
153 void decrement()
154 {
155 --std::get<Index>(contents());
156 if constexpr (Index < std::tuple_size<iterators>::value - 1)
157 decrement<Index + 1>();
158 }
159 template <std::size_t Index>
160 void add(difference_type aAmount)
161 {
162 std::get<Index>(contents()) += aAmount;
163 if constexpr (Index < std::tuple_size<iterators>::value - 1)
164 add<Index + 1>(aAmount);
165 }
166 template <std::size_t Index>
167 void subtract(difference_type aAmount)
168 {
169 std::get<Index>(contents()) -= aAmount;
170 if constexpr (Index < std::tuple_size<iterators>::value - 1)
171 subtract<Index + 1>(aAmount);
172 }
173 template <std::size_t... Is>
174 reference reference_helper(std::index_sequence<Is...>)
175 {
176 return reference_helper_2(*std::get<Is>(contents())...);
177 }
178 template <typename... References>
179 reference reference_helper_2(References&... aReferences)
180 {
181 return reference{ aReferences... };
182 }
183 template <std::size_t Index>
184 void set_pointer(pointer& aResult)
185 {
186 std::get<Index>(aResult) = &std::get<Index>(contents());
187 if constexpr (Index < std::tuple_size<iterators>::value - 1)
188 set_pointer<Index + 1>(aResult);
189 }
190 iterators& contents()
191 {
192 return iContents;
193 }
194 private:
195 iterators iContents;
196 };
197
198 template <typename... Iterators>
199 inline zip_iterator<Iterators...> make_zip_iterator(Iterators&&... iterators)
200 {
201 return zip_iterator<Iterators...>(std::forward<Iterators>(iterators)...);
202 }
203}
204
205namespace std
206{
207 template <typename... Iterators>
208 struct iterator_traits<neolib::zip_iterator<Iterators...>>
209 {
210 typedef typename neolib::zip_iterator_traits<Iterators...>::difference_type difference_type;
211 typedef typename neolib::zip_iterator_traits<Iterators...>::value_type value_type;
212 typedef typename neolib::zip_iterator_traits<Iterators...>::pointer pointer;
213 typedef typename neolib::zip_iterator_traits<Iterators...>::reference reference;
214 typedef typename neolib::zip_iterator_traits<Iterators...>::iterator_category iterator_category;
215 };
216
217 template <typename... Iterators>
219 {
220 auto temp = *a;
221 *a = *b;
222 *b = temp;
223 }
224}
self_type operator+(difference_type aAmount) const
traits::iterator_category iterator_category
const iterators & contents() const
traits::reference reference
self_type & operator--()
traits::pointer pointer
self_type & operator++()
traits::difference_type difference_type
traits::value_type value_type
bool operator!=(const self_type &aOther) const
self_type operator++(int)
self_type operator--(int)
bool operator<(const self_type &aOther) const
difference_type operator-(const self_type &aOther) const
zip_iterator(const Iterators2 &... iterators)
self_type operator-(difference_type aAmount) const
bool operator==(const self_type &aOther) const
zip_iterator< Iterators... > make_zip_iterator(Iterators &&... iterators)
Definition plf_hive.h:79
std::tuple< typename Iterators::pointer... > pointer
std::tuple< typename Iterators::value_type... > value_type
std::iterator_traits< typenamestd::tuple_element< 0, iterators >::type >::iterator_category iterator_category
std::tuple< Iterators... > iterators
std::tuple< typename Iterators::reference... > reference