97 #ifndef LIB_ITER_EXPLORER_H 98 #define LIB_ITER_EXPLORER_H 112 #include <functional> 119 template<
typename T,
class A>
class vector;
120 template<
typename K,
typename CMP,
class A>
class set;
133 namespace iter_explorer {
136 using iterator =
typename meta::Strip<CON>::TypeReferred::iterator;
138 using const_iterator =
typename meta::Strip<CON>::TypeReferred::const_iterator;
191 :
public ISO::iterator
193 using Iterator =
typename ISO::iterator;
201 : Iterator{ISO::build (externalSource)}
206 : Iterator{heapObject? ISO::build (heapObject)
215 REQUIRE (ISO::iterator::isValid());
216 return static_cast<ISO&
> (*ISO::iterator::source());
228 using meta::disable_if;
234 using std::is_const_v;
235 using std::is_base_of;
236 using std::common_type;
237 using std::common_type_t;
238 using std::conditional_t;
239 using std::is_convertible;
240 using std::remove_reference_t;
250 : __and_<can_STL_ForEach<SRC>
251 ,__not_<can_IterForEach<SRC>>
257 : __and_<can_IterForEach<SRC>
258 ,__not_<is_StateCore<SRC>>
267 template<
class SRC,
typename SEL=
void>
270 static_assert (!
sizeof(SRC),
"Can not build IterExplorer: Unable to figure out how to iterate the given SRC type.");
276 using SrcRaw =
typename lib::meta::Strip<SRC>::Type;
284 using SrcIter = remove_reference_t<SRC>;
285 using SrcVal =
typename SrcIter::value_type;
291 static_assert (not std::is_rvalue_reference<SRC>::value,
292 "container needs to exist elsewhere during the lifetime of the iteration");
298 struct _DecoratorTraits<ISO*, enable_if<is_base_of<IterSource<typename ISO::value_type>, ISO>>>
301 using SrcVal =
typename ISO::value_type;
305 struct _DecoratorTraits<ISO*&, enable_if<is_base_of<IterSource<typename ISO::value_type>, ISO>>>
310 struct _DecoratorTraits<ISO&, enable_if<is_base_of<IterSource<typename ISO::value_type>, ISO>>>
324 template<
class SRC,
class RES>
328 using SrcYield = iter::Yield<SRC>;
329 using ResYield = iter::Yield<ResIter>;
331 static constexpr
bool can_reconcile = _CommonT::value;
332 static constexpr
bool isRefResult = _CommonT::isRef;
334 static_assert (can_reconcile,
335 "source iterator and result from the expansion must yield compatible values");
336 static_assert (is_const_v<SrcYield> == is_const_v<ResYield>,
337 "source and expanded types differ in const-ness");
339 using YieldRes =
typename _CommonT::ResType;
340 using value_type =
typename _CommonT::value_type;
341 using reference =
typename _CommonT::reference;
342 using pointer =
typename _CommonT::pointer;
351 namespace iter_explorer {
353 constexpr
auto ACCEPT_ALL = [](
auto){
return true;};
354 constexpr
auto IDENTITY = [](
auto it){
return *it;};
385 template<
class FUN,
typename SRC>
389 template<
typename F,
typename SEL =
void>
399 using Arg =
typename std::add_lvalue_reference<SRC>::type;
400 using Ret = decltype(std::declval<F>() (std::declval<Arg>()));
401 using Sig = Ret(Arg);
405 using Sig =
typename FunDetector<FUN>::Sig;
408 static_assert (meta::is_UnaryFun<Sig>());
413 template<
class ARG,
class SEL =
void>
416 using FunArgType = remove_reference_t<Arg>;
417 static_assert (std::is_convertible<ARG, FunArgType>::value,
418 "the bound functor must accept the source iterator or state core as parameter");
420 static decltype(
auto)
421 wrap (FUN&& rawFunctor)
423 return forward<FUN> (rawFunctor);
430 ,__not_<is_convertible<IT, Arg>>>>>
435 return [rawFun](IT& srcIter) -> Res {
return rawFun(*srcIter); };
442 , is_base_of<IterSource<typename IT::value_type>, remove_reference_t<Arg>>
445 using Source =
typename IT::Source;
450 return [rawFun](IT&
iter) -> Res {
return rawFun(
iter.source()); };
465 template<
typename FUN,
typename SRC>
467 static_assert_isPredicate()
469 using Res =
typename _FunTraits<FUN,SRC>::Res;
470 static_assert(std::is_constructible<bool, Res>::value,
"Functor must be a predicate");
477 template<
class SRC,
class FUN>
480 using Result =
typename iter_explorer::_FunTraits<FUN,SRC>::Res;
481 using ResVal =
typename lib::meta::RefTraits<Result>::Value;
510 BaseAdapter(SRC && src) : SRC{forward<SRC> (src)} { }
553 template<
class SRC,
class RES>
557 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
559 using _Trait = _ExpanderTraits<SRC,RES>;
560 using ResIter =
typename _Trait::ResIter;
561 using RootExpandFunctor = function<RES(SRC&)>;
562 using ChldExpandFunctor = function<RES(ResIter&)>;
564 RootExpandFunctor expandRoot_;
565 ChldExpandFunctor expandChild_;
573 template<
typename FUN>
574 Expander (SRC&& parentExplorer, FUN&& expandFunctor)
575 : SRC{move (parentExplorer)}
587 REQUIRE (this->checkPoint(),
"attempt to expand an empty explorer");
588 REQUIRE (invariant());
590 ResIter expanded{ hasChildren()? expandChild_(*expansions_)
591 : expandRoot_(*
this)};
592 if (not isnil(expanded))
593 expansions_.push (move(expanded));
597 ENSURE (invariant());
604 return expansions_.size();
615 if (not hasChildren())
return;
616 static_cast<SRC&
> (*this) = move (*expansions_);
625 using value_type =
typename _Trait::value_type;
626 using reference =
typename _Trait::reference;
627 using pointer =
typename _Trait::pointer;
633 ENSURE (invariant());
642 return hasChildren()? **expansions_
650 dropExhaustedChildren();
651 ENSURE (invariant());
658 return not hasChildren()
659 or expansions_->isValid();
683 REQUIRE (hasChildren());
688 dropExhaustedChildren()
690 while (not invariant())
712 static_assert(is_StateCore<SRC>::value,
"need wrapped state core as predecessor in pipeline");
721 SRC::__throw_if_empty();
722 SRC::expandChildren();
735 static_assert(is_StateCore<SRC>::value,
"need wrapped state core as predecessor in pipeline");
737 bool shallExpand_ =
false;
754 SRC::__throw_if_empty();
755 SRC::expandChildren();
756 shallExpand_ =
false;
781 template<
class SRC,
class RES>
785 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
787 using TransformFunctor = function<RES(SRC&)>;
790 TransformFunctor trafo_;
794 using value_type =
typename meta::ValueTypeBinding<RES>::value_type;
795 using reference =
typename meta::ValueTypeBinding<RES>::reference;
796 using pointer =
typename meta::ValueTypeBinding<RES>::pointer;
799 template<
typename FUN>
800 Transformer (SRC&& dataSrc, FUN&& transformFunctor)
801 : SRC{move (dataSrc)}
813 , trafo_{move (o.trafo_)}
819 swap (*
this,changed);
828 swap (t1.trafo_, t2.trafo_);
841 SRC::expandChildren();
849 return bool(srcIter());
855 return unConst(
this)->invokeTransformation();
869 return unConst(*
this);
873 invokeTransformation ()
876 treated_ = trafo_(srcIter());
891 template<
class SRC,
class RES, u
int grp>
895 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
898 using Group = std::array<RES, grp>;
899 using Iter =
typename Group::iterator;
903 Group& group(){
return *
this; }
904 Iter begin() {
return group().begin();}
905 Iter end() {
return group().end(); }
912 using value_type = Group;
913 using reference = Group&;
914 using pointer = Group*;
920 : SRC{move (dataSrc)}
933 ENSURE (buff_.begin()+pos_ <= buff_.end());
935 return RangeIter{buff_.begin(), buff_.begin()+pos_};
956 SRC::expandChildren();
971 return unConst(buff_).group();
985 return unConst(*
this);
994 ; pos_<grp and srcIter()
997 buff_.group()[pos_] = *srcIter();
1024 template<
class SRC,
typename AGG,
class GRP>
1028 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
1031 using SrcValue =
typename meta::ValueTypeBinding<SRC>::value_type;
1032 using Grouping = function<GRP(SRC&)>;
1033 using Aggregator = function<void(AGG&, SrcValue&)>;
1035 std::optional<AGG> agg_{};
1038 Aggregator aggregate_;
1041 using value_type =
typename meta::RefTraits<AGG>::Value;
1042 using reference =
typename meta::RefTraits<AGG>::Reference;
1043 using pointer =
typename meta::RefTraits<AGG>::Pointer;
1048 template<
class FGRP,
class FAGG>
1050 : SRC{move (dataSrc)}
1052 , aggregate_{forward<FAGG> (aggFun)}
1068 return *unConst(
this)->agg_;
1077 agg_ = std::nullopt;
1085 return unConst(*
this);
1093 GRP group = grouping_(srcIter());
1096 aggregate_(*agg_, *srcIter());
1099 while (srcIter() and group == grouping_(srcIter()));
1117 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
1120 using FilterPredicate = function<bool(SRC&)>;
1122 FilterPredicate predicate_;
1129 template<
typename FUN>
1130 Filter (SRC&& dataSrc, FUN&& filterFun)
1131 : SRC{move (dataSrc)}
1143 SRC::expandChildren();
1152 return bool(srcIter());
1155 typename SRC::reference
1173 return unConst(*
this);
1179 return not
bool{predicate_};
1188 if (isDisabled())
return;
1189 while (srcIter() and not predicate_(srcIter()))
1218 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
1224 template<
typename FUN>
1226 :
_Filter{move (dataSrc), forward<FUN> (filterFun)}
1233 template<
typename COND>
1237 remouldFilter (forward<COND> (conjunctiveClause)
1238 ,[](
auto first,
auto chain)
1240 return [=](
auto& val)
1249 template<
typename COND>
1253 remouldFilter (forward<COND> (conjunctiveClause)
1254 ,[](
auto first,
auto chain)
1256 return [=](
auto& val)
1265 template<
typename COND>
1269 remouldFilter (forward<COND> (disjunctiveClause)
1270 ,[](
auto first,
auto chain)
1272 return [=](
auto& val)
1281 template<
typename COND>
1285 remouldFilter (forward<COND> (disjunctiveClause)
1286 ,[](
auto first,
auto chain)
1288 return [=](
auto& val)
1300 auto dummy = [](
auto){
return false; };
1301 remouldFilter (dummy
1302 ,[](
auto currentFilter,
auto)
1304 return [=](
auto& val)
1306 return not currentFilter(val);
1312 template<
typename COND>
1316 remouldFilter (forward<COND> (entirelyDifferentPredicate)
1317 ,[](
auto,
auto chain)
1319 return [=](
auto& val)
1330 _Filter::predicate_ =
nullptr;
1350 template<
typename COND,
class COMB>
1354 static_assert_isPredicate<COND,SRC>();
1356 if (_Filter::isDisabled())
1357 _Filter::predicate_ = ACCEPT_ALL;
1359 _Filter::predicate_ = buildCombinedClause (_Filter::predicate_
1362 _Filter::pullFilter();
1382 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
1385 using Cond = function<bool(SRC&)>;
1387 Cond whileCondition_;
1394 template<
typename FUN>
1396 :
Core{move (dataSrc)}
1406 return Core::checkPoint()
1407 and whileCondition_(Core::srcIter());
1425 template<
typename VAL>
1431 virtual VAL* expandChildren() =0;
1432 virtual size_t depth()
const =0;
1449 using Val =
typename SRC::value_type;
1453 using Parent::Parent;
1456 expandChildren()
override 1458 Parent::wrappedIter().expandChildren();
1459 return Parent::wrappedIter()? & *Parent::wrappedIter()
1464 depth()
const override 1466 return Parent::wrappedIter().depth();
1493 template<
typename VAL>
1507 VAL* changedResult = expandableSource().expandChildren();
1508 this->resetPos (changedResult);
1514 return expandableSource().depth();
1527 move (opaqueSrcPipeline)})}
1531 expandableSource()
const 1533 if (not this->source())
1534 throw error::State (
"operating on a disabled default constructed IterExplorer" 1535 ,error::LUMIERA_ERROR_BOTTOM_VALUE);
1537 auto source = unConst(
this)->source().get();
1582 static_assert(can_IterForEach<SRC>::value,
"Lumiera Iterator required as source");
1586 using value_type =
typename meta::ValueTypeBinding<SRC>::value_type;
1587 using reference =
typename meta::ValueTypeBinding<SRC>::reference;
1588 using pointer =
typename meta::ValueTypeBinding<SRC>::pointer;
1643 using ExpandedChildren =
typename iter_explorer::_FunTraits<FUN,SRC>::Res;
1646 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1667 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1677 return this->expand (forward<FUN> (expandFunctor))
1695 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1715 using Product =
typename iter_explorer::_FunTraits<FUN,SRC>::Res;
1718 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1736 using Value =
typename meta::ValueTypeBinding<SRC>::value_type;
1738 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1755 template<
class FGRP,
class FAGG>
1759 using GroupVal =
typename iter_explorer::_FunTraits<FGRP,SRC>::Res;
1761 static_assert (meta::is_BinaryFun<FAGG>());
1763 using Aggregate =
typename meta::RefTraits<ArgType1>::Value;
1766 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1769 ,forward<FGRP> (groupFun)
1770 ,forward<FAGG> (aggFun)});
1774 template<
class FGRP>
1778 using Value =
typename meta::ValueTypeBinding<SRC>::value_type;
1779 return groupedBy (forward<FGRP> (groupFun)
1780 ,[](Value& agg, Value
const& val){ agg += val; }
1792 iter_explorer::static_assert_isPredicate<FUN,SRC>();
1795 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1808 iter_explorer::static_assert_isPredicate<FUN,SRC>();
1811 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1812 using ArgType =
typename iter_explorer::_FunTraits<FUN,SRC>::Arg;
1815 ,[whileCond = forward<FUN>(untilCond)](ArgType val)
1817 return not whileCond(val);
1833 iter_explorer::static_assert_isPredicate<FUN,SRC>();
1836 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1863 iter_explorer::static_assert_isPredicate<FUN,SRC>();
1866 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1875 return mutableFilter (iter_explorer::ACCEPT_ALL);
1891 template<
template<
class>
class LAY>
1895 using ResCore = LAY<SRC>;
1896 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1907 using Val =
typename meta::ValueTypeBinding<SRC>::value_type;
1908 static_assert (not std::is_pointer_v<Val>);
1909 return IterExplorer::transform ([](Val& ref){
return &ref; });
1916 using Ptr =
typename meta::ValueTypeBinding<SRC>::value_type;
1917 return IterExplorer::transform ([](Ptr ptr){
return *ptr; });
1924 template<
template<
typename>
class SET =std::set>
1928 using Value =
typename meta::ValueTypeBinding<SRC>::value_type;
1930 using ResIter =
typename _DecoratorTraits<ResCore>::SrcIter;
1932 for (
auto& val : *
this)
1933 buffer.emplace (val);
1961 return SRC {move(*
this)};
1970 foreach (FUN&& consumer)
1973 SRC& pipeline = *
this;
1974 for ( ; pipeline; ++pipeline)
1975 consumeFun (pipeline);
1989 ,
typename COMB =decltype(std::plus<>())
1990 ,
typename VAL =
typename iter_explorer::_ReduceTraits<SRC,FUN>::ResVal>
1993 ,COMB junctor =COMB()
1994 ,VAL seedVal =VAL())
1998 VAL sum{move(seedVal)};
1999 IterExplorer::foreach ([&](SRC& srcIter){ sum = junctor (sum, accessVal(srcIter)); });
2021 static_assert (std::is_constructible<bool,value_type>());
2022 SRC& pipeline = *
this;
2023 for ( ; pipeline; ++pipeline)
2033 static_assert (std::is_constructible<bool,value_type>());
2034 SRC& pipeline = *
this;
2035 for ( ; pipeline; ++pipeline)
2047 template<
template<
typename>
class CON =std::vector>
2051 CON<value_type> con{};
2058 effuse (CON&& sink) -> CON
2060 CON con{move(sink)};
2070 for (
auto& val : *
this)
2071 con.push_back (val);
2086 template<
class SRC,
class SEL =
void>
2095 using BaseAdapter = SRC;
2100 template<
class SRC,
class SEL =
void>
2103 using RawIter = SRC;
2109 using RawIter =
typename COR::TAG_CheckedCore_Raw;
2118 template<
class SRC,
class SEL =
void>
2121 using RawIter = SRC;
2126 using _SrcIT =
typename SRC::TAG_IterExplorer_Src;
2127 using RawIter =
typename _UnstripAdapter<_SrcIT>::RawIter;
2191 using RawIter =
typename _PipelineDetector<IT>::RawIter;
2192 using SrcIter =
typename _DecoratorTraits<RawIter>::SrcIter;
2193 using Base =
typename _BaseDetector<SrcIter>::BaseAdapter;
IterSourceIter(ISO &externalSource)
link to existing IterSource (without memory management)
typename _Trait::YieldRes YieldRes
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
static auto wrap(function< Sig > rawFun)
void expandChildren()
refresh state when other layers manipulate the source sequence.
Detect if given source was already built by IterExplorer;.
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 expandChildren()
collaboration: recurse into nested scope
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)
size_t depth() const
collaboration: number of nested scopes
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.
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)
Detect or otherwise add BaseAdapter.
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 ...
Detect and remove typical adapter layers added by a preceding IterExplorer usage. ...
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.
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.
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.
auto deduplicate()
preconfigured decorator to materialise, sort and deduplicate all source elements. ...
adapt to a functor, which accesses the source iterator or embedded "state core"
auto derefPtr()
preconfigured transformer to dereference pointers into references
SRC TAG_IterExplorer_BaseAdapter
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
Adapter to »piggy-back« a STL iterable container inline and expose it as »state core«.
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.
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.