neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
generic_iterator.hpp
Go to the documentation of this file.
1// generic_iterator.hpp
2/*
3 * Copyright (c) 2007 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 <type_traits>
40#include <boost/aligned_storage.hpp>
41
42namespace neolib
43{
45 {
46 public:
47 typedef std::bidirectional_iterator_tag iterator_category;
48 typedef std::ptrdiff_t difference_type;
49 public:
50 struct wrong_iterator_type : std::logic_error { wrong_iterator_type() : std::logic_error("neolib::generic_iterator::wrong_iterator_type") {} };
51 protected:
53 {
54 public:
55 virtual ~i_wrapper() = default;
56 public:
57 virtual i_wrapper* clone() const = 0;
58 virtual i_wrapper* clone(void* aStorage) const = 0;
59 public:
60 virtual i_wrapper& operator++() = 0;
61 virtual i_wrapper& operator--() = 0;
62 virtual i_wrapper& operator+=(difference_type aDelta) = 0;
63 virtual i_wrapper& operator-=(difference_type aDelta) = 0;
64 virtual bool operator==(const i_wrapper& aOther) const = 0;
65 virtual bool operator!=(const i_wrapper& aOther) const = 0;
66 };
67 template <typename Iterator>
68 class wrapper : public i_wrapper
69 {
70 public:
71 typedef typename std::iterator_traits<Iterator>::pointer pointer;
72 typedef typename std::iterator_traits<Iterator>::reference reference;
73 public:
74 wrapper(Iterator aIterator) : iIterator(aIterator)
75 {
76 }
77 public:
78 i_wrapper* clone() const override
79 {
80 return new wrapper(*this);
81 }
82 i_wrapper* clone(void* aStorage) const override
83 {
84 return new (aStorage)wrapper(*this);
85 }
86 public:
87 Iterator get() const
88 {
89 return iIterator;
90 }
91 public:
93 {
94 return iIterator.operator*();
95 }
97 {
98 return iIterator.operator->();
99 }
100 public:
101 wrapper& operator++() override
102 {
103 iIterator.operator++();
104 return *this;
105 }
106 wrapper& operator--() override
107 {
108 iIterator.operator--();
109 return *this;
110 }
112 {
113 std::advance(iIterator, aDelta);
114 return *this;
115 }
117 {
118 std::advance(iIterator, -aDelta);
119 return *this;
120 }
121 bool operator==(const i_wrapper& aOther) const override
122 {
123 return iIterator == dynamic_cast<const wrapper&>(aOther).iIterator;
124 }
125 bool operator!=(const i_wrapper& aOther) const override
126 {
127 return !(*this == aOther);
128 }
129 private:
130 Iterator iIterator;
131 };
132 public:
134 iWrappedIterator{ nullptr },
135 iInPlace{ false }
136 {
137 }
139 iWrappedIterator{ aOther.iInPlace ? aOther.iWrappedIterator->clone(iIteratorStorage) : aOther.iWrappedIterator->clone() },
140 iInPlace{ aOther.iInPlace }
141 {
142 }
144 {
145 if (iInPlace)
146 iWrappedIterator->~i_wrapper();
147 else
148 delete iWrappedIterator;
149 }
150 public:
152 {
153 (*iWrappedIterator).operator++();
154 return *this;
155 }
157 {
158 (*iWrappedIterator).operator--();
159 return *this;
160 }
162 {
163 generic_iterator old = *this;
164 (*iWrappedIterator).operator++();
165 return old;
166 }
168 {
169 generic_iterator old = *this;
170 (*iWrappedIterator).operator--();
171 return old;
172 }
174 {
175 (*iWrappedIterator).operator+=(aDelta);
176 return *this;
177 }
179 {
180 (*iWrappedIterator).operator-=(aDelta);
181 return *this;
182 }
184 {
185 generic_iterator result = *this;
186 (*result.iWrappedIterator).operator+=(aDelta);
187 return result;
188 }
190 {
191 generic_iterator result = *this;
192 (*result.iWrappedIterator).operator-=(aDelta);
193 return result;
194 }
195 bool operator==(const generic_iterator& aOther) const
196 {
197 return (*iWrappedIterator).operator==(*aOther.iWrappedIterator);
198 }
199 bool operator!=(const generic_iterator& aOther) const
200 {
201 return (*iWrappedIterator).operator!=(*aOther.iWrappedIterator);
202 }
203 public:
204 template <typename Iterator>
205 bool is_one_of() const
206 {
207 return dynamic_cast<const wrapper<Iterator>*>(&wrapped_iterator()) != nullptr;
208 }
209 template <typename Iterator1, typename Iterator2, typename... Rest>
210 bool is_one_of() const
211 {
212 return dynamic_cast<const wrapper<Iterator1>*>(&wrapped_iterator()) != nullptr || is_one_of<Iterator2, Rest...>();
213 }
214 template <typename Iterator>
215 Iterator get() const
216 {
217 if (is_one_of<Iterator>())
218 {
219 return static_cast<Iterator>(dynamic_cast<const wrapper<Iterator>&>(wrapped_iterator()).get());
220 }
221 else
222 {
223 throw wrong_iterator_type();
224 }
225 }
226 template <typename Iterator, typename NextIterator, typename... Rest>
227 Iterator get() const
228 {
229 if (is_one_of<NextIterator>())
230 {
231 return static_cast<Iterator>(dynamic_cast<const wrapper<NextIterator>&>(wrapped_iterator()).get());
232 }
233 else
234 {
235 return get<Iterator, Rest...>();
236 }
237 }
238 protected:
239 template <typename Wrapper>
240 void construct(const Wrapper& aWrapper)
241 {
242 construct2(aWrapper, sizeof(Wrapper) <= sizeof(iIteratorStorage));
243 }
244 template <typename Wrapper>
245 void construct2(const Wrapper& aWrapper, bool aInPlace)
246 {
247 if (aInPlace)
248 {
249 iWrappedIterator = new(iIteratorStorage) Wrapper{ aWrapper };
250 iInPlace = true;
251 }
252 else
253 {
254 iWrappedIterator = new Wrapper{ aWrapper };
255 iInPlace = false;
256 }
257 }
259 {
260 return *iWrappedIterator;
261 }
263 {
264 return *iWrappedIterator;
265 }
266 private:
267 union
268 {
269 std::aligned_storage<sizeof(void*) * 4>::type iPad;
270 char iIteratorStorage[sizeof(void*) * 4];
271 };
272 i_wrapper* iWrappedIterator;
273 bool iInPlace;
274 };
275
276 template <typename Iterator>
278 {
279 public:
280 typedef typename std::iterator_traits<Iterator>::value_type value_type;
281 typedef typename std::iterator_traits<Iterator>::pointer pointer;
282 typedef typename std::iterator_traits<Iterator>::reference reference;
283 typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
284 public:
286 {
287 construct(wrapper<Iterator>(aIterator));
288 }
294 generic_iterator(aOther)
295 {
296 }
297 public:
299 {
300 wrapped_iterator().operator++();
301 return *this;
302 }
304 {
305 wrapped_iterator().operator--();
306 return *this;
307 }
309 {
311 wrapped_iterator().operator++();
312 return old;
313 }
315 {
316 generic_iterator old = *this;
317 wrapped_iterator().operator--();
318 return old;
319 }
321 {
322 wrapped_iterator().operator+=(aDelta);
323 return *this;
324 }
326 {
327 wrapped_iterator().operator-=(aDelta);
328 return *this;
329 }
331 {
332 return wrapped_iterator().operator+(aDelta);
333 }
335 {
336 return wrapped_iterator().operator-(aDelta);
337 }
339 {
340 return wrapped_iterator().operator*();
341 }
343 {
344 return wrapped_iterator().operator->();
345 }
346 bool operator==(const specialized_generic_iterator& aOther) const
347 {
348 return wrapped_iterator().operator==(aOther.wrapped_iterator());
349 }
350 bool operator!=(const specialized_generic_iterator& aOther) const
351 {
352 return wrapped_iterator().operator!=(aOther.wrapped_iterator());
353 }
354 };
355
356 template <typename Iterator>
358 {
359 return specialized_generic_iterator<Iterator>{ aIterator };
360 }
361}
virtual i_wrapper * clone(void *aStorage) const =0
virtual i_wrapper & operator+=(difference_type aDelta)=0
virtual i_wrapper & operator--()=0
virtual i_wrapper * clone() const =0
virtual i_wrapper & operator++()=0
virtual i_wrapper & operator-=(difference_type aDelta)=0
virtual bool operator!=(const i_wrapper &aOther) const =0
virtual bool operator==(const i_wrapper &aOther) const =0
i_wrapper * clone() const override
std::iterator_traits< Iterator >::reference reference
std::iterator_traits< Iterator >::pointer pointer
wrapper & operator+=(difference_type aDelta) override
bool operator==(const i_wrapper &aOther) const override
wrapper & operator-=(difference_type aDelta) override
i_wrapper * clone(void *aStorage) const override
bool operator!=(const i_wrapper &aOther) const override
generic_iterator(const generic_iterator &aOther)
generic_iterator & operator--()
void construct(const Wrapper &aWrapper)
bool operator!=(const generic_iterator &aOther) const
const i_wrapper & wrapped_iterator() const
generic_iterator & operator-=(difference_type aDelta)
generic_iterator operator+(difference_type aDelta)
std::aligned_storage< sizeof(void *) *4 >::type iPad
generic_iterator & operator++()
generic_iterator & operator+=(difference_type aDelta)
std::bidirectional_iterator_tag iterator_category
generic_iterator operator--(int)
generic_iterator operator++(int)
void construct2(const Wrapper &aWrapper, bool aInPlace)
generic_iterator operator-(difference_type aDelta)
bool operator==(const generic_iterator &aOther) const
char iIteratorStorage[sizeof(void *) *4]
specialized_generic_iterator operator+(difference_type aDelta)
specialized_generic_iterator & operator--()
std::iterator_traits< Iterator >::reference reference
specialized_generic_iterator(const specialized_generic_iterator &aOther)
std::iterator_traits< Iterator >::value_type value_type
bool operator!=(const specialized_generic_iterator &aOther) const
specialized_generic_iterator operator++(int)
specialized_generic_iterator & operator+=(difference_type aDelta)
specialized_generic_iterator & operator-=(difference_type aDelta)
std::iterator_traits< Iterator >::pointer pointer
specialized_generic_iterator operator-(difference_type aDelta)
std::iterator_traits< Iterator >::difference_type difference_type
specialized_generic_iterator & operator++()
bool operator==(const specialized_generic_iterator &aOther) const
specialized_generic_iterator operator--(int)
specialized_generic_iterator(const generic_iterator &aOther)
specialized_generic_iterator< Iterator > make_generic_iterator(Iterator aIterator)
void advance(it_type &it, const distance_type distance)
Definition plf_hive.h:81