neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
any_iterator.hpp
Go to the documentation of this file.
1// any_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 <stdexcept>
39#include <typeinfo>
40
41namespace neolib
42{
43 class any_iterator;
44
46 {
47 // types
48 public:
49 struct bad_cast : public std::logic_error { bad_cast() : std::logic_error("neolib::any_const_iterator::bad_cast") {} };
50 struct is_empty : public std::logic_error { is_empty() : std::logic_error("neolib::any_const_iterator::is_empty") {} };
51 private:
52 class holder_base
53 {
54 // construction
55 public:
56 virtual ~holder_base() = default;
57 // operations
58 public:
59 virtual void operator++() = 0;
60 virtual void operator--() = 0;
61 virtual bool operator==(const any_const_iterator& aOther) const = 0;
62 template <typename T>
63 operator const T&() const
64 {
65 if (typeid(T) != type())
66 throw bad_cast();
67 return *static_cast<const T*>(ptr());
68 }
69 template <typename T>
70 operator T&()
71 {
72 if (typeid(T) != type())
73 throw bad_cast();
74 return *static_cast<T*>(ptr());
75 }
76 template <typename T>
77 bool is() const { return typeid(T) == type(); }
78 virtual holder_base* clone(any_const_iterator& aOwner) const = 0;
79 // implementation
80 private:
81 virtual const std::type_info& type() const = 0;
82 virtual const void* ptr() const = 0;
83 virtual void* ptr() = 0;
84 };
85 template <typename T>
86 class holder : public holder_base
87 {
88 // construction
89 public:
90 holder(const T& aObject) : iObject(aObject) {}
91 // implementation
92 private:
93 virtual void operator++() { ++iObject; }
94 virtual void operator--() { --iObject; }
95 virtual bool operator==(const any_const_iterator& aOther) const
96 {
97 return iObject == static_cast<const T&>(aOther);
98 }
99 virtual holder_base* clone(any_const_iterator& aOwner) const { return aOwner.create(iObject); }
100 virtual const std::type_info& type() const { return typeid(T); }
101 virtual const void* ptr() const { return &iObject; }
102 virtual void* ptr() { return &iObject; }
103 // attributes
104 private:
105 T iObject;
106 };
107 // construction
108 public:
109 any_const_iterator() : iHolder(nullptr) {}
110 template <typename T>
111 any_const_iterator(const T& aObject) : iHolder(create(aObject)) {}
112 any_const_iterator(const any_const_iterator& aOther) : iHolder(aOther.iHolder ? aOther.iHolder->clone(*this) : nullptr) {}
113 ~any_const_iterator() { destroy(); }
115 {
116 destroy();
117 if (aOther.iHolder)
118 iHolder = aOther.iHolder->clone(*this);
119 return *this;
120 }
121 private:
122 any_const_iterator(const any_iterator&); // not allowed, use any_const_iterator_cast instead
123 // operations
124 public:
126 {
127 if (empty())
128 throw is_empty();
129 ++(*iHolder);
130 return *this;
131 }
133 {
134 if (empty())
135 throw is_empty();
136 any_const_iterator ret = *this;
137 ++ret;
138 return ret;
139 }
141 {
142 if (empty())
143 throw is_empty();
144 --(*iHolder);
145 return *this;
146 }
148 {
149 if (empty())
150 throw is_empty();
151 any_const_iterator ret = *this;
152 --ret;
153 return ret;
154 }
155 friend bool operator==(const any_const_iterator& aLeft, const any_const_iterator& aRight)
156 {
157 if (aLeft.empty())
158 throw is_empty();
159 return aLeft.iHolder->operator==(aRight);
160 }
161 friend bool operator!=(const any_const_iterator& aLeft, const any_const_iterator& aRight)
162 {
163 return !(aLeft == aRight);
164 }
165 template <typename T>
166 operator const T&() const { if (empty()) throw bad_cast(); return *iHolder; }
167 template <typename T>
168 operator T&() { if (empty()) throw bad_cast(); return *iHolder; }
169 template <typename T>
170 bool is() const { return iHolder && iHolder->is<T>(); }
171 bool something() const { return iHolder != nullptr; }
172 bool empty() const { return !something(); }
173 void reset() { destroy(); }
174 // implementation
175 private:
176 template <typename T>
177 holder_base* create(const T& aData)
178 {
179 if (sizeof(T) <= sizeof(iSpace.iBytes))
180 iHolder = new (iSpace.iBytes) holder<T>(aData);
181 else
182 iHolder = new holder<T>(aData);
183 return iHolder;
184 }
185 void destroy()
186 {
187 if (iHolder == reinterpret_cast<holder_base*>(iSpace.iBytes))
188 iHolder->~holder_base();
189 else
190 delete iHolder;
191 iHolder = nullptr;
192 }
193 // attributes
194 private:
195 holder_base* iHolder;
196 union
197 {
198 std::max_align_t alignTo;
199 char iBytes[64];
200 } iSpace;
201 };
202
204 {
205 // types
206 public:
207 struct bad_cast : public std::logic_error { bad_cast() : std::logic_error("neolib::any_iterator::bad_cast") {} };
208 struct is_empty : public std::logic_error { is_empty() : std::logic_error("neolib::any_iterator::is_empty") {} };
209 private:
210 class holder_base
211 {
212 // construction
213 public:
214 virtual ~holder_base() = default;
215 // operations
216 public:
217 virtual void operator++() = 0;
218 virtual void operator--() = 0;
219 virtual bool operator==(const any_iterator& aOther) const = 0;
220 template <typename T>
221 operator const T&() const
222 {
223 if (typeid(T) != type())
224 throw bad_cast();
225 return *static_cast<const T*>(ptr());
226 }
227 template <typename T>
228 operator T&()
229 {
230 if (typeid(T) != type())
231 throw bad_cast();
232 return *static_cast<T*>(ptr());
233 }
234 template <typename T>
235 bool is() const { return typeid(T) == type(); }
236 virtual holder_base* clone(any_iterator& aOwner) const = 0;
237 // implementation
238 private:
239 virtual const std::type_info& type() const = 0;
240 virtual const void* ptr() const = 0;
241 virtual void* ptr() = 0;
242 };
243 template <typename T>
244 class holder : public holder_base
245 {
246 // construction
247 public:
248 holder(const T& aObject) : iObject(aObject) {}
249 // implementation
250 private:
251 virtual void operator++() { ++iObject; }
252 virtual void operator--() { --iObject; }
253 virtual bool operator==(const any_iterator& aOther) const
254 {
255 return iObject == static_cast<const T&>(aOther);
256 }
257 virtual holder_base* clone(any_iterator& aOwner) const { return aOwner.create(iObject); }
258 virtual const std::type_info& type() const { return typeid(T); }
259 virtual const void* ptr() const { return &iObject; }
260 virtual void* ptr() { return &iObject; }
261 // attributes
262 private:
263 T iObject;
264 };
265 // construction
266 public:
267 any_iterator() : iHolder(nullptr) {}
268 template <typename T>
269 any_iterator(const T& aObject) : iHolder(new holder<T>(aObject)) {}
270 any_iterator(const any_iterator& aOther) : iHolder(aOther.iHolder ? aOther.iHolder->clone(*this) : nullptr) {}
271 ~any_iterator() { destroy(); }
273 {
274 destroy();
275 if (aOther.iHolder)
276 iHolder = aOther.iHolder->clone(*this);
277 return *this;
278 }
279 // operations
280 public:
282 {
283 if (empty())
284 throw is_empty();
285 ++(*iHolder);
286 return *this;
287 }
289 {
290 if (empty())
291 throw is_empty();
292 any_iterator ret = *this;
293 ++ret;
294 return ret;
295 }
297 {
298 if (empty())
299 throw is_empty();
300 --(*iHolder);
301 return *this;
302 }
304 {
305 if (empty())
306 throw is_empty();
307 any_iterator ret = *this;
308 --ret;
309 return ret;
310 }
311 friend bool operator==(const any_iterator& aLeft, const any_iterator& aRight)
312 {
313 if (aLeft.empty())
314 throw is_empty();
315 return aLeft.iHolder->operator==(aRight);
316 }
317 friend bool operator!=(const any_iterator& aLeft, const any_iterator& aRight)
318 {
319 return !(aLeft == aRight);
320 }
321 template <typename T>
322 operator const T&() const { if (empty()) throw bad_cast(); return *iHolder; }
323 template <typename T>
324 operator T&() { if (empty()) throw bad_cast(); return *iHolder; }
325 template <typename T>
326 bool is() const { return iHolder && iHolder->is<T>(); }
327 bool something() const { return iHolder != nullptr; }
328 bool empty() const { return !something(); }
329 void reset() { destroy(); }
330 // implementation
331 private:
332 template <typename T>
333 holder_base* create(const T& aData)
334 {
335 if (sizeof(T) <= sizeof(iSpace.iBytes))
336 iHolder = new (iSpace.iBytes) holder<T>(aData);
337 else
338 iHolder = new holder<T>(aData);
339 return iHolder;
340 }
341 void destroy()
342 {
343 if (iHolder == reinterpret_cast<holder_base*>(iSpace.iBytes))
344 iHolder->~holder_base();
345 else
346 delete iHolder;
347 iHolder = nullptr;
348 }
349 // attributes
350 private:
351 holder_base* iHolder;
352 union
353 {
354 std::max_align_t alignTo;
355 char iBytes[64];
356 } iSpace;
357 };
358
359 template <typename Source, typename Target>
361 {
362 return static_cast<Target>(static_cast<const Source&>(aSource));
363 }
364}
365
any_const_iterator operator++(int)
any_const_iterator & operator=(const any_const_iterator &aOther)
any_const_iterator & operator++()
friend bool operator==(const any_const_iterator &aLeft, const any_const_iterator &aRight)
any_const_iterator & operator--()
any_const_iterator operator--(int)
friend bool operator!=(const any_const_iterator &aLeft, const any_const_iterator &aRight)
any_const_iterator(const T &aObject)
any_const_iterator(const any_const_iterator &aOther)
std::max_align_t alignTo
any_iterator & operator--()
any_iterator operator++(int)
friend bool operator!=(const any_iterator &aLeft, const any_iterator &aRight)
friend bool operator==(const any_iterator &aLeft, const any_iterator &aRight)
any_iterator(const T &aObject)
any_iterator(const any_iterator &aOther)
any_iterator & operator=(const any_iterator &aOther)
any_iterator & operator++()
any_iterator operator--(int)
any_const_iterator any_const_iterator_cast(any_iterator aSource)