104 #ifndef LIB_ITER_EXPLORER_H 105 #define LIB_ITER_EXPLORER_H 119 #include <functional> 126 template<
typename T,
class A>
class vector;
139 namespace iter_explorer {
142 using iterator =
typename meta::Strip<CON>::TypeReferred::iterator;
144 using const_iterator =
typename meta::Strip<CON>::TypeReferred::const_iterator;
197 :
public ISO::iterator
199 using Iterator =
typename ISO::iterator;
207 : Iterator{ISO::build (externalSource)}
212 : Iterator{heapObject? ISO::build (heapObject)
221 REQUIRE (ISO::iterator::isValid());
222 return static_cast<ISO&
> (*ISO::iterator::source());
234 using meta::disable_if;
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;
256 : __and_<can_STL_ForEach<SRC>
257 ,__not_<can_IterForEach<SRC>>
263 : __and_<can_IterForEach<SRC>
264 ,__not_<is_StateCore<SRC>>
273 using Res = remove_reference_t<decltype(std::declval<COR>().yield())>;
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;
282 template<
class SRC,
typename SEL=
void>
285 static_assert (!
sizeof(SRC),
"Can not build IterExplorer: Unable to figure out how to iterate the given SRC type.");
291 using SrcRaw =
typename lib::meta::Strip<SRC>::Type;
292 using SrcVal =
typename CoreYield<SrcRaw>::value_type;
299 using SrcIter = remove_reference_t<SRC>;
300 using SrcVal =
typename SrcIter::value_type;
306 static_assert (not std::is_rvalue_reference<SRC>::value,
307 "container needs to exist elsewhere during the lifetime of the iteration");
313 struct _DecoratorTraits<ISO*, enable_if<is_base_of<IterSource<typename ISO::value_type>, ISO>>>
316 using SrcVal =
typename ISO::value_type;
320 struct _DecoratorTraits<ISO*&, enable_if<is_base_of<IterSource<typename ISO::value_type>, ISO>>>
325 struct _DecoratorTraits<ISO&, enable_if<is_base_of<IterSource<typename ISO::value_type>, ISO>>>
336 template<
class SRC,
class RES>
340 using SrcYield =
typename ValueTypeBinding<SRC>::value_type;
341 using ResYield =
typename ValueTypeBinding<ResIter>::value_type;
342 static constexpr
bool can_reconcile =
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");
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>
356 using value_type =
typename ValueTypeBinding<CommonType>::value_type;
357 using reference =
typename ValueTypeBinding<CommonType>::reference;
358 using pointer =
typename ValueTypeBinding<CommonType>::pointer;
367 namespace iter_explorer {
369 constexpr
auto ACCEPT_ALL = [](
auto){
return true;};
370 constexpr
auto IDENTITY = [](
auto it){
return *it;};
401 template<
class FUN,
typename SRC>
405 template<
typename F,
typename SEL =
void>
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);
421 using Sig =
typename FunDetector<FUN>::Sig;
424 static_assert (meta::is_UnaryFun<Sig>());
429 template<
class ARG,
class SEL =
void>
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");
436 static decltype(
auto)
437 wrap (FUN&& rawFunctor)
439 return forward<FUN> (rawFunctor);
445 struct ArgAdapter<IT, enable_if<__and_<is_convertible<typename IT::reference, Arg>
446 ,__not_<is_convertible<IT, Arg>>>>>
451 return [rawFun](IT& srcIter) -> Res {
return rawFun(*srcIter); };
458 , is_base_of<IterSource<typename IT::value_type>, remove_reference_t<Arg>>
461 using Source =
typename IT::Source;
466 return [rawFun](IT&
iter) -> Res {
return rawFun(
iter.source()); };
481 template<
typename FUN,
typename SRC>
483 static_assert_isPredicate()
485 using Res =
typename _FunTraits<FUN,SRC>::Res;
486 static_assert(std::is_constructible<bool, Res>::value,
"Functor must be a predicate");
493 template<
class SRC,
class FUN>
496 using Result =
typename iter_explorer::_FunTraits<FUN,SRC>::Res;
526 BaseAdapter(SRC && src) : SRC{forward<SRC> (src)} { }
528 void expandChildren() { }
529 size_t depth()
const {
return 0; }
559 template<
class SRC,
class RES>
563 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
565 using _Trait = _ExpanderTraits<SRC,RES>;
566 using ResIter =
typename _Trait::ResIter;
567 using RootExpandFunctor = function<RES(SRC&)>;
568 using ChldExpandFunctor = function<RES(ResIter&)>;
570 RootExpandFunctor expandRoot_;
571 ChldExpandFunctor expandChild_;
579 template<
typename FUN>
580 Expander (SRC&& parentExplorer, FUN&& expandFunctor)
581 : SRC{move (parentExplorer)}
593 REQUIRE (this->checkPoint(),
"attempt to expand an empty explorer");
594 REQUIRE (invariant());
596 ResIter expanded{ hasChildren()? expandChild_(*expansions_)
597 : expandRoot_(*
this)};
598 if (not isnil(expanded))
599 expansions_.push (move(expanded));
603 ENSURE (invariant());
610 return expansions_.size();
621 if (not hasChildren())
return;
622 static_cast<SRC&
> (*this) = move (*expansions_);
631 using reference =
typename _Trait::reference;
632 using pointer =
typename _Trait::pointer;
638 ENSURE (invariant());
647 return hasChildren()? **expansions_
655 dropExhaustedChildren();
656 ENSURE (invariant());
663 return not hasChildren()
664 or expansions_->isValid();
688 REQUIRE (hasChildren());
693 dropExhaustedChildren()
695 while (not invariant())
717 static_assert(is_StateCore<SRC>::value,
"need wrapped state core as predecessor in pipeline");
726 SRC::__throw_if_empty();
727 SRC::expandChildren();
740 static_assert(is_StateCore<SRC>::value,
"need wrapped state core as predecessor in pipeline");
742 bool shallExpand_ =
false;
759 SRC::__throw_if_empty();
760 SRC::expandChildren();
761 shallExpand_ =
false;
777 template<
class SRC,
class RES>
781 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
783 using TransformFunctor = function<RES(SRC&)>;
786 TransformFunctor trafo_;
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;
798 template<
typename FUN>
799 Transformer (SRC&& dataSrc, FUN&& transformFunctor)
800 : SRC{move (dataSrc)}
814 SRC::expandChildren();
822 return bool(srcIter());
828 return unConst(
this)->invokeTransformation();
842 return unConst(*
this);
846 invokeTransformation ()
849 treated_ = trafo_(srcIter());
864 template<
class SRC,
class RES, u
int grp>
868 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
871 using Group = std::array<RES, grp>;
872 using Iter =
typename Group::iterator;
876 Group& group(){
return *
this; }
877 Iter begin() {
return group().begin();}
878 Iter end() {
return group().end(); }
885 using value_type = Group;
886 using reference = Group&;
887 using pointer = Group*;
893 : SRC{move (dataSrc)}
906 ENSURE (buff_.begin()+pos_ <= buff_.end());
908 return RangeIter{buff_.begin(), buff_.begin()+pos_};
929 SRC::expandChildren();
944 return unConst(buff_).group();
958 return unConst(*
this);
967 ; pos_<grp and srcIter()
970 buff_.group()[pos_] = *srcIter();
995 template<
class SRC,
typename AGG,
class GRP>
999 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
1002 using SrcValue =
typename meta::ValueTypeBinding<SRC>::value_type;
1003 using Grouping = function<GRP(SRC&)>;
1004 using Aggregator = function<void(AGG&, SrcValue&)>;
1006 std::optional<AGG> agg_{};
1009 Aggregator aggregate_;
1013 using reference =
typename meta::RefTraits<AGG>::Reference;
1014 using pointer =
typename meta::RefTraits<AGG>::Pointer;
1019 template<
class FGRP,
class FAGG>
1021 : SRC{move (dataSrc)}
1023 , aggregate_{forward<FAGG> (aggFun)}
1039 return *unConst(
this)->agg_;
1048 agg_ = std::nullopt;
1056 return unConst(*
this);
1064 GRP group = grouping_(srcIter());
1067 aggregate_(*agg_, *srcIter());
1070 while (srcIter() and group == grouping_(srcIter()));
1088 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
1091 using FilterPredicate = function<bool(SRC&)>;
1093 FilterPredicate predicate_;
1100 template<
typename FUN>
1101 Filter (SRC&& dataSrc, FUN&& filterFun)
1102 : SRC{move (dataSrc)}
1114 SRC::expandChildren();
1123 return bool(srcIter());
1126 typename SRC::reference
1144 return unConst(*
this);
1150 return not
bool{predicate_};
1159 if (isDisabled())
return;
1160 while (srcIter() and not predicate_(srcIter()))
1189 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
1195 template<
typename FUN>
1197 :
_Filter{move (dataSrc), forward<FUN> (filterFun)}
1204 template<
typename COND>
1208 remouldFilter (forward<COND> (conjunctiveClause)
1209 ,[](
auto first,
auto chain)
1211 return [=](
auto& val)
1220 template<
typename COND>
1224 remouldFilter (forward<COND> (conjunctiveClause)
1225 ,[](
auto first,
auto chain)
1227 return [=](
auto& val)
1236 template<
typename COND>
1240 remouldFilter (forward<COND> (disjunctiveClause)
1241 ,[](
auto first,
auto chain)
1243 return [=](
auto& val)
1252 template<
typename COND>
1256 remouldFilter (forward<COND> (disjunctiveClause)
1257 ,[](
auto first,
auto chain)
1259 return [=](
auto& val)
1271 auto dummy = [](
auto){
return false; };
1272 remouldFilter (dummy
1273 ,[](
auto currentFilter,
auto)
1275 return [=](
auto& val)
1277 return not currentFilter(val);
1283 template<
typename COND>
1287 remouldFilter (forward<COND> (entirelyDifferentPredicate)
1288 ,[](
auto,
auto chain)
1290 return [=](
auto& val)
1301 _Filter::predicate_ =
nullptr;
1321 template<
typename COND,
class COMB>
1325 static_assert_isPredicate<COND,SRC>();
1327 if (_Filter::isDisabled())
1328 _Filter::predicate_ = ACCEPT_ALL;
1330 _Filter::predicate_ = buildCombinedClause (_Filter::predicate_
1333 _Filter::pullFilter();
1353 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
1356 using Cond = function<bool(SRC&)>;
1358 Cond whileCondition_;
1365 template<
typename FUN>
1367 :
Core{move (dataSrc)}
1377 return Core::checkPoint()
1378 and whileCondition_(Core::srcIter());
1396 template<
typename VAL>
1402 virtual VAL* expandChildren() =0;
1403 virtual size_t depth()
const =0;
1420 using Val =
typename SRC::value_type;
1424 using Parent::Parent;
1427 expandChildren()
override 1429 Parent::wrappedIter().expandChildren();
1430 return Parent::wrappedIter()? & *Parent::wrappedIter()
1435 depth()
const override 1437 return Parent::wrappedIter().depth();
1464 template<
typename VAL>
1478 VAL* changedResult = expandableSource().expandChildren();
1479 this->resetPos (changedResult);
1485 return expandableSource().depth();
1498 move (opaqueSrcPipeline)})}
1502 expandableSource()
const 1504 if (not this->source())
1505 throw error::State (
"operating on a disabled default constructed IterExplorer" 1506 ,error::LUMIERA_ERROR_BOTTOM_VALUE);
1508 auto source = unConst(
this)->source().get();
1553 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
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;
1606 using ExpandedChildren =
typename iter_explorer::_FunTraits<FUN,SRC>::Res;
1609 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1630 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1640 return this->expand (forward<FUN> (expandFunctor))
1658 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1678 using Product =
typename iter_explorer::_FunTraits<FUN,SRC>::Res;
1681 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1699 using Value =
typename meta::ValueTypeBinding<SRC>::value_type;
1701 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1718 template<
class FGRP,
class FAGG>
1722 using GroupVal =
typename iter_explorer::_FunTraits<FGRP,SRC>::Res;
1724 static_assert (meta::is_BinaryFun<FAGG>());
1729 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1732 ,forward<FGRP> (groupFun)
1733 ,forward<FAGG> (aggFun)});
1737 template<
class FGRP>
1741 using Value =
typename meta::ValueTypeBinding<SRC>::value_type;
1742 return groupedBy (forward<FGRP> (groupFun)
1743 ,[](Value& agg, Value
const& val){ agg += val; }
1755 iter_explorer::static_assert_isPredicate<FUN,SRC>();
1758 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1771 iter_explorer::static_assert_isPredicate<FUN,SRC>();
1774 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1775 using ArgType =
typename iter_explorer::_FunTraits<FUN,SRC>::Arg;
1778 ,[whileCond = forward<FUN>(untilCond)](ArgType val)
1780 return not whileCond(val);
1796 iter_explorer::static_assert_isPredicate<FUN,SRC>();
1799 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1826 iter_explorer::static_assert_isPredicate<FUN,SRC>();
1829 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1838 return mutableFilter (iter_explorer::ACCEPT_ALL);
1854 template<
template<
class>
class LAY>
1858 using ResCore = LAY<SRC>;
1859 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
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; });
1879 using Ptr =
typename meta::ValueTypeBinding<SRC>::value_type;
1880 return IterExplorer::transform ([](Ptr ptr){
return *ptr; });
1906 return SRC {move(*
this)};
1915 foreach (FUN&& consumer)
1918 SRC& pipeline = *
this;
1919 for ( ; pipeline; ++pipeline)
1920 consumeFun (pipeline);
1934 ,
typename COMB =decltype(std::plus<>())
1935 ,
typename VAL =
typename iter_explorer::_ReduceTraits<SRC,FUN>::ResVal>
1938 ,COMB junctor =COMB()
1939 ,VAL seedVal =VAL())
1943 VAL sum{move(seedVal)};
1944 IterExplorer::foreach ([&](SRC& srcIter){ sum = junctor (sum, accessVal(srcIter)); });
1966 static_assert (std::is_constructible<bool,value_type>());
1967 SRC& pipeline = *
this;
1968 for ( ; pipeline; ++pipeline)
1978 static_assert (std::is_constructible<bool,value_type>());
1979 SRC& pipeline = *
this;
1980 for ( ; pipeline; ++pipeline)
1992 template<
template<
typename>
class CON =std::vector>
1996 CON<value_type> con{};
2003 effuse (CON&& sink) -> CON
2005 CON con{move(sink)};
2015 for (
auto& val : *
this)
2016 con.push_back (val);
2081 using SrcIter =
typename _DecoratorTraits<IT>::SrcIter;
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...
static auto wrap(function< Sig > rawFun)
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.
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)
handle all regular "function-like" entities
bool checkPoint() const
adapt the iteration control API for IterableDecorator: check the stop condition first and block event...
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.
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.
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's exception hierarchy.
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 ...
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
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.
adapt to a functor, which accesses the source iterator or embedded "state core"
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...
ResIter & accessCurrentChildIter()
Adapter to build a demand-driven tree expanding and exploring computation based on a custom opaque st...
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.
static auto wrap(function< Sig > rawFun)
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.