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) Lumiera.org
5  2010, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
40 #ifndef LIB_ITER_ADAPTER_STL_H
41 #define LIB_ITER_ADAPTER_STL_H
42 
43 
44 #include "lib/iter-adapter.hpp"
46 
47 #include <vector>
48 
49 
50 namespace lib {
51 namespace iter_stl {
52 
57  template<typename IT>
59  {
60  public:
61  using value_type = typename IT::value_type;
62  using reference = typename IT::reference;
63  using pointer = typename IT::pointer;
64 
65  private:
66  IT i_;
67  pointer prev_;
68 
69  void memorise() { if (i_) prev_ = &(*i_); }
70 
71  public:
72  DistinctIter() : i_(), prev_() { }
73  DistinctIter(IT const& i) : i_(i),prev_() { memorise(); }
74 
75  pointer operator->() const { return i_; }
76  reference operator*() const { return *i_; }
77  bool isValid() const { return i_; }
78 
79  explicit
80  operator bool() const
81  {
82  return bool{i_};
83  }
84 
85 
87  operator++()
88  {
89  do ++i_;
90  while (i_ && prev_ && *prev_ == *i_ );
91  memorise();
92  return *this;
93  }
94 
95  friend bool operator== (DistinctIter const& i1, DistinctIter const& i2) { return i1.i_ == i2.i_; }
96  friend bool operator!= (DistinctIter const& i1, DistinctIter const& i2) { return i1.i_ != i2.i_; }
97  };
98 
99 
100 
105  template<typename DEF>
106  struct WrappedStlIter : DEF
107  {
108  typedef typename DEF::Iter Iter;
109  typedef typename DEF::reference reference;
110  typedef typename DEF::pointer pointer;
111 
112 
113  WrappedStlIter() : i_() { }
114  WrappedStlIter(Iter const& i) : i_(i) { }
115 
116  pointer operator->() const { return DEF::get(i_); }
117  reference operator*() const { return *(DEF::get(i_)); }
118 
119  WrappedStlIter& operator++() { ++i_; return *this; }
120 
121  friend bool operator== (WrappedStlIter const& i1, WrappedStlIter const& i2) { return i1.i_ == i2.i_; }
122  friend bool operator!= (WrappedStlIter const& i1, WrappedStlIter const& i2) { return i1.i_ != i2.i_; }
123 
124  private:
125  mutable Iter i_;
126  };
127 
128 
129  /* -- customisations for building concrete wrappers -- */
130 
135  template<typename IT>
137  {
138  using Iter = IT;
139  using value_type = typename IT::value_type;
140  using reference = typename IT::reference;
141  using pointer = typename IT::pointer;
142 
143  static Iter get (Iter& it) { return & (*it); }
144  };
145 
150  template<typename IT>
152  {
153  using Iter = IT;
154  using value_type = typename IT::value_type::first_type;
155  using reference = value_type &;
156  using pointer = value_type *;
157 
158  static pointer get (Iter& it) { return & (it->first); }
159  };
160 
165  template<typename IT>
167  {
168  using Iter = IT;
169  using value_type = typename IT::value_type::second_type;
170  using reference = value_type &;
171  using pointer = value_type *;
172 
173  static pointer get (Iter& it) { return & (it->second); }
174  };
175 
176  template<typename IT>
178  {
179  using Iter = IT;
180  using value_type = const typename IT::value_type::second_type;
181  using reference = const value_type &;
182  using pointer = const value_type *;
183 
184  static pointer get (Iter& it) { return & (it->second); }
185  };
186 
187 
188 
189 
190 
191 
192  namespace { // traits and helpers...
193 
194  template<class MAP>
196  {
197  typedef typename MAP::value_type::first_type Key;
198  typedef typename MAP::value_type::second_type Val;
199  typedef typename MAP::iterator Itr;
200  };
201 
202  template<class MAP>
203  struct _MapTypeSelector<const MAP>
204  {
205  typedef typename MAP::value_type::first_type Key;
206  typedef typename MAP::value_type::second_type const Val;
207  typedef typename MAP::const_iterator Itr;
208  };
209 
211  template<class IT, typename SEL>
213  {
216  };
217 
219  template<class IT, typename SEL>
220  struct _MapSubSelector<IT, SEL const&>
221  {
222  typedef WrappedStlIter< Wrapped_PickKey<IT>> PickKey; // Key is always const for maps
224  };
225 
226 
227 
228  template<class MAP>
229  struct _MapT
230  {
231  typedef typename _MapTypeSelector<MAP>::Key KeyType;
232  typedef typename _MapTypeSelector<MAP>::Val ValType;
233  typedef typename _MapTypeSelector<MAP>::Itr EntryIter;
234 
235  typedef typename EntryIter::reference DetectConst;
238 
241 
243  };
244 
245 
246  template<class IT>
247  struct _MapIterT
248  {
249  typedef IT EntryIter;
250 
251  typedef typename EntryIter::value_type::first_type KeyType;
252  typedef typename EntryIter::value_type::second_type ValType;
253 
254  typedef typename EntryIter::reference DetectConst;
257 
260 
262  };
263 
264 
265 
266  template<class SEQ>
267  struct _SeqT
268  {
269  typedef typename SEQ::iterator Iter;
270  typedef RangeIter<Iter> Range;
273  };
274 
275  template<class SEQ>
276  struct _SeqT<const SEQ>
277  {
278  typedef typename SEQ::const_iterator Iter;
279  typedef RangeIter<Iter> Range;
282  };
283 
284  }//(End) traits/helpers
285 
286 
287 
288 
292  template<class CON>
293  inline typename _SeqT<CON>::Range
294  eachElm (CON& coll)
295  {
296  typedef typename _SeqT<CON>::Range Range;
297  return Range (coll.begin(), coll.end());
298  }
299 
300 
304  template<class CON>
305  inline typename _SeqT<CON>::Addrs
306  eachAddress (CON& coll)
307  {
308  typedef typename _SeqT<CON>::Addrs Addresses;
309  return Addresses (eachElm (coll));
310  }
311 
312 
316  template<class MAP>
317  inline typename _MapT<MAP>::KeyIter
318  eachKey (MAP& map)
319  {
320  typedef typename _MapT<MAP>::KeyIter Range;
321  typedef typename _MapT<MAP>::PickKeyIter PickKey;
322 
323  return Range (PickKey (map.begin()), PickKey (map.end()));
324  }
325 
326 
330  template<class IT>
331  inline typename _MapIterT<IT>::KeyIter
332  eachKey (IT const& begin, IT const& end)
333  {
334  typedef typename _MapIterT<IT>::KeyIter Range;
335  typedef typename _MapIterT<IT>::PickKeyIter PickKey;
336 
337  return Range (PickKey (begin), PickKey (end));
338  }
339 
340 
344  template<class MAP>
345  inline typename _MapT<MAP>::ValIter
346  eachVal (MAP& map)
347  {
348  typedef typename _MapT<MAP>::ValIter Range;
349  typedef typename _MapT<MAP>::PickValIter PickVal;
350 
351  return Range (PickVal (map.begin()), PickVal (map.end()));
352  }
353 
354 
358  template<class IT>
359  inline typename _MapIterT<IT>::ValIter
360  eachVal (IT const& begin, IT const& end)
361  {
362  typedef typename _MapIterT<IT>::ValIter Range;
363  typedef typename _MapIterT<IT>::PickValIter PickVal;
364 
365  return Range (PickVal (begin), PickVal (end));
366  }
367 
368 
372  template<class SEQ>
373  inline typename _SeqT<SEQ>::DistinctVals
374  eachDistinct (SEQ& seq)
375  {
376  typedef typename _SeqT<SEQ>::Range Range;
377  typedef typename _SeqT<SEQ>::DistinctVals DistinctValues;
378 
379  return DistinctValues (Range (seq.begin(), seq.end()));
380  }
381 
382 
387  template<class MAP>
388  inline typename _MapT<MAP>::DistinctKeys
389  eachDistinctKey (MAP& map)
390  {
391  return typename _MapT<MAP>::DistinctKeys (eachKey (map));
392  }
393 
394 
399  template<class MMAP, typename KEY>
400  inline typename _MapT<MMAP>::ValIter
401  eachValForKey (MMAP& multimap, KEY key)
402  {
403  typedef typename _MapT<MMAP>::EntryIter Pos;
404  typedef typename _MapT<MMAP>::ValIter Range;
405  typedef typename _MapT<MMAP>::PickValIter PickVal;
406 
407  std::pair<Pos,Pos> valRange = multimap.equal_range (key);
408 
409  return Range (PickVal (valRange.first), PickVal (valRange.second));
410  }
411 
412 
413 
414 
422  template<typename VAL>
424  {
425  typedef std::vector<VAL> Sequence;
426 
427  mutable
428  Sequence buffer_;
429  size_t pos_ = 0;
430 
431 
432  public:
435 
440  template<class IT>
441  IterSnapshot (IT& src)
442  {
443  for ( ; src; ++src)
444  buffer_.push_back(*src);
445  }
446 
451  template<class IT>
452  IterSnapshot (IT const& src)
453  {
454  for (IT copy{src}; copy; ++copy)
455  buffer_.push_back(*copy);
456  }
457 
459  template<class IT>
460  IterSnapshot (IT& pos, IT const& end)
461  {
462  for ( ; pos!=end; ++pos)
463  buffer_.push_back(*pos);
464  }
465 
467  template<class IT>
468  IterSnapshot (IT const& begin, IT const& end)
469  {
470  for (IT pos{begin}; pos!=end; ++pos)
471  buffer_.push_back(*pos);
472  }
473 
474  IterSnapshot(IterSnapshot &&) = default;
475  IterSnapshot(IterSnapshot const&) = default;
476  IterSnapshot& operator= (IterSnapshot const&) = default;
477  IterSnapshot& operator= (IterSnapshot &&) = default;
478 
479  explicit
480  operator bool() const
481  {
482  return isValid();
483  }
484 
485  size_t
486  size() const
487  {
488  return buffer_.size();
489  }
490 
491 
492 
493  /* === lumiera forward iterator concept === */
494 
495  typedef VAL* pointer;
496  typedef VAL& reference;
497  typedef VAL value_type;
498 
499  reference
500  operator*() const
501  {
502  _maybe_throw();
503  return buffer_[pos_];
504  }
505 
506  pointer
507  operator->() const
508  {
509  _maybe_throw();
510  return &buffer_[pos_];
511  }
512 
513  IterSnapshot&
514  operator++()
515  {
516  _maybe_throw();
517  ++pos_;
518  return *this;
519  }
520 
521  bool
522  isValid () const
523  {
524  return pos_ < buffer_.size();
525  }
526 
527  bool
528  empty () const
529  {
530  return not isValid();
531  }
532 
534 
535 
536 
538  friend bool
539  operator== (IterSnapshot const& s1, IterSnapshot const& s2)
540  {
541  return (s1.empty() and s2.empty())
542  or (s1.isValid() and s2.isValid()
543  and s1.pos_ == s2.pos_
544  and s1.buffer_ == s2.buffer_
545  );
546  }
547 
548  friend bool
549  operator!= (IterSnapshot const& snap1, IterSnapshot const& snap2)
550  {
551  return not (snap1 == snap2);
552  }
553 
554 
555  private:
556  void
557  _maybe_throw() const
558  {
559  if (!isValid())
560  _throwIterExhausted();
561  }
562  };
563 
564  namespace {
565  template<class CON>
566  using ContentSnapshot = IterSnapshot<typename CON::value_type>;
567  }
568 
569 
570 
576  template<class CON>
577  inline ContentSnapshot<CON>
578  snapshot(CON const& con)
579  {
580  return ContentSnapshot<CON>{begin(con), end(con)};
581  }
582 
586  template<class IT>
587  inline ContentSnapshot<IT>
589  {
590  return ContentSnapshot<IT>{ii};
591  }
592 
602  template<class VAL>
604  snapshot(std::initializer_list<VAL> const&& ili)
605  {
606  using OnceIter = iter_stl::IterSnapshot<VAL>;
607  return OnceIter(begin(ili), end(ili));
608  }
609 
610 
611 }} // namespace lib::iter_stl
612 #endif
IterSnapshot(IT &src)
take snapshot by discharging the given Lumiera Forward iterator
helper to access the parts of the pair values correctly...
Extension adapter for Lumiera Forward Iterators to dereference any pointer values automatically...
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"
IterSnapshot(IT &pos, IT const &end)
take snapshot by consuming a STL iterator
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