Lumiera  0.pre.03
»edit your freedom«
iter-adapter.hpp
Go to the documentation of this file.
1 /*
2  ITER-ADAPTER.hpp - helpers for building simple forward iterators
3 
4  Copyright (C) Lumiera.org
5  2009, 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 
101 #ifndef LIB_ITER_ADAPTER_H
102 #define LIB_ITER_ADAPTER_H
103 
104 
105 #include "lib/error.hpp"
107 
108 #include <iterator>
109 
110 
111 namespace lib {
112 
113 
114  namespace { // internal helpers
115  inline void
116  _throwIterExhausted()
117  {
118  throw lumiera::error::Invalid ("Can't iterate further",
119  lumiera::error::LUMIERA_ERROR_ITER_EXHAUST);
120  }
121  }
122 
124 #define ENABLE_USE_IN_STD_RANGE_FOR_LOOPS(ITER) \
125  friend ITER begin (ITER const& it){ return it; } \
126  friend ITER&& begin (ITER&& it) { return static_cast<ITER&&> (it); } \
127  friend ITER end (ITER const&) { return ITER(); } \
128  using iterator_category = std::input_iterator_tag; \
129  using difference_type = size_t;
130 
131 
132 
175  template<class POS, class CON>
177  {
178  CON source_;
179  mutable POS pos_;
180 
182 
183  public:
184  using value_type = typename _ValTrait::value_type;
185  using reference = typename _ValTrait::reference;
186  using pointer = typename _ValTrait::pointer;
187 
188 
189  IterAdapter (CON src, POS const& startpos)
190  : source_(src)
191  , pos_(startpos)
192  {
193  check();
194  }
195 
196  IterAdapter ()
197  : source_()
198  , pos_()
199  { }
200 
201  explicit
202  operator bool() const
203  {
204  return isValid();
205  }
206 
207 
208  /* === lumiera forward iterator concept === */
209 
210  reference
211  operator*() const
212  {
213  _maybe_throw();
214  return *pos_;
215  }
216 
217  pointer
218  operator->() const
219  {
220  _maybe_throw();
221  return & *pos_;
222  }
223 
224  IterAdapter&
225  operator++()
226  {
227  _maybe_throw();
228  iterate();
229  return *this;
230  }
231 
232  bool
233  isValid () const
234  {
235  return check();
236  }
237 
238  bool
239  empty () const
240  {
241  return not isValid();
242  }
243 
244 
245  protected: /* === iteration control interface === */
246 
252  bool
253  check() const
254  {
255  return source_ && checkPoint (source_,pos_); // extension point: free function checkPoint(...)
256  }
257 
263  void
265  {
266  iterNext (source_,pos_); // extension point: free function iterNext(...)
267  check();
268  } // checkPoint() might mark end condition
269  // for comparison with IterAdapter{}
270 
271 
272 
273  protected:
274  using ConRef = typename meta::RefTraits<CON>::Reference;
275 
277  ConRef source() { return source_; }
278  const ConRef source() const { return unConst(this)->source_; }
279 
280  void
281  resetPos (POS otherPos)
282  {
283  pos_ = otherPos;
284  check();
285  }
286 
287  private:
288  void
289  _maybe_throw() const
290  {
291  if (not isValid())
292  _throwIterExhausted();
293  }
294 
295 
296  public:
297  ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (IterAdapter);
298 
300  template<class P1, class P2, class CX>
301  friend bool operator== (IterAdapter<P1,CX> const&, IterAdapter<P2,CX> const&);
302  };
303 
304 
306  template<class P1, class P2, class CON>
307  inline bool operator== (IterAdapter<P1,CON> const& il, IterAdapter<P2,CON> const& ir) { return il.pos_ == ir.pos_; }
308 
309  template<class P1, class P2, class CON>
310  inline bool operator!= (IterAdapter<P1,CON> const& il, IterAdapter<P2,CON> const& ir) { return not (il == ir); }
311 
312 
313 
314 
341  template<typename T, class ST =T>
343  {
344  ST core_;
345 
346  public:
347  typedef T* pointer;
348  typedef T& reference;
349  typedef T value_type;
350 
351  IterStateWrapper (ST&& initialState)
352  : core_(std::forward<ST>(initialState))
353  { }
354 
355  IterStateWrapper (ST const& initialState)
356  : core_(initialState)
357  { }
358 
360  : core_()
361  { }
362 
363  explicit
364  operator bool() const
365  {
366  return isValid();
367  }
368 
369 
370  /* === lumiera forward iterator concept === */
371 
372  reference
373  operator*() const
374  {
375  __throw_if_empty();
376  return core_.yield(); // core interface: yield
377  }
378 
379  pointer
380  operator->() const
381  {
382  __throw_if_empty();
383  return & core_.yield(); // core interface: yield
384  }
385 
387  operator++()
388  {
389  __throw_if_empty();
390  core_.iterNext(); // core interface: iterNext
391  return *this;
392  }
393 
394  bool
395  isValid () const
396  {
397  return core_.checkPoint(); // core interface: checkPoint
398  }
399 
400  bool
401  empty () const
402  {
403  return not isValid();
404  }
405 
406  protected:
407 
410  ST &
412  {
413  return core_;
414  }
415 
416  void
417  __throw_if_empty() const
418  {
419  if (not isValid())
420  _throwIterExhausted();
421  }
422 
423 
424 
425  public:
427 
429  template<class T1, class T2, class STX>
431  };
432 
433 
434 
436  template<class T1, class T2, class ST>
437  inline bool
439  {
440  return (il.empty() and ir.empty())
441  or (il.isValid() and ir.isValid() and il.core_ == ir.core_);
442  }
443 
444  template<class T1, class T2, class ST>
445  inline bool
446  operator!= (IterStateWrapper<T1,ST> const& il, IterStateWrapper<T2,ST> const& ir)
447  {
448  return not (il == ir);
449  }
450 
451 
452 
453 
463  template<class IT>
465  : public IT
466  {
468  ,"Lumiera Iterator required as source");
469  protected:
470  IT&
471  srcIter() const
472  {
473  return unConst(*this);
474  }
475 
476  public:
477  using IT::IT;
478 
479  /* === state protocol API for IterStateWrapper === */
480  bool
481  checkPoint() const
482  {
483  return bool(srcIter());
484  }
485 
486  typename IT::reference
487  yield() const
488  {
489  return *srcIter();
490  }
491 
492  void
493  iterNext()
494  {
495  ++ srcIter();
496  }
497  };
498 
499 
500 
508  template<class COR>
510  : public COR
511  {
513  ,"Adapted type must expose a »state core« API");
514  protected:
515  COR&
516  _rawCore() const
517  {
518  return unConst(*this);
519  }
520 
521  void
522  __throw_if_empty() const
523  {
524  if (not checkPoint())
525  _throwIterExhausted();
526  }
527 
528  public:
532  template<typename...ARGS>
533  CheckedCore (ARGS&& ...init)
534  : COR(std::forward<ARGS>(init)...)
535  { }
536 
537  CheckedCore() =default;
538  CheckedCore (CheckedCore&&) =default;
539  CheckedCore (CheckedCore const&) =default;
540  CheckedCore& operator= (CheckedCore&&) =default;
541  CheckedCore& operator= (CheckedCore const&) =default;
542 
543 
544  /* === state protocol API for IterStateWrapper === */
545  bool
546  checkPoint() const
547  {
548  return _rawCore().checkPoint();
549  }
550 
551  decltype(auto)
552  yield() const
553  {
554  __throw_if_empty();
555  return _rawCore().yield();
556  }
557 
558  void
559  iterNext()
560  {
561  __throw_if_empty();
562  _rawCore().iterNext();
563  }
564  };
565 
566 
567 
568 
592  template<typename T, class COR>
594  : public COR
595  {
596  COR & _core() { return static_cast<COR&> (*this); }
597  COR const& _core() const { return static_cast<COR const&> (*this); }
598 
599  protected:
600  void
601  __throw_if_empty() const
602  {
603  if (not isValid())
604  _throwIterExhausted();
605  }
606 
607  public:
608  typedef T* pointer;
609  typedef T& reference;
610  typedef T value_type;
611 
617  template<typename...ARGS>
618  IterableDecorator (ARGS&& ...init)
619  : COR(std::forward<ARGS>(init)...)
620  { }
621 
622  IterableDecorator() =default;
624  IterableDecorator (IterableDecorator const&) =default;
625  IterableDecorator& operator= (IterableDecorator&&) =default;
626  IterableDecorator& operator= (IterableDecorator const&) =default;
627 
628 
629  /* === lumiera forward iterator concept === */
630 
631  explicit operator bool() const { return isValid(); }
632 
633  reference
634  operator*() const
635  {
636  return _core().yield(); // core interface: yield
637  }
638 
639  pointer
640  operator->() const
641  {
642  return & _core().yield(); // core interface: yield
643  }
644 
646  operator++()
647  {
648  _core().iterNext(); // core interface: iterNext
649  return *this;
650  }
651 
652  bool
653  isValid () const
654  {
655  return _core().checkPoint(); // core interface: checkPoint
656  }
657 
658  bool
659  empty () const
660  {
661  return not isValid();
662  }
663 
664 
665 
667 
668 
670  template<class T1, class T2>
671  friend bool
673  {
674  return (il.empty() and ir.empty())
675  or (il.isValid() and ir.isValid() and il._core() == ir._core());
676  }
677 
678  template<class T1, class T2>
679  friend bool
680  operator!= (IterableDecorator<T1,COR> const& il, IterableDecorator<T2,COR> const& ir)
681  {
682  return not (il == ir);
683  }
684  };
685 
686 
687 
688 
689 
690 
691 
706  template<class IT>
707  class RangeIter
708  {
709  IT p_;
710  IT e_;
711 
713 
714  public:
715  using pointer = typename _ValTrait::pointer;
716  using reference = typename _ValTrait::reference;
717 
719  using value_type = typename std::remove_reference<reference>::type;
720 
721 
722  RangeIter (IT const& start, IT const& end)
723  : p_(start)
724  , e_(end)
725  { }
726 
727  RangeIter ()
728  : p_()
729  , e_()
730  { }
731 
732 
736  template<class I2>
737  RangeIter (I2 const& oIter)
738  : p_(oIter.getPos())
739  , e_(oIter.getEnd())
740  { }
741 
742  explicit
743  operator bool() const
744  {
745  return isValid();
746  }
747 
748 
749  /* === lumiera forward iterator concept === */
750 
751  reference
752  operator*() const
753  {
754  _maybe_throw();
755  return *p_;
756  }
757 
758  pointer
759  operator->() const
760  {
761  _maybe_throw();
762  return &(*p_);
763  }
764 
765  RangeIter&
766  operator++()
767  {
768  _maybe_throw();
769  ++p_;
770  return *this;
771  }
772 
773  bool
774  isValid () const
775  {
776  return (p_!= IT()) && (p_ != e_);
777  }
778 
779  bool
780  empty () const
781  {
782  return not isValid();
783  }
784 
785 
787  const IT& getPos() const { return p_; }
788  const IT& getEnd() const { return e_; }
789 
790 
792 
793 
794  private:
795 
796  void
797  _maybe_throw() const
798  {
799  if (!isValid())
800  _throwIterExhausted();
801  }
802  };
803 
804 
805 
807  template<class I1, class I2>
808  inline bool operator== (RangeIter<I1> const& il, RangeIter<I2> const& ir) { return (!il && !ir) || (il.getPos() == ir.getPos()); }
809 
810  template<class I1, class I2>
811  inline bool operator!= (RangeIter<I1> const& il, RangeIter<I2> const& ir) { return !(il == ir); }
812 
813 
814 
815 
816 
825  template<typename INT>
826  class NumIter
827  {
828  INT i_;
829  INT e_;
830 
831  public:
832  typedef const INT* pointer;
833  typedef const INT& reference;
834  typedef INT value_type;
835 
836  NumIter (INT start, INT end)
837  : i_(start)
838  , e_(end)
839  { }
840 
841  template<typename X>
842  NumIter (X&& start, X&& end)
843  : i_(std::forward<X>(start))
844  , e_(std::forward<X>(end))
845  { }
846 
847  NumIter ()
848  : i_()
849  , e_()
850  { }
851 
852  // standard copy operations acceptable
853 
854  explicit
855  operator bool() const
856  {
857  return isValid();
858  }
859 
860 
861 
862  /* === lumiera forward iterator concept === */
863 
864  reference
865  operator*() const
866  {
867  _maybe_throw();
868  return i_;
869  }
870 
871  pointer
872  operator->() const
873  {
874  _maybe_throw();
875  return &i_;
876  }
877 
878  NumIter&
879  operator++()
880  {
881  _maybe_throw();
882  ++i_;
883  return *this;
884  }
885 
886  bool
887  isValid () const
888  {
889  return (i_!= INT()) && (i_ < e_); // NOTE: use comparison to detect iteration end
890  }
891 
892  bool
893  empty () const
894  {
895  return not isValid();
896  }
897 
898 
900  const INT& getPos() const { return i_; }
901  const INT& getEnd() const { return e_; }
902 
903 
905 
906 
907  private:
908  void
909  _maybe_throw() const
910  {
911  if (!isValid())
912  _throwIterExhausted();
913  }
914  };
915 
916 
917 
919  template<class I1, class I2>
920  inline bool operator== (NumIter<I1> const& il, NumIter<I2> const& ir) { return (!il && !ir) || (il.getPos() == ir.getPos()); }
921 
922  template<class I1, class I2>
923  inline bool operator!= (NumIter<I1> const& il, NumIter<I2> const& ir) { return !(il == ir); }
924 
925 
926 
928  template<typename INT>
929  inline NumIter<INT>
930  eachNum (INT start, INT end)
931  {
932  return NumIter<INT> (start, end);
933  }
934 
935 
936 
937 
938 
939 
940 
945  template<class TY>
946  struct IterType;
947 
948  template<template<class,class> class Iter, class TY, class CON>
949  struct IterType<Iter<TY,CON>>
950  {
951  typedef CON Container;
952  typedef TY ElemType;
953 
954  template<class T2>
955  struct SimilarIter
956  {
957  typedef Iter<T2,CON> Type;
958  };
959  };
960 
961  template<class IT>
962  struct IterType<RangeIter<IT>>
963  : IterType<IT>
964  {
965  template<class T2>
966  struct SimilarIter
967  {
968  typedef typename IterType<IT>::template SimilarIter<T2>::Type WrappedIter;
970  };
971  };
972 
973 
974 
976  template<class IT>
977  class ConstIter
978  {
979  IT i_;
980 
981 
982  public:
983  typedef const typename IT::value_type value_type;
984  typedef const typename IT::pointer pointer;
985  typedef const typename IT::reference reference;
986 
987  ConstIter (IT srcIter)
988  : i_(srcIter)
989  { }
990 
991  explicit
992  operator bool() const
993  {
994  return isValid();
995  }
996 
997 
998 
999  /* === lumiera forward iterator concept === */
1000 
1001  reference
1002  operator*() const
1003  {
1004  return *i_;
1005  }
1006 
1007  pointer
1008  operator->() const
1009  {
1010  return i_.operator->();
1011  }
1012 
1013  ConstIter&
1014  operator++()
1015  {
1016  ++i_;
1017  return *this;
1018  }
1019 
1020  bool
1021  isValid () const
1022  {
1023  return bool(i_);
1024  }
1025 
1026  bool
1027  empty () const
1028  {
1029  return not isValid();
1030  }
1031 
1032 
1034  IT const&
1035  getBase() const
1036  {
1037  return i_;
1038  }
1039 
1040 
1042  };
1043 
1044 
1046  template<class I1, class I2>
1047  inline bool operator== (ConstIter<I1> const& il, ConstIter<I2> const& ir) { return il.getBase() == ir.getBase(); }
1048 
1049  template<class I1, class I2>
1050  inline bool operator!= (ConstIter<I1> const& il, ConstIter<I2> const& ir) { return not (il == ir); }
1051 
1052 
1053 
1054 }// namespace lib
1055 #endif /*LIB_ITER_ADAPTER_H*/
const IT & getPos() const
access wrapped STL iterator
ST & stateCore()
allow derived classes to access state representation
Helper for type rewritings: get the element type for an iterator like entity.
NumIter< INT > eachNum(INT start, INT end)
convenience function to iterate "each number"
CheckedCore(ARGS &&...init)
blindly pass-down any argument...
Adapter to add sanity checks to a »state core«.
Type re-binding helper template for custom containers and adapters.
STL namespace.
Trait template to detect a type exposing a »state core« API.
Definition: trait.hpp:513
IterableDecorator(ARGS &&...init)
by default, pass anything down for initialisation of the core.
#define ENABLE_USE_IN_STD_RANGE_FOR_LOOPS(ITER)
use a given Lumiera Forward Iterator in standard "range for loops"
ConRef source()
allow derived classes to access backing container
Adapter to dress up an existing »Lumiera Forward Iterator« as »state core«.
typename std::remove_reference< reference >::type value_type
Implementation namespace for support and library code.
Enumerate all "numbers" within a range.
friend bool operator==(IterAdapter< P1, CX > const &, IterAdapter< P2, CX > const &)
comparison is allowed to access impl iterator
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:196
IT const & getBase() const
access the wrapped implementation iterator
const INT & getPos() const
access wrapped index elements
Another Lumiera Forward Iterator building block, based on incorporating a state type right into the i...
Trait template to detect a type usable immediately as "Lumiera Forward Iterator" in a specialised for...
Definition: trait.hpp:489
wrapper to expose values as const
RangeIter(I2 const &oIter)
allow copy, when the underlying iterators are compatible or convertible
Lumiera error handling (C++ interface).
IT i_
nested source iterator
bool check() const
ask the controlling container if this position is valid.
Decorator-Adapter to make a »state core« iterable as Lumiera Forward Iterator.
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
Type re-binding helper template for creating nested typedefs usable by custom containers and iterator...
void iterate()
ask the controlling container to yield the next position.
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...