Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
iter-adapter-stl.hpp
Go to the documentation of this file.
1/*
2 ITER-ADAPTER-STL.hpp - helpers for building simple forward iterators
3
4 Copyright (C)
5 2010, 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
31#ifndef LIB_ITER_ADAPTER_STL_H
32#define LIB_ITER_ADAPTER_STL_H
33
34
35#include "lib/iter-adapter.hpp"
37
38#include <vector>
39
40
41namespace lib {
42namespace iter_stl {
43
48 template<typename IT>
50 {
51 public:
52 using value_type = IT::value_type;
53 using reference = IT::reference;
54 using pointer = IT::pointer;
55
56 private:
57 IT i_;
59
60 void memorise() { if (i_) prev_ = &(*i_); }
61
62 public:
63 DistinctIter() : i_(), prev_() { }
64 DistinctIter(IT const& i) : i_(i),prev_() { memorise(); }
65
66 pointer operator->() const { return i_; }
67 reference operator*() const { return *i_; }
68 bool isValid() const { return i_; }
69
70 explicit
71 operator bool() const
72 {
73 return bool{i_};
74 }
75
76
79 {
80 do ++i_;
81 while (i_ and prev_ and *prev_ == *i_ );
82 memorise();
83 return *this;
84 }
85
86 friend bool operator== (DistinctIter const& i1, DistinctIter const& i2) { return i1.i_ == i2.i_; }
87 friend bool operator!= (DistinctIter const& i1, DistinctIter const& i2) { return i1.i_ != i2.i_; }
88 };
89
90
91
96 template<typename DEF>
97 struct WrappedStlIter : DEF
98 {
99 using Iter = DEF::Iter;
100 using reference = DEF::reference;
101 using pointer = DEF::pointer;
102
103
105 WrappedStlIter(Iter const& i) : i_(i) { }
106
107 pointer operator->() const { return DEF::get(i_); }
108 reference operator*() const { return *(DEF::get(i_)); }
109
110 WrappedStlIter& operator++() { ++i_; return *this; }
111
112 friend bool operator== (WrappedStlIter const& i1, WrappedStlIter const& i2) { return i1.i_ == i2.i_; }
113 friend bool operator!= (WrappedStlIter const& i1, WrappedStlIter const& i2) { return i1.i_ != i2.i_; }
114
115 private:
116 mutable Iter i_;
117 };
118
119
120 /* -- customisations for building concrete wrappers -- */
121
126 template<typename IT>
128 {
129 using Iter = IT;
130 using value_type = IT::value_type;
131 using reference = IT::reference;
132 using pointer = IT::pointer;
133
134 static Iter get (Iter& it) { return & (*it); }
135 };
136
141 template<typename IT>
143 {
144 using Iter = IT;
145 using value_type = IT::value_type::first_type;
148
149 static pointer get (Iter& it) { return & (it->first); }
150 };
151
156 template<typename IT>
158 {
159 using Iter = IT;
160 using value_type = IT::value_type::second_type;
163
164 static pointer get (Iter& it) { return & (it->second); }
165 };
166
167 template<typename IT>
169 {
170 using Iter = IT;
171 using value_type = const IT::value_type::second_type;
172 using reference = const value_type &;
173 using pointer = const value_type *;
174
175 static pointer get (Iter& it) { return & (it->second); }
176 };
177
178
179
180
181
182
183 namespace { // traits and helpers...
184
185 template<class MAP>
187 {
188 using Key = MAP::value_type::first_type;
189 using Val = MAP::value_type::second_type;
190 using Itr = MAP::iterator;
191 };
192
193 template<class MAP>
194 struct _MapTypeSelector<const MAP>
195 {
196 using Key = MAP::value_type::first_type;
197 using Val = MAP::value_type::second_type const;
198 using Itr = MAP::const_iterator;
199 };
200
202 template<class IT, typename SEL>
208
210 template<class IT, typename SEL>
211 struct _MapSubSelector<IT, SEL const&>
212 {
213 using PickKey = WrappedStlIter< Wrapped_PickKey<IT>>; // Key is always const for maps
215 };
216
217
218
219 template<class MAP>
235
236
237 template<class IT>
239 {
240 using EntryIter = IT;
241
242 using KeyType = EntryIter::value_type::first_type;
243 using ValType = EntryIter::value_type::second_type;
244
245 using DetectConst = EntryIter::reference;
248
251
253 };
254
255
256
257 template<class SEQ>
258 struct _SeqT
259 {
260 using Iter = SEQ::iterator;
264 };
265
266 template<class SEQ>
267 struct _SeqT<const SEQ>
268 {
269 using Iter = SEQ::const_iterator;
273 };
274
275 }//(End) traits/helpers
276
277
278
279
283 template<class CON>
284 inline _SeqT<CON>::Range
285 eachElm (CON& coll)
286 {
287 using Range = _SeqT<CON>::Range;
288 return Range (coll.begin(), coll.end());
289 }
290
291
295 template<class CON>
296 inline _SeqT<CON>::Addrs
297 eachAddress (CON& coll)
298 {
299 using Addresses = _SeqT<CON>::Addrs;
300 return Addresses (eachElm (coll));
301 }
302
303
307 template<class MAP>
308 inline _MapT<MAP>::KeyIter
309 eachKey (MAP& map)
310 {
311 using Range = _MapT<MAP>::KeyIter;
312 using PickKey = _MapT<MAP>::PickKeyIter;
313
314 return Range (PickKey (map.begin()), PickKey (map.end()));
315 }
316
317
321 template<class IT>
322 inline _MapIterT<IT>::KeyIter
323 eachKey (IT const& begin, IT const& end)
324 {
325 using Range = _MapIterT<IT>::KeyIter;
326 using PickKey = _MapIterT<IT>::PickKeyIter;
327
328 return Range (PickKey (begin), PickKey (end));
329 }
330
331
335 template<class MAP>
336 inline _MapT<MAP>::ValIter
337 eachVal (MAP& map)
338 {
339 using Range = _MapT<MAP>::ValIter;
340 using PickVal = _MapT<MAP>::PickValIter;
341
342 return Range (PickVal (map.begin()), PickVal (map.end()));
343 }
344
345
349 template<class IT>
350 inline _MapIterT<IT>::ValIter
351 eachVal (IT const& begin, IT const& end)
352 {
353 using Range = _MapIterT<IT>::ValIter;
354 using PickVal = _MapIterT<IT>::PickValIter;
355
356 return Range (PickVal (begin), PickVal (end));
357 }
358
359
363 template<class SEQ>
364 inline _SeqT<SEQ>::DistinctVals
365 eachDistinct (SEQ& seq)
366 {
367 using Range = _SeqT<SEQ>::Range;
368 using DistinctValues = _SeqT<SEQ>::DistinctVals;
369
370 return DistinctValues (Range (seq.begin(), seq.end()));
371 }
372
373
378 template<class MAP>
379 inline _MapT<MAP>::DistinctKeys
381 {
382 return typename _MapT<MAP>::DistinctKeys (eachKey (map));
383 }
384
385
390 template<class MMAP, typename KEY>
391 inline _MapT<MMAP>::ValIter
392 eachValForKey (MMAP& multimap, KEY key)
393 {
394 using Pos = _MapT<MMAP>::EntryIter;
395 using Range = _MapT<MMAP>::ValIter;
396 using PickVal = _MapT<MMAP>::PickValIter;
397
398 std::pair<Pos,Pos> valRange = multimap.equal_range (key);
399
400 return Range (PickVal{valRange.first}, PickVal{valRange.second});
401 }
402
403
404
405
413 template<typename VAL>
415 {
416 using Sequence = std::vector<VAL>;
417
418 mutable
420 size_t pos_ = 0;
421
422
423 public:
426
431 template<class IT>
432 IterSnapshot (IT&& src)
433 {
434 for ( ; src; ++src)
435 buffer_.emplace_back (*src);
436 }
437
442 template<class IT>
443 IterSnapshot (IT const& src)
444 {
445 for (IT copy{src}; copy; ++copy)
446 buffer_.emplace_back (*copy);
447 }
448
450 template<class IT>
451 IterSnapshot (IT&& pos, IT const& end)
452 {
453 for ( ; pos!=end; ++pos)
454 buffer_.emplace_back (*pos);
455 }
456
458 template<class IT>
459 IterSnapshot (IT const& begin, IT const& end)
460 {
461 for (IT pos{begin}; pos!=end; ++pos)
462 buffer_.emplace_back (*pos);
463 }
464
466 IterSnapshot(IterSnapshot const&) = default;
469
470 explicit
471 operator bool() const
472 {
473 return isValid();
474 }
475
476 size_t
477 size() const
478 {
479 return buffer_.size();
480 }
481
482
483
484 /* === lumiera forward iterator concept === */
485
486 using pointer = VAL*;
487 using reference = VAL&;
488 using value_type = VAL ;
489
491 operator*() const
492 {
493 _maybe_throw();
494 return buffer_[pos_];
495 }
496
497 pointer
499 {
500 _maybe_throw();
501 return &buffer_[pos_];
502 }
503
506 {
507 _maybe_throw();
508 ++pos_;
509 return *this;
510 }
511
512 bool
513 isValid () const
514 {
515 return pos_ < buffer_.size();
516 }
517
518 bool
519 empty () const
520 {
521 return not isValid();
522 }
523
525
526
527
529 friend bool
531 {
532 return (s1.empty() and s2.empty())
533 or (s1.isValid() and s2.isValid()
534 and s1.pos_ == s2.pos_
535 and s1.buffer_ == s2.buffer_
536 );
537 }
538
539 friend bool
540 operator!= (IterSnapshot const& snap1, IterSnapshot const& snap2)
541 {
542 return not (snap1 == snap2);
543 }
544
545
546 private:
547 void
549 {
550 if (!isValid())
551 _throwIterExhausted();
552 }
553 };
554
555 namespace {
556 template<class CON>
558 }
559
560
561
567 template<class CON>
568 inline ContentSnapshot<CON>
569 snapshot(CON const& con)
570 {
571 return ContentSnapshot<CON>{begin(con), end(con)};
572 }
573
577 template<class IT>
578 inline ContentSnapshot<IT>
580 {
581 return ContentSnapshot<IT>{ii};
582 }
583
593 template<class VAL>
595 snapshot(std::initializer_list<VAL> const&& ili)
596 {
597 using OnceIter = iter_stl::IterSnapshot<VAL>;
598 return OnceIter(begin(ili), end(ili));
599 }
600
601
602}} // namespace lib::iter_stl
603#endif
wrapper for an existing Iterator type to expose the address of each value yielded.
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
Helper to filter repeated values from a wrapped iterator (both STL or Lumiera)
friend bool operator!=(DistinctIter const &i1, DistinctIter const &i2)
friend bool operator==(DistinctIter const &i1, DistinctIter const &i2)
materialised iterator contents.
IterSnapshot()
create empty snapshot
IterSnapshot(IT &&pos, IT const &end)
take snapshot by consuming a STL iterator
IterSnapshot(IterSnapshot &&)=default
IterSnapshot(IT const &begin, IT const &end)
take snapshot from STL iterator
IterSnapshot(IT const &src)
build snapshot from a copy of the Lumiera Iterator
IterSnapshot & operator=(IterSnapshot const &)=default
IterSnapshot(IT &&src)
take snapshot by discharging the given Lumiera Forward iterator
friend bool operator!=(IterSnapshot const &snap1, IterSnapshot const &snap2)
IterSnapshot(IterSnapshot const &)=default
friend bool operator==(IterSnapshot const &s1, IterSnapshot const &s2)
equality is based first on the valid state (to support pos != end) and then on the actual position an...
Extension adapter for Lumiera Forward Iterators to dereference any pointer values automatically.
Helper template(s) for creating Lumiera Forward Iterators.
#define ENABLE_USE_IN_STD_RANGE_FOR_LOOPS(ITER)
use a given Lumiera Forward Iterator in standard "range for loops"
IterSnapshot< typename CON::value_type > ContentSnapshot
_MapSubSelector< EntryIter, DetectConst >::PickKey PickKeyIter
_MapSubSelector< EntryIter, DetectConst >::PickVal PickValIter
helper to access the parts of the pair values correctly...
_MapT< MAP >::DistinctKeys eachDistinctKey(MAP &map)
ContentSnapshot< CON > snapshot(CON const &con)
Take a snapshot of the given STL compliant container.
_SeqT< CON >::Range eachElm(CON &coll)
ContentSnapshot< IT > dischargeToSnapshot(IT &ii)
Take a snapshot of the given LumieraIterator, which is thereby consumed.
_MapT< MAP >::KeyIter eachKey(MAP &map)
_MapT< MMAP >::ValIter eachValForKey(MMAP &multimap, KEY key)
_SeqT< SEQ >::DistinctVals eachDistinct(SEQ &seq)
build a Lumiera Forward Iterator to suppress any repetitions in the given sequence.
_MapT< MAP >::ValIter eachVal(MAP &map)
_SeqT< CON >::Addrs eachAddress(CON &coll)
Implementation namespace for support and library code.
helper baseclass to simplify defining customised wrapped STL iterators
friend bool operator!=(WrappedStlIter const &i1, WrappedStlIter const &i2)
friend bool operator==(WrappedStlIter const &i1, WrappedStlIter const &i2)
Wrapped-Iter-Policy: forwarding directly with typing retained unaltered.
const IT::value_type::second_type value_type
Wrapped-Iter-Policy: picking the key part of a pair iterator (map or multimap).
IT::value_type::first_type value_type
Wrapped-Iter-Policy: picking the value part of a pair iterator (map or multimap).
IT::value_type::second_type value_type