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 
132 #define LIFT_PARENT_INCREMENT_OPERATOR(_BASECLASS_)\
133  auto& \
134  operator++() \
135  { \
136  _BASECLASS_::operator++(); \
137  return *this; \
138  }
139 
140 
141 
184  template<class POS, class CON>
186  {
187  CON source_;
188  mutable POS pos_;
189 
191 
192  public:
193  using value_type = typename _ValTrait::value_type;
194  using reference = typename _ValTrait::reference;
195  using pointer = typename _ValTrait::pointer;
196 
197 
198  IterAdapter (CON src, POS const& startpos)
199  : source_(src)
200  , pos_(startpos)
201  {
202  check();
203  }
204 
205  IterAdapter ()
206  : source_()
207  , pos_()
208  { }
209 
210  explicit
211  operator bool() const
212  {
213  return isValid();
214  }
215 
216 
217  /* === lumiera forward iterator concept === */
218 
219  reference
220  operator*() const
221  {
222  _maybe_throw();
223  return *pos_;
224  }
225 
226  pointer
227  operator->() const
228  {
229  _maybe_throw();
230  return & *pos_;
231  }
232 
233  IterAdapter&
234  operator++()
235  {
236  _maybe_throw();
237  iterate();
238  return *this;
239  }
240 
241  bool
242  isValid () const
243  {
244  return check();
245  }
246 
247  bool
248  empty () const
249  {
250  return not isValid();
251  }
252 
253 
254  protected: /* === iteration control interface === */
255 
261  bool
262  check() const
263  {
264  return source_ && checkPoint (source_,pos_); // extension point: free function checkPoint(...)
265  }
266 
272  void
274  {
275  iterNext (source_,pos_); // extension point: free function iterNext(...)
276  check();
277  } // checkPoint() might mark end condition
278  // for comparison with IterAdapter{}
279 
280 
281 
282  protected:
283  using ConRef = typename meta::RefTraits<CON>::Reference;
284 
286  ConRef source() { return source_; }
287  const ConRef source() const { return unConst(this)->source_; }
288 
289  void
290  resetPos (POS otherPos)
291  {
292  pos_ = otherPos;
293  check();
294  }
295 
296  private:
297  void
298  _maybe_throw() const
299  {
300  if (not isValid())
301  _throwIterExhausted();
302  }
303 
304 
305  public:
306  ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (IterAdapter);
307 
309  template<class P1, class P2, class CX>
310  friend bool operator== (IterAdapter<P1,CX> const&, IterAdapter<P2,CX> const&);
311  };
312 
313 
315  template<class P1, class P2, class CON>
316  inline bool operator== (IterAdapter<P1,CON> const& il, IterAdapter<P2,CON> const& ir) { return il.pos_ == ir.pos_; }
317 
318  template<class P1, class P2, class CON>
319  inline bool operator!= (IterAdapter<P1,CON> const& il, IterAdapter<P2,CON> const& ir) { return not (il == ir); }
320 
321 
322 
323 
350  template<typename T, class ST =T>
352  {
353  ST core_;
354 
355  public:
356  typedef T* pointer;
357  typedef T& reference;
358  typedef T value_type;
359 
360  IterStateWrapper (ST&& initialState)
361  : core_(std::forward<ST>(initialState))
362  { }
363 
364  IterStateWrapper (ST const& initialState)
365  : core_(initialState)
366  { }
367 
369  : core_()
370  { }
371 
372  explicit
373  operator bool() const
374  {
375  return isValid();
376  }
377 
378 
379  /* === lumiera forward iterator concept === */
380 
381  reference
382  operator*() const
383  {
384  __throw_if_empty();
385  return core_.yield(); // core interface: yield
386  }
387 
388  pointer
389  operator->() const
390  {
391  __throw_if_empty();
392  return & core_.yield(); // core interface: yield
393  }
394 
396  operator++()
397  {
398  __throw_if_empty();
399  core_.iterNext(); // core interface: iterNext
400  return *this;
401  }
402 
403  bool
404  isValid () const
405  {
406  return core_.checkPoint(); // core interface: checkPoint
407  }
408 
409  bool
410  empty () const
411  {
412  return not isValid();
413  }
414 
415  protected:
416 
419  ST & stateCore() { return core_; }
420  ST const& stateCore() const { return core_; }
421 
422  void
423  __throw_if_empty() const
424  {
425  if (not isValid())
426  _throwIterExhausted();
427  }
428 
429 
430 
431  public:
433 
435  template<class T1, class T2, class STX>
437  };
438 
439 
440 
442  template<class T1, class T2, class ST>
443  inline bool
445  {
446  return (il.empty() and ir.empty())
447  or (il.isValid() and ir.isValid() and il.core_ == ir.core_);
448  }
449 
450  template<class T1, class T2, class ST>
451  inline bool
452  operator!= (IterStateWrapper<T1,ST> const& il, IterStateWrapper<T2,ST> const& ir)
453  {
454  return not (il == ir);
455  }
456 
457 
458 
459 
469  template<class IT>
471  : public IT
472  {
474  ,"Lumiera Iterator required as source");
475  protected:
476  IT&
477  srcIter() const
478  {
479  return unConst(*this);
480  }
481 
482  public:
483  using IT::IT;
484 
485  /* === state protocol API for IterStateWrapper === */
486  bool
487  checkPoint() const
488  {
489  return bool(srcIter());
490  }
491 
492  typename IT::reference
493  yield() const
494  {
495  return *srcIter();
496  }
497 
498  void
499  iterNext()
500  {
501  ++ srcIter();
502  }
503  };
504 
505 
506 
514  template<class COR>
516  : public COR
517  {
519  ,"Adapted type must expose a »state core« API");
520  protected:
521  COR&
522  _rawCore() const
523  {
524  return unConst(*this);
525  }
526 
527  void
528  __throw_if_empty() const
529  {
530  if (not checkPoint())
531  _throwIterExhausted();
532  }
533 
534  public:
538  template<typename...ARGS>
539  CheckedCore (ARGS&& ...init)
540  : COR(std::forward<ARGS>(init)...)
541  { }
542 
543  CheckedCore() =default;
544  CheckedCore (CheckedCore&&) =default;
545  CheckedCore (CheckedCore const&) =default;
546  CheckedCore& operator= (CheckedCore&&) =default;
547  CheckedCore& operator= (CheckedCore const&) =default;
548 
549 
550  /* === state protocol API for IterStateWrapper === */
551  bool
552  checkPoint() const
553  {
554  return _rawCore().checkPoint();
555  }
556 
557  decltype(auto)
558  yield() const
559  {
560  __throw_if_empty();
561  return _rawCore().yield();
562  }
563 
564  void
565  iterNext()
566  {
567  __throw_if_empty();
568  _rawCore().iterNext();
569  }
570  };
571 
572 
573 
574 
598  template<typename T, class COR>
600  : public COR
601  {
602  COR & _core() { return static_cast<COR&> (*this); }
603  COR const& _core() const { return static_cast<COR const&> (*this); }
604 
605  protected:
606  void
607  __throw_if_empty() const
608  {
609  if (not isValid())
610  _throwIterExhausted();
611  }
612 
613  public:
614  typedef T* pointer;
615  typedef T& reference;
616  typedef T value_type;
617 
623  template<typename...ARGS>
624  IterableDecorator (ARGS&& ...init)
625  : COR(std::forward<ARGS>(init)...)
626  { }
627 
628  IterableDecorator() =default;
630  IterableDecorator (IterableDecorator const&) =default;
631  IterableDecorator& operator= (IterableDecorator&&) =default;
632  IterableDecorator& operator= (IterableDecorator const&) =default;
633 
634 
635  /* === lumiera forward iterator concept === */
636 
637  explicit operator bool() const { return isValid(); }
638 
639  reference
640  operator*() const
641  {
642  return _core().yield(); // core interface: yield
643  }
644 
645  pointer
646  operator->() const
647  {
648  return & _core().yield(); // core interface: yield
649  }
650 
652  operator++()
653  {
654  _core().iterNext(); // core interface: iterNext
655  return *this;
656  }
657 
658  bool
659  isValid () const
660  {
661  return _core().checkPoint(); // core interface: checkPoint
662  }
663 
664  bool
665  empty () const
666  {
667  return not isValid();
668  }
669 
670 
671 
673 
674 
676  template<class T1, class T2>
677  friend bool
679  {
680  return (il.empty() and ir.empty())
681  or (il.isValid() and ir.isValid() and il._core() == ir._core());
682  }
683 
684  template<class T1, class T2>
685  friend bool
686  operator!= (IterableDecorator<T1,COR> const& il, IterableDecorator<T2,COR> const& ir)
687  {
688  return not (il == ir);
689  }
690  };
691 
692 
693 
694 
695 
696 
697 
712  template<class IT>
713  class RangeIter
714  {
715  IT p_;
716  IT e_;
717 
719 
720  public:
721  using pointer = typename _ValTrait::pointer;
722  using reference = typename _ValTrait::reference;
723 
725  using value_type = typename std::remove_reference<reference>::type;
726 
727 
728  RangeIter (IT const& start, IT const& end)
729  : p_(start)
730  , e_(end)
731  { }
732 
733  RangeIter ()
734  : p_()
735  , e_()
736  { }
737 
738 
742  template<class I2>
743  RangeIter (I2 const& oIter)
744  : p_(oIter.getPos())
745  , e_(oIter.getEnd())
746  { }
747 
748  explicit
749  operator bool() const
750  {
751  return isValid();
752  }
753 
754 
755  /* === lumiera forward iterator concept === */
756 
757  reference
758  operator*() const
759  {
760  _maybe_throw();
761  return *p_;
762  }
763 
764  pointer
765  operator->() const
766  {
767  _maybe_throw();
768  return &(*p_);
769  }
770 
771  RangeIter&
772  operator++()
773  {
774  _maybe_throw();
775  ++p_;
776  return *this;
777  }
778 
779  bool
780  isValid () const
781  {
782  return (p_!= IT()) && (p_ != e_);
783  }
784 
785  bool
786  empty () const
787  {
788  return not isValid();
789  }
790 
791 
793  const IT& getPos() const { return p_; }
794  const IT& getEnd() const { return e_; }
795 
796 
798 
799 
800  private:
801 
802  void
803  _maybe_throw() const
804  {
805  if (!isValid())
806  _throwIterExhausted();
807  }
808  };
809 
810 
811 
813  template<class I1, class I2>
814  inline bool operator== (RangeIter<I1> const& il, RangeIter<I2> const& ir) { return (!il && !ir) || (il.getPos() == ir.getPos()); }
815 
816  template<class I1, class I2>
817  inline bool operator!= (RangeIter<I1> const& il, RangeIter<I2> const& ir) { return !(il == ir); }
818 
819 
820 
821 
822 
831  template<typename INT>
832  class NumIter
833  {
834  INT i_;
835  INT e_;
836 
837  public:
838  typedef const INT* pointer;
839  typedef const INT& reference;
840  typedef INT value_type;
841 
842  NumIter (INT start, INT end)
843  : i_(start)
844  , e_(end)
845  { }
846 
847  template<typename X>
848  NumIter (X&& start, X&& end)
849  : i_(std::forward<X>(start))
850  , e_(std::forward<X>(end))
851  { }
852 
853  NumIter ()
854  : i_()
855  , e_()
856  { }
857 
858  // standard copy operations acceptable
859 
860  explicit
861  operator bool() const
862  {
863  return isValid();
864  }
865 
866 
867 
868  /* === lumiera forward iterator concept === */
869 
870  reference
871  operator*() const
872  {
873  _maybe_throw();
874  return i_;
875  }
876 
877  pointer
878  operator->() const
879  {
880  _maybe_throw();
881  return &i_;
882  }
883 
884  NumIter&
885  operator++()
886  {
887  _maybe_throw();
888  ++i_;
889  return *this;
890  }
891 
892  bool
893  isValid () const
894  {
895  return (i_!= INT()) && (i_ < e_); // NOTE: use comparison to detect iteration end
896  }
897 
898  bool
899  empty () const
900  {
901  return not isValid();
902  }
903 
904 
906  const INT& getPos() const { return i_; }
907  const INT& getEnd() const { return e_; }
908 
909 
911 
912 
913  private:
914  void
915  _maybe_throw() const
916  {
917  if (!isValid())
918  _throwIterExhausted();
919  }
920  };
921 
922 
923 
925  template<class I1, class I2>
926  inline bool operator== (NumIter<I1> const& il, NumIter<I2> const& ir) { return (!il && !ir) || (il.getPos() == ir.getPos()); }
927 
928  template<class I1, class I2>
929  inline bool operator!= (NumIter<I1> const& il, NumIter<I2> const& ir) { return !(il == ir); }
930 
931 
932 
934  template<typename INT>
935  inline NumIter<INT>
936  eachNum (INT start, INT end)
937  {
938  return NumIter<INT> (start, end);
939  }
940 
941 
942 
943 
944 
945 
946 
951  template<class TY>
952  struct IterType;
953 
954  template<template<class,class> class Iter, class TY, class CON>
955  struct IterType<Iter<TY,CON>>
956  {
957  typedef CON Container;
958  typedef TY ElemType;
959 
960  template<class T2>
961  struct SimilarIter
962  {
963  typedef Iter<T2,CON> Type;
964  };
965  };
966 
967  template<class IT>
968  struct IterType<RangeIter<IT>>
969  : IterType<IT>
970  {
971  template<class T2>
972  struct SimilarIter
973  {
974  typedef typename IterType<IT>::template SimilarIter<T2>::Type WrappedIter;
976  };
977  };
978 
979 
980 
982  template<class IT>
983  class ConstIter
984  {
985  IT i_;
986 
987 
988  public:
989  typedef const typename IT::value_type value_type;
990  typedef const typename IT::pointer pointer;
991  typedef const typename IT::reference reference;
992 
993  ConstIter (IT srcIter)
994  : i_(srcIter)
995  { }
996 
997  explicit
998  operator bool() const
999  {
1000  return isValid();
1001  }
1002 
1003 
1004 
1005  /* === lumiera forward iterator concept === */
1006 
1007  reference
1008  operator*() const
1009  {
1010  return *i_;
1011  }
1012 
1013  pointer
1014  operator->() const
1015  {
1016  return i_.operator->();
1017  }
1018 
1019  ConstIter&
1020  operator++()
1021  {
1022  ++i_;
1023  return *this;
1024  }
1025 
1026  bool
1027  isValid () const
1028  {
1029  return bool(i_);
1030  }
1031 
1032  bool
1033  empty () const
1034  {
1035  return not isValid();
1036  }
1037 
1038 
1040  IT const&
1041  getBase() const
1042  {
1043  return i_;
1044  }
1045 
1046 
1048  };
1049 
1050 
1052  template<class I1, class I2>
1053  inline bool operator== (ConstIter<I1> const& il, ConstIter<I2> const& ir) { return il.getBase() == ir.getBase(); }
1054 
1055  template<class I1, class I2>
1056  inline bool operator!= (ConstIter<I1> const& il, ConstIter<I2> const& ir) { return not (il == ir); }
1057 
1058 
1059 
1060 }// namespace lib
1061 #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:529
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:199
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:505
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. ...