Lumiera  0.pre.03
»edit your freedom«
iter-explorer.hpp
Go to the documentation of this file.
1 /*
2  ITER-EXPLORER.hpp - building blocks for iterator evaluation strategies
3 
4  Copyright (C) Lumiera.org
5  2017, 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 
104 #ifndef LIB_ITER_EXPLORER_H
105 #define LIB_ITER_EXPLORER_H
106 
107 
108 #include "lib/error.hpp"
111 #include "lib/meta/function.hpp"
112 #include "lib/meta/trait.hpp"
113 #include "lib/wrapper.hpp"
114 #include "lib/iter-adapter.hpp"
115 #include "lib/iter-source.hpp"
116 #include "lib/iter-stack.hpp"
117 #include "lib/util.hpp"
118 
119 #include <functional>
120 #include <optional>
121 #include <utility>
122 
123 
124 //Forward declaration to allow a default result container for IterExplorer::effuse
125 namespace std {
126  template<typename T, class A> class vector;
127 }
128 
129 
130 namespace lib {
131 
132  using std::move;
133  using std::forward;
134  using std::function;
135  using util::isnil;
136 
137  namespace error = lumiera::error;
138 
139  namespace iter_explorer { // basic iterator wrappers...
140 
141  template<class CON>
142  using iterator = typename meta::Strip<CON>::TypeReferred::iterator;
143  template<class CON>
144  using const_iterator = typename meta::Strip<CON>::TypeReferred::const_iterator;
145 
151  template<class CON>
152  struct StlRange
153  : RangeIter<iterator<CON>>
154  {
155  StlRange() =default;
156  StlRange (CON& container)
157  : RangeIter<iterator<CON>> {begin(container), end(container)}
158  { }
159  // standard copy operations acceptable
160  };
161 
162  template<class CON>
163  struct StlRange<const CON>
164  : RangeIter<const_iterator<CON>>
165  {
166  StlRange() =default;
167  StlRange (CON const& container)
168  : RangeIter<const_iterator<CON>> {begin(container), end(container)}
169  { }
170  // standard copy operations acceptable
171  };
172 
173  template<class CON>
174  struct StlRange<CON &>
175  : StlRange<CON>
176  {
178  };
179 
180 
195  template<class ISO>
197  : public ISO::iterator
198  {
199  using Iterator = typename ISO::iterator;
200 
201  public:
202  IterSourceIter() =default;
203  // standard copy operations
204 
206  IterSourceIter (ISO& externalSource)
207  : Iterator{ISO::build (externalSource)}
208  { }
209 
211  IterSourceIter (ISO* heapObject)
212  : Iterator{heapObject? ISO::build (heapObject)
213  : Iterator()}
214  { }
215 
216  using Source = ISO;
217 
218  Source&
219  source()
220  {
221  REQUIRE (ISO::iterator::isValid());
222  return static_cast<ISO&> (*ISO::iterator::source());
223  }
224  };
225 
226  }//(End) namespace iter_explorer : basic iterator wrappers
227 
228 
229 
230 
231  namespace { // IterExplorer traits
232 
233  using meta::enable_if;
234  using meta::disable_if;
235  using meta::Yes_t;
236  using meta::No_t;
237  using meta::_Fun;
238  using std::__and_;
239  using std::__not_;
240  using std::is_const_v;
241  using std::is_base_of;
242  using std::common_type;
243  using std::common_type_t;
244  using std::conditional_t;
245  using std::is_convertible;
246  using std::remove_reference_t;
247  using meta::is_StateCore;
248  using meta::can_IterForEach;
249  using meta::can_STL_ForEach;
251  using meta::has_TypeResult;
252 
253 
254  template<class SRC>
256  : __and_<can_STL_ForEach<SRC>
257  ,__not_<can_IterForEach<SRC>>
258  >
259  { };
260 
261  template<class SRC>
263  : __and_<can_IterForEach<SRC>
264  ,__not_<is_StateCore<SRC>>
265  >
266  { };
267 
268 
270  template<class COR>
271  struct CoreYield
272  {
273  using Res = remove_reference_t<decltype(std::declval<COR>().yield())>;
274 
275  using value_type = typename meta::RefTraits<Res>::Value;
276  using reference = typename meta::RefTraits<Res>::Reference;
277  using pointer = typename meta::RefTraits<Res>::Pointer;
278  };
279 
280 
282  template<class SRC, typename SEL=void>
284  {
285  static_assert (!sizeof(SRC), "Can not build IterExplorer: Unable to figure out how to iterate the given SRC type.");
286  };
287 
288  template<class SRC>
289  struct _DecoratorTraits<SRC, enable_if<is_StateCore<SRC>>>
290  {
291  using SrcRaw = typename lib::meta::Strip<SRC>::Type;
292  using SrcVal = typename CoreYield<SrcRaw>::value_type;
294  };
295 
296  template<class SRC>
297  struct _DecoratorTraits<SRC, enable_if<shall_use_Lumiera_Iter<SRC>>>
298  {
299  using SrcIter = remove_reference_t<SRC>;
300  using SrcVal = typename SrcIter::value_type;
301  };
302 
303  template<class SRC>
304  struct _DecoratorTraits<SRC, enable_if<shall_wrap_STL_Iter<SRC>>>
305  {
306  static_assert (not std::is_rvalue_reference<SRC>::value,
307  "container needs to exist elsewhere during the lifetime of the iteration");
309  using SrcVal = typename SrcIter::value_type;
310  };
311 
312  template<class ISO>
313  struct _DecoratorTraits<ISO*, enable_if<is_base_of<IterSource<typename ISO::value_type>, ISO>>>
314  {
316  using SrcVal = typename ISO::value_type;
317  };
318 
319  template<class ISO>
320  struct _DecoratorTraits<ISO*&, enable_if<is_base_of<IterSource<typename ISO::value_type>, ISO>>>
322  { };
323 
324  template<class ISO>
325  struct _DecoratorTraits<ISO&, enable_if<is_base_of<IterSource<typename ISO::value_type>, ISO>>>
327  { };
328 
329 
330 
336  template<class SRC, class RES>
338  {
339  using ResIter = typename _DecoratorTraits<RES>::SrcIter;
340  using SrcYield = typename ValueTypeBinding<SRC>::value_type;
341  using ResYield = typename ValueTypeBinding<ResIter>::value_type;
342  static constexpr bool can_reconcile =
344 
345  static_assert (can_reconcile,
346  "source iterator and result from the expansion must yield compatible values");
347  static_assert (is_const_v<SrcYield> == is_const_v<ResYield>,
348  "source and expanded types differ in const-ness");
349 
350  // NOTE: unfortunately std::common_type decays (strips cv and reference)
351  // in C++20, there would be std::common_reference; for now we have to work around that
352  using CommonType = conditional_t<is_const_v<SrcYield> or is_const_v<ResYield>
353  , const common_type_t<SrcYield,ResYield>
354  , common_type_t<SrcYield,ResYield>
355  >;
356  using value_type = typename ValueTypeBinding<CommonType>::value_type;
357  using reference = typename ValueTypeBinding<CommonType>::reference;
358  using pointer = typename ValueTypeBinding<CommonType>::pointer;
359  };
360 
361  }//(End) IterExplorer traits
362 
363 
364 
365 
366 
367  namespace iter_explorer { // Implementation of Iterator decorating layers...
368 
369  constexpr auto ACCEPT_ALL = [](auto){return true;};
370  constexpr auto IDENTITY = [](auto it){return *it;};
371 
401  template<class FUN, typename SRC>
402  struct _FunTraits
403  {
405  template<typename F, typename SEL =void>
406  struct FunDetector
407  {
408  using Sig = typename _Fun<F>::Sig;
409  };
410 
412  template<typename F>
413  struct FunDetector<F, disable_if<_Fun<F>> >
414  {
415  using Arg = typename std::add_lvalue_reference<SRC>::type;
416  using Ret = decltype(std::declval<F>() (std::declval<Arg>()));
417  using Sig = Ret(Arg);
418  };
419 
420 
421  using Sig = typename FunDetector<FUN>::Sig;
422  using Arg = typename _Fun<Sig>::Args::List::Head; // assuming function with a single argument
423  using Res = typename _Fun<Sig>::Ret;
424  static_assert (meta::is_UnaryFun<Sig>());
425 
426 
427 
429  template<class ARG, class SEL =void>
430  struct ArgAdapter
431  {
432  using FunArgType = remove_reference_t<Arg>;
433  static_assert (std::is_convertible<ARG, FunArgType>::value,
434  "the bound functor must accept the source iterator or state core as parameter");
435 
436  static decltype(auto)
437  wrap (FUN&& rawFunctor)
438  {
439  return forward<FUN> (rawFunctor);
440  }
441  };
442 
444  template<class IT>
445  struct ArgAdapter<IT, enable_if<__and_<is_convertible<typename IT::reference, Arg>
446  ,__not_<is_convertible<IT, Arg>>>>> // need to exclude the latter, since IterableDecorator
447  { // often seems to accept IT::value_type (while in fact it doesn't)
448  static auto
449  wrap (function<Sig> rawFun)
450  {
451  return [rawFun](IT& srcIter) -> Res { return rawFun(*srcIter); };
452  }
453  };
454 
456  template<class IT>
457  struct ArgAdapter<IT, enable_if<__and_< is_base_of<IterSource<typename IT::value_type>, typename IT::Source>
458  , is_base_of<IterSource<typename IT::value_type>, remove_reference_t<Arg>>
459  > >>
460  {
461  using Source = typename IT::Source;
462 
463  static auto
464  wrap (function<Sig> rawFun)
465  {
466  return [rawFun](IT& iter) -> Res { return rawFun(iter.source()); };
467  }
468  };
469 
470 
471 
473  static auto
474  adaptFunctor (FUN&& rawFunctor)
475  {
476  return function<Res(SRC&)> {ArgAdapter<SRC>::wrap (forward<FUN> (rawFunctor))};
477  }
478  };
479 
480 
481  template<typename FUN, typename SRC>
482  inline void
483  static_assert_isPredicate()
484  {
485  using Res = typename _FunTraits<FUN,SRC>::Res;
486  static_assert(std::is_constructible<bool, Res>::value, "Functor must be a predicate");
487  }
488 
489 
493  template<class SRC, class FUN>
495  {
496  using Result = typename iter_explorer::_FunTraits<FUN,SRC>::Res;
497  using ResVal = typename lib::meta::RefTraits<Result>::Value;
498  };
499 
500 
501 
502 
503 
520  template<class SRC>
521  struct BaseAdapter
522  : SRC
523  {
524  BaseAdapter() = default;
525  BaseAdapter(SRC const& src) : SRC{src} { }
526  BaseAdapter(SRC && src) : SRC{forward<SRC> (src)} { }
527 
528  void expandChildren() { }
529  size_t depth() const { return 0; }
530  };
531 
532 
559  template<class SRC, class RES>
560  class Expander
561  : public SRC
562  {
563  static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
564 
565  using _Trait = _ExpanderTraits<SRC,RES>;
566  using ResIter = typename _Trait::ResIter;
567  using RootExpandFunctor = function<RES(SRC&)>;
568  using ChldExpandFunctor = function<RES(ResIter&)>;
569 
570  RootExpandFunctor expandRoot_;
571  ChldExpandFunctor expandChild_;
572 
573  IterStack<ResIter> expansions_;
574 
575  public:
576  Expander() =default;
577  // inherited default copy operations
578 
579  template<typename FUN>
580  Expander (SRC&& parentExplorer, FUN&& expandFunctor)
581  : SRC{move (parentExplorer)} // NOTE: slicing move to strip IterExplorer (Builder)
582  , expandRoot_ {_FunTraits<FUN,SRC> ::adaptFunctor (forward<FUN> (expandFunctor))} // adapt to accept SRC&
583  , expandChild_{_FunTraits<FUN,ResIter>::adaptFunctor (forward<FUN> (expandFunctor))} // adapt to accept RES&
584  , expansions_{}
585  { }
586 
587 
588 
590  void
592  {
593  REQUIRE (this->checkPoint(), "attempt to expand an empty explorer");
594  REQUIRE (invariant());
595 
596  ResIter expanded{ hasChildren()? expandChild_(*expansions_)
597  : expandRoot_(*this)};
598  if (not isnil(expanded))
599  expansions_.push (move(expanded)); // note: source of expansion retained
600  else
601  iterNext(); // expansion unsuccessful, thus consume source immediately
602 
603  ENSURE (invariant());
604  }
605 
607  size_t
608  depth() const
609  {
610  return expansions_.size();
611  }
612 
618  void
620  {
621  if (not hasChildren()) return;
622  static_cast<SRC&> (*this) = move (*expansions_);
623  expansions_.clear();
624  }
625 
626 
627  public: /* === Iteration control API for IterableDecorator === */
628 
630  using value_type = typename _Trait::value_type;
631  using reference = typename _Trait::reference;
632  using pointer = typename _Trait::pointer;
633 
634 
635  bool
636  checkPoint() const
637  {
638  ENSURE (invariant());
639 
640  return hasChildren()
641  or SRC::isValid();
642  }
643 
644  reference
645  yield() const
646  {
647  return hasChildren()? **expansions_
648  : **this;
649  }
650 
651  void
652  iterNext()
653  {
654  incrementCurrent();
655  dropExhaustedChildren();
656  ENSURE (invariant());
657  }
658 
659  private:
660  bool
661  invariant() const
662  {
663  return not hasChildren()
664  or expansions_->isValid();
665  }
666 
667  void
668  incrementCurrent()
669  {
670  if (hasChildren())
671  ++(*expansions_);
672  else
673  ++(*this);
674  }
675 
676 
677  protected:
678  bool
679  hasChildren() const
680  {
681  return 0 < depth();
682  }
683 
685  ResIter&
687  {
688  REQUIRE (hasChildren());
689  return *expansions_;
690  }
691 
692  void
693  dropExhaustedChildren()
694  {
695  while (not invariant())
696  {
697  ++expansions_; // pop expansion stack (to reinstate invariant)
698  incrementCurrent(); // consume source of innermost expansion
699  }
700  }
701  };
702 
703 
704 
713  template<class SRC>
715  : public SRC
716  {
717  static_assert(is_StateCore<SRC>::value, "need wrapped state core as predecessor in pipeline");
718 
719  public:
721  using SRC::SRC;
722 
723  void
724  iterNext()
725  {
726  SRC::__throw_if_empty();
727  SRC::expandChildren();
728  }
729  };
730 
731 
732 
736  template<class SRC>
738  : public SRC
739  {
740  static_assert(is_StateCore<SRC>::value, "need wrapped state core as predecessor in pipeline");
741 
742  bool shallExpand_ = false;
743 
744  public:
746  using SRC::SRC;
747 
748  void
749  expandChildren()
750  {
751  shallExpand_ = true;
752  }
753 
754  void
755  iterNext()
756  {
757  if (shallExpand_)
758  {
759  SRC::__throw_if_empty();
760  SRC::expandChildren();
761  shallExpand_ = false;
762  }
763  else
764  SRC::iterNext();
765  }
766  };
767 
768 
769 
777  template<class SRC, class RES>
779  : public SRC
780  {
781  static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
782 
783  using TransformFunctor = function<RES(SRC&)>;
785 
786  TransformFunctor trafo_;
787  TransformedItem treated_;
788 
789  public:
790  using value_type = typename meta::ValueTypeBinding<RES>::value_type;
791  using reference = typename meta::ValueTypeBinding<RES>::reference;
792  using pointer = typename meta::ValueTypeBinding<RES>::pointer;
793 
794 
795  Transformer() =default;
796  // inherited default copy operations
797 
798  template<typename FUN>
799  Transformer (SRC&& dataSrc, FUN&& transformFunctor)
800  : SRC{move (dataSrc)} // NOTE: slicing move to strip IterExplorer (Builder)
801  , trafo_{_FunTraits<FUN,SRC>::adaptFunctor (forward<FUN> (transformFunctor))}
802  { }
803 
804 
810  void
812  {
813  treated_.reset();
814  SRC::expandChildren();
815  }
816 
817  public: /* === Iteration control API for IterableDecorator === */
818 
819  bool
820  checkPoint() const
821  {
822  return bool(srcIter());
823  }
824 
825  reference
826  yield() const
827  {
828  return unConst(this)->invokeTransformation();
829  }
830 
831  void
832  iterNext()
833  {
834  ++ srcIter();
835  treated_.reset();
836  }
837 
838  private:
839  SRC&
840  srcIter() const
841  {
842  return unConst(*this);
843  }
844 
845  reference
846  invokeTransformation ()
847  {
848  if (not treated_) // invoke transform function once per src item
849  treated_ = trafo_(srcIter());
850  return *treated_;
851  }
852  };
853 
854 
855 
864  template<class SRC, class RES, uint grp>
865  class Grouping
866  : public SRC
867  {
868  static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
869 
870  protected:
871  using Group = std::array<RES, grp>;
872  using Iter = typename Group::iterator;
873  struct Buffer
874  : lib::UninitialisedStorage<RES,grp>
875  {
876  Group& group(){ return *this; }
877  Iter begin() { return group().begin();}
878  Iter end() { return group().end(); }
879  };
880  Buffer buff_;
881  uint pos_{0};
882 
883 
884  public:
885  using value_type = Group;
886  using reference = Group&;
887  using pointer = Group*;
888 
889  Grouping() =default;
890  // inherited default copy operations
891 
892  Grouping (SRC&& dataSrc)
893  : SRC{move (dataSrc)}
894  {
895  pullGroup(); // initially pull to establish the invariant
896  }
897 
898 
903  auto
905  {
906  ENSURE (buff_.begin()+pos_ <= buff_.end());
907  // Array iterators are actually pointers
908  return RangeIter{buff_.begin(), buff_.begin()+pos_};
909  }
910 
917  auto
919  {
920  return checkPoint()? RangeIter<Iter>()
921  : getGroupedElms();
922  }
923 
926  void
928  {
929  SRC::expandChildren();
930  pullGroup();
931  }
932 
933  public: /* === Iteration control API for IterableDecorator === */
934 
935  bool
936  checkPoint() const
937  {
938  return pos_ == grp;
939  }
940 
941  reference
942  yield() const
943  {
944  return unConst(buff_).group();
945  }
946 
947  void
948  iterNext()
949  {
950  pullGroup();
951  }
952 
953 
954  protected:
955  SRC&
956  srcIter() const
957  {
958  return unConst(*this);
959  }
960 
963  void
965  {
966  for (pos_=0
967  ; pos_<grp and srcIter()
968  ; ++pos_,++srcIter()
969  )
970  buff_.group()[pos_] = *srcIter();
971  }
972  };
973 
974 
975 
995  template<class SRC, typename AGG, class GRP>
997  : public SRC
998  {
999  static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
1000 
1001  protected:
1002  using SrcValue = typename meta::ValueTypeBinding<SRC>::value_type;
1003  using Grouping = function<GRP(SRC&)>;
1004  using Aggregator = function<void(AGG&, SrcValue&)>;
1005 
1006  std::optional<AGG> agg_{};
1007 
1008  Grouping grouping_;
1009  Aggregator aggregate_;
1010 
1011  public:
1012  using value_type = typename meta::RefTraits<AGG>::Value;
1013  using reference = typename meta::RefTraits<AGG>::Reference;
1014  using pointer = typename meta::RefTraits<AGG>::Pointer;
1015 
1016  GroupAggregator() =default;
1017  // inherited default copy operations
1018 
1019  template<class FGRP, class FAGG>
1020  GroupAggregator (SRC&& dataSrc, FGRP&& groupFun, FAGG&& aggFun)
1021  : SRC{move (dataSrc)}
1022  , grouping_{_FunTraits<FGRP,SRC>::adaptFunctor (forward<FGRP> (groupFun))}
1023  , aggregate_{forward<FAGG> (aggFun)}
1024  {
1025  pullGroup(); // initially pull to establish the invariant
1026  }
1027 
1028 
1029  public: /* === Iteration control API for IterableDecorator === */
1030  bool
1031  checkPoint() const
1032  {
1033  return bool(agg_);
1034  }
1035 
1036  reference
1037  yield() const
1038  {
1039  return *unConst(this)->agg_;
1040  }
1041 
1042  void
1043  iterNext()
1044  {
1045  if (srcIter())
1046  pullGroup();
1047  else
1048  agg_ = std::nullopt;
1049  }
1050 
1051 
1052  protected:
1053  SRC&
1054  srcIter() const
1055  {
1056  return unConst(*this);
1057  }
1058 
1061  void
1063  {
1064  GRP group = grouping_(srcIter());
1065  agg_ = AGG{};
1066  do{
1067  aggregate_(*agg_, *srcIter());
1068  ++ srcIter();
1069  }
1070  while (srcIter() and group == grouping_(srcIter()));
1071  }
1072  };
1073 
1074 
1075 
1076 
1084  template<class SRC>
1085  class Filter
1086  : public SRC
1087  {
1088  static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
1089 
1090  protected:
1091  using FilterPredicate = function<bool(SRC&)>;
1092 
1093  FilterPredicate predicate_;
1094 
1095  public:
1096 
1097  Filter() =default;
1098  // inherited default copy operations
1099 
1100  template<typename FUN>
1101  Filter (SRC&& dataSrc, FUN&& filterFun)
1102  : SRC{move (dataSrc)}
1103  , predicate_{_FunTraits<FUN,SRC>::adaptFunctor (forward<FUN> (filterFun))}
1104  {
1105  pullFilter(); // initially pull to establish the invariant
1106  }
1107 
1108 
1111  void
1113  {
1114  SRC::expandChildren();
1115  pullFilter();
1116  }
1117 
1118  public: /* === Iteration control API for IterableDecorator === */
1119 
1120  bool
1121  checkPoint() const
1122  {
1123  return bool(srcIter());
1124  }
1125 
1126  typename SRC::reference
1127  yield() const
1128  {
1129  return *srcIter();
1130  }
1131 
1132  void
1133  iterNext()
1134  {
1135  ++ srcIter();
1136  pullFilter();
1137  }
1138 
1139 
1140  protected:
1141  SRC&
1142  srcIter() const
1143  {
1144  return unConst(*this);
1145  }
1146 
1147  bool
1148  isDisabled() const
1149  {
1150  return not bool{predicate_};
1151  }
1152 
1156  void
1158  {
1159  if (isDisabled()) return;
1160  while (srcIter() and not predicate_(srcIter()))
1161  ++srcIter();
1162  }
1163  };
1164 
1165 
1166 
1184  template<class SRC>
1186  : public Filter<SRC>
1187  {
1188  using _Filter = Filter<SRC>;
1189  static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
1190 
1191  public:
1192  MutableFilter() =default;
1193  // inherited default copy operations
1194 
1195  template<typename FUN>
1196  MutableFilter (SRC&& dataSrc, FUN&& filterFun)
1197  : _Filter{move (dataSrc), forward<FUN> (filterFun)}
1198  { }
1199 
1200 
1201  public: /* === API to Remould the Filter condition underway === */
1202 
1204  template<typename COND>
1205  void
1206  andFilter (COND&& conjunctiveClause)
1207  {
1208  remouldFilter (forward<COND> (conjunctiveClause)
1209  ,[](auto first, auto chain)
1210  {
1211  return [=](auto& val)
1212  {
1213  return first(val)
1214  and chain(val);
1215  };
1216  });
1217  }
1218 
1220  template<typename COND>
1221  void
1222  andNotFilter (COND&& conjunctiveClause)
1223  {
1224  remouldFilter (forward<COND> (conjunctiveClause)
1225  ,[](auto first, auto chain)
1226  {
1227  return [=](auto& val)
1228  {
1229  return first(val)
1230  and not chain(val);
1231  };
1232  });
1233  }
1234 
1236  template<typename COND>
1237  void
1238  orFilter (COND&& disjunctiveClause)
1239  {
1240  remouldFilter (forward<COND> (disjunctiveClause)
1241  ,[](auto first, auto chain)
1242  {
1243  return [=](auto& val)
1244  {
1245  return first(val)
1246  or chain(val);
1247  };
1248  });
1249  }
1250 
1252  template<typename COND>
1253  void
1254  orNotFilter (COND&& disjunctiveClause)
1255  {
1256  remouldFilter (forward<COND> (disjunctiveClause)
1257  ,[](auto first, auto chain)
1258  {
1259  return [=](auto& val)
1260  {
1261  return first(val)
1262  or not chain(val);
1263  };
1264  });
1265  }
1266 
1268  void
1270  {
1271  auto dummy = [](auto){ return false; };
1272  remouldFilter (dummy
1273  ,[](auto currentFilter, auto)
1274  {
1275  return [=](auto& val)
1276  {
1277  return not currentFilter(val);
1278  };
1279  });
1280  }
1281 
1283  template<typename COND>
1284  void
1285  setNewFilter (COND&& entirelyDifferentPredicate)
1286  {
1287  remouldFilter (forward<COND> (entirelyDifferentPredicate)
1288  ,[](auto, auto chain)
1289  {
1290  return [=](auto& val)
1291  {
1292  return chain(val);
1293  };
1294  });
1295  }
1296 
1298  void
1300  {
1301  _Filter::predicate_ = nullptr;
1302  }
1303 
1304 
1305  private:
1321  template<typename COND, class COMB>
1322  void
1323  remouldFilter (COND&& additionalClause, COMB buildCombinedClause)
1324  {
1325  static_assert_isPredicate<COND,SRC>();
1326 
1327  if (_Filter::isDisabled())
1328  _Filter::predicate_ = ACCEPT_ALL;
1329 
1330  _Filter::predicate_ = buildCombinedClause (_Filter::predicate_ // pick up the existing filter predicate
1331  ,_FunTraits<COND,SRC>::adaptFunctor (forward<COND> (additionalClause))
1332  ); // wrap the extension predicate in a similar way
1333  _Filter::pullFilter(); // then pull to re-establish the Invariant
1334  }
1335  };
1336 
1337 
1338 
1349  template<class SRC>
1351  : public IterStateCore<SRC>
1352  {
1353  static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
1354 
1355  using Core = IterStateCore<SRC>;
1356  using Cond = function<bool(SRC&)>;
1357 
1358  Cond whileCondition_;
1359 
1360  public:
1361 
1362  StopTrigger() =default;
1363  // inherited default copy operations
1364 
1365  template<typename FUN>
1366  StopTrigger (SRC&& dataSrc, FUN&& condition)
1367  : Core{move (dataSrc)}
1368  , whileCondition_{_FunTraits<FUN,SRC>::adaptFunctor (forward<FUN> (condition))}
1369  { }
1370 
1371 
1374  bool
1375  checkPoint() const
1376  {
1377  return Core::checkPoint()
1378  and whileCondition_(Core::srcIter());
1379  }
1380  };
1381 
1382 
1383 
1384 
1396  template<typename VAL>
1398  {
1399  protected:
1401  public:
1402  virtual VAL* expandChildren() =0;
1403  virtual size_t depth() const =0;
1404  };
1405 
1414  template<class SRC>
1416  : public WrappedLumieraIter<SRC>
1417  , public ChildExpandableSource<typename SRC::value_type>
1418  {
1420  using Val = typename SRC::value_type;
1421 
1423  public:
1424  using Parent::Parent;
1425 
1426  virtual Val*
1427  expandChildren() override
1428  {
1429  Parent::wrappedIter().expandChildren();
1430  return Parent::wrappedIter()? & *Parent::wrappedIter()
1431  : nullptr;
1432  }
1433 
1434  virtual size_t
1435  depth() const override
1436  {
1437  return Parent::wrappedIter().depth();
1438  }
1439  };
1440 
1441  }//(End)Iterator decorating layer implementation
1442 
1443 
1444 
1445 
1446 
1464  template<typename VAL>
1466  : IterSource<VAL>::iterator
1467  {
1469 
1470 
1471  IterExploreSource() =default;
1472  // inherited default copy operations
1473 
1474 
1475  void
1476  expandChildren()
1477  {
1478  VAL* changedResult = expandableSource().expandChildren();
1479  this->resetPos (changedResult);
1480  }
1481 
1482  size_t
1483  depth() const
1484  {
1485  return expandableSource().depth();
1486  }
1487 
1488 
1489  private:
1490  template<class SRC>
1491  friend class IterExplorer;
1492 
1493  template<class IT>
1494  IterExploreSource (IT&& opaqueSrcPipeline)
1498  move (opaqueSrcPipeline)})}
1499  { }
1500 
1501  Expandable&
1502  expandableSource() const
1503  {
1504  if (not this->source())
1505  throw error::State ("operating on a disabled default constructed IterExplorer"
1506  ,error::LUMIERA_ERROR_BOTTOM_VALUE);
1507 
1508  auto source = unConst(this)->source().get();
1509  return dynamic_cast<Expandable&> (*source);
1510  }
1511  };
1512 
1513 
1514 
1515 
1516 
1517  /* ======= IterExplorer pipeline builder and iterator ======= */
1518 
1549  template<class SRC>
1551  : public SRC
1552  {
1553  static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
1554 
1555 
1556  public:
1557  using value_type = typename meta::ValueTypeBinding<SRC>::value_type;
1558  using reference = typename meta::ValueTypeBinding<SRC>::reference;
1559  using pointer = typename meta::ValueTypeBinding<SRC>::pointer;
1560 
1562  using SRC::SRC;
1563 
1564 
1565 
1566  /* ==== Builder functions ==== */
1567 
1602  template<class FUN>
1603  auto
1604  expand (FUN&& expandFunctor)
1605  {
1606  using ExpandedChildren = typename iter_explorer::_FunTraits<FUN,SRC>::Res;
1607 
1609  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1610 
1611  return IterExplorer<ResIter> (ResCore {move(*this), forward<FUN>(expandFunctor)});
1612  }
1613 
1614 
1626  auto
1628  {
1629  using ResCore = iter_explorer::AutoExpander<SRC>;
1630  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1631 
1632  return IterExplorer<ResIter> (ResCore {move(*this)});
1633  }
1634 
1636  template<class FUN>
1637  auto
1638  expandAll (FUN&& expandFunctor)
1639  {
1640  return this->expand (forward<FUN> (expandFunctor))
1641  .expandAll();
1642  }
1643 
1644 
1654  auto
1656  {
1657  using ResCore = iter_explorer::ScheduledExpander<SRC>;
1658  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1659 
1660  return IterExplorer<ResIter> (ResCore {move(*this)});
1661  }
1662 
1663 
1674  template<class FUN>
1675  auto
1676  transform (FUN&& transformFunctor)
1677  {
1678  using Product = typename iter_explorer::_FunTraits<FUN,SRC>::Res;
1679 
1681  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1682 
1683  return IterExplorer<ResIter> (ResCore {move(*this), forward<FUN>(transformFunctor)});
1684  }
1685 
1686 
1695  template<uint grp>
1696  auto
1698  {
1699  using Value = typename meta::ValueTypeBinding<SRC>::value_type;
1701  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1702 
1703  return IterExplorer<ResIter> (ResCore {move(*this)});
1704  }
1705 
1706 
1718  template<class FGRP, class FAGG>
1719  auto
1720  groupedBy (FGRP&& groupFun, FAGG&& aggFun)
1721  {
1722  using GroupVal = typename iter_explorer::_FunTraits<FGRP,SRC>::Res;
1723 
1724  static_assert (meta::is_BinaryFun<FAGG>());
1725  using ArgType1 = typename _Fun<FAGG>::Args::List::Head;
1726  using Aggregate = typename meta::RefTraits<ArgType1>::Value;
1727 
1729  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1730 
1731  return IterExplorer<ResIter> (ResCore {move(*this)
1732  ,forward<FGRP> (groupFun)
1733  ,forward<FAGG> (aggFun)});
1734  }
1735 
1737  template<class FGRP>
1738  auto
1739  groupedBy (FGRP&& groupFun)
1740  {
1741  using Value = typename meta::ValueTypeBinding<SRC>::value_type;
1742  return groupedBy (forward<FGRP> (groupFun)
1743  ,[](Value& agg, Value const& val){ agg += val; }
1744  );
1745  }
1746 
1747 
1751  template<class FUN>
1752  auto
1753  iterWhile (FUN&& whileCond)
1754  {
1755  iter_explorer::static_assert_isPredicate<FUN,SRC>();
1756 
1757  using ResCore = iter_explorer::StopTrigger<SRC>;
1758  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1759 
1760  return IterExplorer<ResIter> (ResCore {move(*this), forward<FUN>(whileCond)});
1761  }
1762 
1763 
1767  template<class FUN>
1768  auto
1769  iterUntil (FUN&& untilCond)
1770  {
1771  iter_explorer::static_assert_isPredicate<FUN,SRC>();
1772 
1773  using ResCore = iter_explorer::StopTrigger<SRC>;
1774  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1775  using ArgType = typename iter_explorer::_FunTraits<FUN,SRC>::Arg;
1776 
1777  return IterExplorer<ResIter> (ResCore { move(*this)
1778  ,[whileCond = forward<FUN>(untilCond)](ArgType val)
1779  {
1780  return not whileCond(val);
1781  }
1782  });
1783  }
1784 
1785 
1792  template<class FUN>
1793  auto
1794  filter (FUN&& filterPredicate)
1795  {
1796  iter_explorer::static_assert_isPredicate<FUN,SRC>();
1797 
1798  using ResCore = iter_explorer::Filter<SRC>;
1799  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1800 
1801  return IterExplorer<ResIter> (ResCore {move(*this), forward<FUN>(filterPredicate)});
1802  }
1803 
1804 
1822  template<class FUN>
1823  auto
1824  mutableFilter (FUN&& filterPredicate)
1825  {
1826  iter_explorer::static_assert_isPredicate<FUN,SRC>();
1827 
1828  using ResCore = iter_explorer::MutableFilter<SRC>;
1829  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1830 
1831  return IterExplorer<ResIter> (ResCore {move(*this), forward<FUN>(filterPredicate)});
1832  }
1833 
1834 
1835  auto
1836  mutableFilter()
1837  {
1838  return mutableFilter (iter_explorer::ACCEPT_ALL);
1839  }
1840 
1841 
1842 
1854  template<template<class> class LAY>
1855  auto
1857  {
1858  using ResCore = LAY<SRC>;
1859  using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
1860 
1861  return IterExplorer<ResIter> (ResCore {move(*this)});
1862  }
1863 
1864 
1865 
1867  auto
1869  {
1870  using Val = typename meta::ValueTypeBinding<SRC>::value_type;
1871  static_assert (not std::is_pointer_v<Val>);
1872  return IterExplorer::transform ([](Val& ref){ return &ref; });
1873  }
1874 
1876  auto
1878  {
1879  using Ptr = typename meta::ValueTypeBinding<SRC>::value_type;
1880  return IterExplorer::transform ([](Ptr ptr){ return *ptr; });
1881  }
1882 
1883 
1884 
1895  {
1896  return IterExploreSource<value_type> {move(*this)};
1897  }
1898 
1899 
1903  SRC
1905  {
1906  return SRC {move(*this)};
1907  }
1908 
1913  template<class FUN>
1914  void
1915  foreach (FUN&& consumer)
1916  {
1917  auto consumeFun = iter_explorer::_FunTraits<FUN,SRC>::adaptFunctor (forward<FUN> (consumer));
1918  SRC& pipeline = *this;
1919  for ( ; pipeline; ++pipeline)
1920  consumeFun (pipeline);
1921  }
1922 
1923 
1933  template<class FUN
1934  ,typename COMB =decltype(std::plus<>())
1935  ,typename VAL =typename iter_explorer::_ReduceTraits<SRC,FUN>::ResVal>
1936  VAL
1937  reduce (FUN&& accessor
1938  ,COMB junctor =COMB()
1939  ,VAL seedVal =VAL())
1940  {
1941  auto accessVal = iter_explorer::_FunTraits<FUN,SRC>::adaptFunctor (forward<FUN> (accessor));
1942 
1943  VAL sum{move(seedVal)};
1944  IterExplorer::foreach ([&](SRC& srcIter){ sum = junctor (sum, accessVal(srcIter)); });
1945  return sum;
1946  }
1947 
1949  auto
1951  {
1952  return IterExplorer::reduce ([](const reference val){ return val; });
1953  }
1954 
1956  size_t
1958  {
1959  return IterExplorer::reduce ([](auto){ return size_t(1); });
1960  }
1961 
1963  bool
1965  {
1966  static_assert (std::is_constructible<bool,value_type>());
1967  SRC& pipeline = *this;
1968  for ( ; pipeline; ++pipeline)
1969  if (*pipeline)
1970  return true;
1971  return false;
1972  }
1973 
1975  bool
1977  {
1978  static_assert (std::is_constructible<bool,value_type>());
1979  SRC& pipeline = *this;
1980  for ( ; pipeline; ++pipeline)
1981  if (not *pipeline)
1982  return false;
1983  return true;
1984  }
1985 
1986 
1992  template<template<typename> class CON =std::vector>
1993  auto
1995  {
1996  CON<value_type> con{};
1997  this->effuse (con);
1998  return con;
1999  }
2000 
2001  template<class CON>
2002  auto
2003  effuse (CON&& sink) -> CON
2004  {
2005  CON con{move(sink)};
2006  this->effuse (con);
2007  return con;
2008  }
2009 
2011  template<class CON>
2012  void
2013  effuse (CON& con)
2014  {
2015  for (auto& val : *this)
2016  con.push_back (val);
2017  }
2018  };
2019 
2020 
2021 
2022 
2023 
2024 
2025 
2026 
2027  /* ==== convenient builder free functions ==== */
2028 
2077  template<class IT>
2078  inline auto
2079  explore (IT&& srcSeq)
2080  {
2081  using SrcIter = typename _DecoratorTraits<IT>::SrcIter;
2083 
2084  return IterExplorer<Base> (std::forward<IT> (srcSeq));
2085  }
2086 
2087 
2088 } // namespace lib
2089 #endif /* LIB_ITER_EXPLORER_H */
IterSourceIter(ISO &externalSource)
link to existing IterSource (without memory management)
static auto adaptFunctor(FUN &&rawFunctor)
builder to create a nested/wrapping functor, suitably adapting the arguments
auto asPtr()
preconfigured transformer to pass pointers down the pipeline
void expandChildren()
refresh state when other layers manipulate the source sequence.
bool and_all()
simplified terminal builder to check if all results yields true (short-circuit)
VAL reduce(FUN &&accessor, COMB junctor=COMB(), VAL seedVal=VAL())
terminal builder to sum up or reduce values from the pipeline.
void disableFilter()
discard filter predicates and disable any filtering
void remouldFilter(COND &&additionalClause, COMB buildCombinedClause)
auto groupedBy(FGRP &&groupFun, FAGG &&aggFun)
adapt this IterExplorer to group elements by a custom criterium and aggregate the group members...
Trait template to detect a type usable with the STL for-each loop.
Definition: trait.hpp:550
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
size_t count()
simplified terminal builder to count number of elements from this sequence.
Representation of the result of some operation, EITHER a value or a failure.
Definition: result.hpp:106
Helper template(s) for creating Lumiera Forward Iterators.
auto processingLayer()
builder function to attach a custom extension layer. Any template in compliance with the general cons...
void effuse(CON &con)
_terminal builder to fill an existing container with all results from this Pipeline ...
Conveniently iterable stack and queue containers.
IterExploreSource< value_type > asIterSource()
terminal builder to package the processing pipeline as IterSource.
bool has_any()
simplified terminal builder to check if any result yields true (short-circuit)
STL namespace.
handle all regular "function-like" entities
Trait template to detect a type exposing a »state core« API.
Definition: trait.hpp:529
bool checkPoint() const
adapt the iteration control API for IterableDecorator: check the stop condition first and block event...
Helper for uniform access to function signature types.
Definition: function.hpp:108
auto expandAll()
extension functionality to be used on top of expand(), to perform expansion automatically.
auto iterWhile(FUN &&whileCond)
adapt this IterExplorer to iterate only as long as a condition holds true.
auto getRestElms()
Retrieve the tail elements produced by the source, which did not suffice to fill a full group...
Adapter to dress up an existing »Lumiera Forward Iterator« as »state core«.
auto mutableFilter(FUN &&filterPredicate)
attach a special filter adapter, allowing to change the filter predicate while iterating.
helper to check if another metafunction produced a result type
Definition: meta/util.hpp:135
Iterator front-end to manage and operate a IterExplorer pipeline opaquely.
auto expandOnIteration()
extension functionality to be used on top of expand(), to perform expansion on next iteration...
void andNotFilter(COND &&conjunctiveClause)
remould existing predicate to require in addition the negation of the given clause to hold ...
typename std::remove_reference< reference >::type value_type
Implementation namespace for support and library code.
auto resultSum()
simplified terminal builder to reduce by numeric sum.
typename enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition: meta/util.hpp:92
auto effuse()
terminal builder to pour and materialise all results from this Pipeline.
void rootCurrent()
lock into the current child sequence.
decide how to adapt and embed the source sequence into the resulting IterExplorer ...
Adapt STL compliant container.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
auto grouped()
adapt this IterExplorer to group result elements into fixed size chunks, packaged as std::array...
Iteration source interface to abstract a data source, which then can be accessed through IterAdapter ...
Definition: iter-source.hpp:88
Metaprogramming tools for transforming functor types.
the value type yielded by a »state core«
typename _Trait::value_type value_type
auto filter(FUN &&filterPredicate)
adapt this IterExplorer to filter results, by invoking the given functor to approve them...
void orFilter(COND &&disjunctiveClause)
remould existing predicate to require either the old OR the given new clause to hold ...
auto transform(FUN &&transformFunctor)
adapt this IterExplorer to pipe each result value through a transformation function.
IterSourceIter(ISO *heapObject)
own and manage a heap allocated IterSource
int reduce(Gtk::Button &icon)
attempt to reduce space consumption
void expandChildren()
refresh state when other layers manipulate the source sequence
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
auto expandAll(FUN &&expandFunctor)
shortcut notation to invoke expand(expandFunctor) followed by expandAll()
Block of raw uninitialised storage with array like access.
Trait template to detect a type usable immediately as "Lumiera Forward Iterator" in a specialised for...
Definition: trait.hpp:505
adapt to a functor, which accesses the source iterator or embedded "state core"
char Yes_t
helper types to detect the overload resolution chosen by the compiler
Definition: meta/util.hpp:104
auto derefPtr()
preconfigured transformer to dereference pointers into references
auto expand(FUN &&expandFunctor)
preconfigure this IterExplorer to allow for _"expansion of children"_.
auto iterUntil(FUN &&untilCond)
adapt this IterExplorer to iterate until a condition becomes first true.
auto groupedBy(FGRP &&groupFun)
simplified grouping to sum / combine all values in a group
void flipFilter()
remould existing predicate to negate the meaning of the existing clause
A raw memory block with proper alignment and array access.
Helpers for type detection, type rewriting and metaprogramming.
auto getGroupedElms()
Iterate over the Elements in the current group.
Lumiera error handling (C++ interface).
void setNewFilter(COND &&entirelyDifferentPredicate)
replace the existing predicate with the given, entirely different predicate
size_t depth() const
diagnostics: current level of nested child expansion
void expandChildren()
refresh state when other layers manipulate the source sequence.
Decorator-Adapter to make a »state core« iterable as Lumiera Forward Iterator.
void expandChildren()
core operation: expand current head element
helper to derive a suitable common type when expanding children
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
Adapter to build a demand-driven tree expanding and exploring computation based on a custom opaque st...
Type re-binding helper template for creating nested typedefs usable by custom containers and iterator...
void andFilter(COND &&conjunctiveClause)
remould existing predicate to require in addition the given clause to hold
SRC asIterator()
terminal builder to strip the IterExplorer and expose the built Pipeline.
Interface to indicate and expose the ability for child expansion.
Extension module to build an opaque data source, accessible as Lumiera Forward Iterator.
Standard implementation of the IterSource interface: a wrapped "Lumiera Forward Iterator".
Library implementation: smart-pointer variations, wrappers and managing holders.
Metaprogramming helpers to check for specific properties of a type in question.
void orNotFilter(COND &&disjunctiveClause)
remould existing predicate to require either the old OR the negation of a new clause to hold ...
Adapt an IterSource to make it iterable.