Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
scoped-collection.hpp
Go to the documentation of this file.
1/*
2 SCOPED-COLLECTION.hpp - managing a fixed collection of noncopyable polymorphic objects
3
4 Copyright (C)
5 2012, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
60#ifndef LIB_SCOPED_COLLECTION_H
61#define LIB_SCOPED_COLLECTION_H
62
63
64#include "lib/error.hpp"
65#include "lib/nocopy.hpp"
66#include "lib/meta/trait.hpp"
67#include "lib/iter-adapter.hpp"
68
69#include <cstddef>
70#include <type_traits>
71
72
73namespace lib {
74
75 namespace error = lumiera::error;
76 using LERR_(INDEX_BOUNDS);
77 using LERR_(CAPACITY);
78
79
80
90 template
91 < class I
92 , size_t siz = sizeof(I)
93 >
95 : util::NonCopyable
96 {
97
98 public:
107 {
108 alignas(I) mutable
109 std::byte buf_[siz];
110
111 public:
112
113 I&
114 accessObj() const
115 {
116 return * std::launder (reinterpret_cast<I*> (&buf_));
117 }
118
119 void
121 {
122 accessObj().~I();
123 }
124
125
126
127
129 template<class TY, typename...ARGS>
130 TY&
131 create (ARGS&& ...args)
132 {
133 static_assert ( meta::is_Subclass<TY,I>()
134 && sizeof(TY) <= siz,
135 "ElementHolder buffer too small");
136
137 return *new(&buf_) TY (std::forward<ARGS> (args)...);
138 }
139 };
140
141
142
143
144
145
147 {
148 clear();
149 }
150
151 explicit
152 ScopedCollection (size_t maxElements)
153 : level_(0)
154 , capacity_(maxElements)
155 , elements_(new ElementHolder[maxElements])
156 { }
157
165 template<class CTOR>
166 ScopedCollection (size_t maxElements, CTOR builder)
167 : level_(0)
168 , capacity_(maxElements)
169 , elements_(new ElementHolder[maxElements])
170 {
171 populate_by (builder);
172 }
173
182 template<class TY>
183 ScopedCollection (size_t maxElements, void (TY::*builder) (ElementHolder&), TY * const instance)
184 : level_(0)
185 , capacity_(maxElements)
186 , elements_(new ElementHolder[maxElements])
187 {
188 populate_by (builder,instance);
189 }
190
191 /* == some pre-defined Builders == */
192
193 class FillAll;
194
195 template<typename TY>
196 class FillWith;
197
198 template<typename IT>
199 class PullFrom;
200
201 template<typename IT>
202 static PullFrom<IT>
203 pull (IT iter)
204 {
205 return PullFrom<IT> (iter);
206 }
207
208 void
210 {
211 REQUIRE (level_ <= capacity_, "Storage corrupted");
212
213 while (level_)
214 {
215 --level_;
216 try {
217 elements_[level_].destroy();
218 }
219 ERROR_LOG_AND_IGNORE (progress, "Clean-up of element in ScopedCollection")
220 }
221 }
222
224 void
226 try {
227 while (level_ < capacity_)
228 {
229 elements_[level_].template create<I>();
230 ++level_;
231 }
232 }
233 catch(...)
234 {
235 WARN (progress, "Failure while populating ScopedCollection. "
236 "All elements will be discarded");
237 clear();
238 throw;
239 }
240
248 template<class CTOR>
249 void
250 populate_by (CTOR builder)
251 try {
252 while (level_ < capacity_)
253 {
254 ElementHolder& storageFrame (elements_[level_]);
255 builder (storageFrame);
256 ++level_;
257 } }
258 catch(...)
259 {
260 WARN (progress, "Failure while populating ScopedCollection. "
261 "All elements will be discarded");
262 clear();
263 throw;
264 }
265
270 template<class TY>
271 void
272 populate_by (void (TY::*builder) (ElementHolder&), TY * const instance)
273 try {
274 while (level_ < capacity_)
275 {
276 ElementHolder& storageFrame (elements_[level_]);
277 (instance->*builder) (storageFrame);
278 ++level_;
279 } }
280 catch(...)
281 {
282 WARN (progress, "Failure while populating ScopedCollection. "
283 "All elements will be discarded");
284 clear();
285 throw;
286 }
287
288
289
293 I&
295 {
296 return emplace<I>();
297 }
298
299
304 template<class TY =I, typename...ARGS>
305 TY&
306 emplace (ARGS&& ...args)
307 {
308 __ensureSufficientCapacity();
309 TY& newElm = elements_[level_].template create<TY>(std::forward<ARGS> (args)...);
310 ++level_;
311 return newElm;
312 }
313
314
315
316 /* === Element access and iteration === */
317
318 I&
319 operator[] (size_t index) const
320 {
321 if (index < level_)
322 return elements_[index].accessObj();
323
324 throw error::Logic ("Attempt to access not (yet) existing object in ScopedCollection"
325 , LERR_(INDEX_BOUNDS));
326 }
327
328
329
332
333
334 iterator begin() { return iterator (this, _access_begin()); }
335 const_iterator begin() const { return const_iterator (this, _access_begin()); }
336 iterator end () { return iterator(); }
337 const_iterator end () const { return const_iterator(); }
338
339
340 size_t size () const { return level_; }
341 size_t capacity () const { return capacity_; }
342 bool empty () const { return 0 == level_; }
343
344
345 // use in standard range for loops...
346 friend iterator begin (ScopedCollection& sco) { return sco.begin(); }
347 friend const iterator begin (ScopedCollection const& sco){ return sco.begin(); }
348 friend iterator end (ScopedCollection& sco) { return sco.end(); }
349 friend const iterator end (ScopedCollection const& sco){ return sco.end(); }
350
351
352 private:
353 /* ==== Storage: heap allocated array of element buffers ==== */
354
355 typedef std::unique_ptr<ElementHolder[]> ElementStorage;
356
357 size_t level_;
358 size_t capacity_;
360
361
362
363 void
365 {
366 if (level_ >= capacity_)
367 throw error::State ("ScopedCollection exceeding the initially defined capacity"
368 , LERR_(CAPACITY));
369 }
370
371
372 /* ==== internal callback API for the iterator ==== */
373
378 friend void
379 iterNext (const ScopedCollection*, I* & pos)
380 {
381 ElementHolder* & storageLocation = reinterpret_cast<ElementHolder* &> (pos);
382 ++storageLocation;
383 }
384
385 friend void
386 iterNext (const ScopedCollection*, const I* & pos)
387 {
388 const ElementHolder* & storageLocation = reinterpret_cast<const ElementHolder* &> (pos);
389 ++storageLocation;
390 }
391
393 template<typename POS>
394 friend bool
395 checkPoint (const ScopedCollection* src, POS & pos)
396 {
397 REQUIRE (src);
398 if ((pos) && (pos < src->_access_end()))
399 return true;
400 else
401 {
402 pos = 0;
403 return false;
404 } }
405
406
407 I* _access_begin() const { return & elements_[0].accessObj(); }
408 I* _access_end() const { return & elements_[level_].accessObj(); }
409
410 };
411
412
413
414
415 /* === Supplement: pre-defined element builders === */
416
426 template<class I, size_t siz>
428 {
429 public:
430 void
432 {
433 storage.template create<I>();
434 }
435 };
436
437 template<class I, size_t siz>
438 template<typename TY>
440 {
441 public:
442 void
444 {
445 storage.template create<TY>();
446 }
447 };
448
458 template<class I, size_t siz>
459 template<typename IT>
461 {
463
465
466 public:
467 PullFrom (IT source)
468 : iter_(source)
469 { }
470
471 void
473 {
474 storage.template create<ElementType> (*iter_);
475 ++iter_;
476 }
477 };
478
479
480
481} // namespace lib
482#endif
Adapter for building an implementation of the »Lumiera Forward Iterator« concept.
Storage Frame to hold one Child object.
TY & create(ARGS &&...args)
place object of type TY, forwarding ctor arguments
fills the ScopedCollection with default constructed I-instances
fills the ScopedCollection with default constructed TY-instances
meta::ValueTypeBinding< IT >::value_type ElementType
A fixed collection of non-copyable polymorphic objects.
IterAdapter< const I *, const ScopedCollection * > const_iterator
friend iterator begin(ScopedCollection &sco)
IterAdapter< I *, const ScopedCollection * > iterator
const_iterator begin() const
friend const iterator begin(ScopedCollection const &sco)
I & emplaceElement()
push a new element of default type to the end of this container
friend const iterator end(ScopedCollection const &sco)
ScopedCollection(size_t maxElements, CTOR builder)
creating a ScopedCollection in RAII-style: The embedded elements will be created immediately.
friend bool checkPoint(const ScopedCollection *src, POS &pos)
Iteration-logic: detect iteration end.
ScopedCollection(size_t maxElements, void(TY::*builder)(ElementHolder &), TY *const instance)
variation of RAII-style: using a builder function, which is a member of some object.
static PullFrom< IT > pull(IT iter)
fills by copy-constructing values pulled from the iterator IT
TY & emplace(ARGS &&...args)
push new entry at the end of this container and build object of type TY in place there
friend void iterNext(const ScopedCollection *, I *&pos)
Iteration-logic: switch to next position.
friend iterator end(ScopedCollection &sco)
ScopedCollection(size_t maxElements)
void populate_by(void(TY::*builder)(ElementHolder &), TY *const instance)
variation of element initialisation, invoking a member function of some manager object for each colle...
void populate_by(CTOR builder)
init all elements at once, invoking a builder functor for each.
std::unique_ptr< ElementHolder[]> ElementStorage
void populate()
init all elements default constructed
const_iterator end() const
friend void iterNext(const ScopedCollection *, const I *&pos)
Any copy and copy construction prohibited.
Definition nocopy.hpp:38
Lumiera error handling (C++ interface).
#define ERROR_LOG_AND_IGNORE(_FLAG_, _OP_DESCR_)
convenience shortcut for a sequence of catch blocks just logging and consuming an error.
Definition error.hpp:267
#define LERR_(_NAME_)
Definition error.hpp:45
Helper template(s) for creating Lumiera Forward Iterators.
RefTraits< TY >::Value value_type
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
Implementation namespace for support and library code.
LumieraError< LERR_(STATE)> State
Definition error.hpp:209
LumieraError< LERR_(LOGIC)> Logic
Definition error.hpp:207
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Helpers for type detection, type rewriting and metaprogramming.