Lumiera  0.pre.03
»edit your freedom«
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 
41 namespace lib {
42 namespace iter_stl {
43 
48  template<typename IT>
50  {
51  public:
52  using value_type = typename IT::value_type;
53  using reference = typename IT::reference;
54  using pointer = typename IT::pointer;
55 
56  private:
57  IT i_;
58  pointer prev_;
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 
78  operator++()
79  {
80  do ++i_;
81  while (i_ && prev_ && *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  typedef typename DEF::Iter Iter;
100  typedef typename DEF::reference reference;
101  typedef typename DEF::pointer pointer;
102 
103 
104  WrappedStlIter() : i_() { }
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 = typename IT::value_type;
131  using reference = typename IT::reference;
132  using pointer = typename 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 = typename IT::value_type::first_type;
146  using reference = value_type &;
147  using pointer = value_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 = typename IT::value_type::second_type;
161  using reference = value_type &;
162  using pointer = value_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 typename 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  typedef typename MAP::value_type::first_type Key;
189  typedef typename MAP::value_type::second_type Val;
190  typedef typename MAP::iterator Itr;
191  };
192 
193  template<class MAP>
194  struct _MapTypeSelector<const MAP>
195  {
196  typedef typename MAP::value_type::first_type Key;
197  typedef typename MAP::value_type::second_type const Val;
198  typedef typename MAP::const_iterator Itr;
199  };
200 
202  template<class IT, typename SEL>
204  {
207  };
208 
210  template<class IT, typename SEL>
211  struct _MapSubSelector<IT, SEL const&>
212  {
213  typedef WrappedStlIter< Wrapped_PickKey<IT>> PickKey; // Key is always const for maps
215  };
216 
217 
218 
219  template<class MAP>
220  struct _MapT
221  {
222  typedef typename _MapTypeSelector<MAP>::Key KeyType;
223  typedef typename _MapTypeSelector<MAP>::Val ValType;
224  typedef typename _MapTypeSelector<MAP>::Itr EntryIter;
225 
226  typedef typename EntryIter::reference DetectConst;
229 
232 
234  };
235 
236 
237  template<class IT>
238  struct _MapIterT
239  {
240  typedef IT EntryIter;
241 
242  typedef typename EntryIter::value_type::first_type KeyType;
243  typedef typename EntryIter::value_type::second_type ValType;
244 
245  typedef typename EntryIter::reference DetectConst;
248 
251 
253  };
254 
255 
256 
257  template<class SEQ>
258  struct _SeqT
259  {
260  typedef typename SEQ::iterator Iter;
261  typedef RangeIter<Iter> Range;
264  };
265 
266  template<class SEQ>
267  struct _SeqT<const SEQ>
268  {
269  typedef typename SEQ::const_iterator Iter;
270  typedef RangeIter<Iter> Range;
273  };
274 
275  }//(End) traits/helpers
276 
277 
278 
279 
283  template<class CON>
284  inline typename _SeqT<CON>::Range
285  eachElm (CON& coll)
286  {
287  typedef typename _SeqT<CON>::Range Range;
288  return Range (coll.begin(), coll.end());
289  }
290 
291 
295  template<class CON>
296  inline typename _SeqT<CON>::Addrs
297  eachAddress (CON& coll)
298  {
299  typedef typename _SeqT<CON>::Addrs Addresses;
300  return Addresses (eachElm (coll));
301  }
302 
303 
307  template<class MAP>
308  inline typename _MapT<MAP>::KeyIter
309  eachKey (MAP& map)
310  {
311  typedef typename _MapT<MAP>::KeyIter Range;
312  typedef typename _MapT<MAP>::PickKeyIter PickKey;
313 
314  return Range (PickKey (map.begin()), PickKey (map.end()));
315  }
316 
317 
321  template<class IT>
322  inline typename _MapIterT<IT>::KeyIter
323  eachKey (IT const& begin, IT const& end)
324  {
325  typedef typename _MapIterT<IT>::KeyIter Range;
326  typedef typename _MapIterT<IT>::PickKeyIter PickKey;
327 
328  return Range (PickKey (begin), PickKey (end));
329  }
330 
331 
335  template<class MAP>
336  inline typename _MapT<MAP>::ValIter
337  eachVal (MAP& map)
338  {
339  typedef typename _MapT<MAP>::ValIter Range;
340  typedef typename _MapT<MAP>::PickValIter PickVal;
341 
342  return Range (PickVal (map.begin()), PickVal (map.end()));
343  }
344 
345 
349  template<class IT>
350  inline typename _MapIterT<IT>::ValIter
351  eachVal (IT const& begin, IT const& end)
352  {
353  typedef typename _MapIterT<IT>::ValIter Range;
354  typedef typename _MapIterT<IT>::PickValIter PickVal;
355 
356  return Range (PickVal (begin), PickVal (end));
357  }
358 
359 
363  template<class SEQ>
364  inline typename _SeqT<SEQ>::DistinctVals
365  eachDistinct (SEQ& seq)
366  {
367  typedef typename _SeqT<SEQ>::Range Range;
368  typedef typename _SeqT<SEQ>::DistinctVals DistinctValues;
369 
370  return DistinctValues (Range (seq.begin(), seq.end()));
371  }
372 
373 
378  template<class MAP>
379  inline typename _MapT<MAP>::DistinctKeys
380  eachDistinctKey (MAP& map)
381  {
382  return typename _MapT<MAP>::DistinctKeys (eachKey (map));
383  }
384 
385 
390  template<class MMAP, typename KEY>
391  inline typename _MapT<MMAP>::ValIter
392  eachValForKey (MMAP& multimap, KEY key)
393  {
394  typedef typename _MapT<MMAP>::EntryIter Pos;
395  typedef typename _MapT<MMAP>::ValIter Range;
396  typedef typename _MapT<MMAP>::PickValIter PickVal;
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  typedef std::vector<VAL> Sequence;
417 
418  mutable
419  Sequence buffer_;
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 
465  IterSnapshot(IterSnapshot &&) = default;
466  IterSnapshot(IterSnapshot const&) = default;
467  IterSnapshot& operator= (IterSnapshot const&) = default;
468  IterSnapshot& operator= (IterSnapshot &&) = 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  typedef VAL* pointer;
487  typedef VAL& reference;
488  typedef VAL value_type;
489 
490  reference
491  operator*() const
492  {
493  _maybe_throw();
494  return buffer_[pos_];
495  }
496 
497  pointer
498  operator->() const
499  {
500  _maybe_throw();
501  return &buffer_[pos_];
502  }
503 
504  IterSnapshot&
505  operator++()
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
530  operator== (IterSnapshot const& s1, IterSnapshot const& s2)
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
548  _maybe_throw() const
549  {
550  if (!isValid())
551  _throwIterExhausted();
552  }
553  };
554 
555  namespace {
556  template<class CON>
557  using ContentSnapshot = IterSnapshot<typename CON::value_type>;
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
helper to access the parts of the pair values correctly...
IterSnapshot(IT &&pos, IT const &end)
take snapshot by consuming a STL iterator
Extension adapter for Lumiera Forward Iterators to dereference any pointer values automatically...
IterSnapshot(IT &&src)
take snapshot by discharging the given Lumiera Forward iterator
IterSnapshot(IT const &begin, IT const &end)
take snapshot from STL iterator
Helper template(s) for creating Lumiera Forward Iterators.
ContentSnapshot< CON > snapshot(CON const &con)
Take a snapshot of the given STL compliant container.
#define ENABLE_USE_IN_STD_RANGE_FOR_LOOPS(ITER)
use a given Lumiera Forward Iterator in standard "range for loops"
Wrapped-Iter-Policy: picking the value part of a pair iterator (map or multimap). ...
Implementation namespace for support and library code.
_MapT< MAP >::DistinctKeys eachDistinctKey(MAP &map)
Wrapped-Iter-Policy: picking the key part of a pair iterator (map or multimap).
_MapT< MMAP >::ValIter eachValForKey(MMAP &multimap, KEY key)
_MapT< MAP >::KeyIter eachKey(MAP &map)
wrapper for an existing Iterator type to expose the address of each value yielded.
Wrapped-Iter-Policy: forwarding directly with typing retained unaltered.
IterSnapshot()
create empty snapshot
_MapT< MAP >::ValIter eachVal(MAP &map)
ContentSnapshot< IT > dischargeToSnapshot(IT &ii)
Take a snapshot of the given LumieraIterator, which is thereby consumed.
_SeqT< CON >::Range eachElm(CON &coll)
helper baseclass to simplify defining customised wrapped STL iterators
_SeqT< SEQ >::DistinctVals eachDistinct(SEQ &seq)
build a Lumiera Forward Iterator to suppress any repetitions in the given sequence.
_SeqT< CON >::Addrs eachAddress(CON &coll)
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
materialised iterator contents.
Helper to filter repeated values from a wrapped iterator (both STL or Lumiera)
IterSnapshot(IT const &src)
build snapshot from a copy of the Lumiera Iterator