diff --git a/src/lib/iter-chain-search.hpp b/src/lib/iter-chain-search.hpp index 3de00ddea..0c58798ce 100644 --- a/src/lib/iter-chain-search.hpp +++ b/src/lib/iter-chain-search.hpp @@ -75,13 +75,12 @@ namespace iter { .mutableFilter(); } - template + template auto - buildExplorer (SRC&& dataSource, FUN&& expandFunctor) + buildExplorer (SRC&& dataSource) { return buildSearchFilter (forward (dataSource)) - .expand (forward (expandFunctor)) - .expandAll(); + .expand ([](auto it){ return it; }); // child iterator starts as copy of current level iterator } /** @@ -97,16 +96,9 @@ namespace iter { struct _IterChainSetup { using Filter = decltype( buildSearchFilter(std::declval()).asIterator() ); - using StepFunctor = std::function; - - using Pipeline = decltype( buildExplorer (std::declval(), std::declval()) ); - - static Pipeline - configurePipeline (SRC&& dataSource, StepFunctor step) - { - return buildExplorer(forward (dataSource), move (step)); - } + using Pipeline = decltype( buildExplorer (std::declval()) ); + using StepFunctor = std::function; }; }//(End)type construction helpers @@ -134,9 +126,6 @@ namespace iter { using Filter = typename _Trait::Filter; using Step = typename _Trait::StepFunctor; - /** @internal access embedded filter sub-Pipeline */ - Filter& filter() { return *this; } - /** Storage for a sequence of filter configuration functors */ std::vector stepChain_; @@ -150,9 +139,7 @@ namespace iter { template explicit IterChainSearch (SEQ&& srcData) - : _Base{_Trait::configurePipeline (forward (srcData) - ,[this](Filter const& curr){ return configureFilterChain(curr); })} - , stepChain_{} + : _Base{buildExplorer (forward (srcData))} { // mark initial pristine state _Base::disableFilter(); } @@ -161,13 +148,28 @@ namespace iter { using _Base::_Base; + /* === adapted iteration control API === */ + void + iterNext() + { + _Base::__throw_if_empty(); + while (_Base::depth() < stepChain_.size() // Backtracking loop: attempt to establish all conditions + and _Base::checkPoint()) // possibly trying further combinations until success: + { + _Base::expandChildren(); // create copy of current filter embedded into child level + stepChain_[_Base::depth()] (_Base::accessCurrentChildIter()); // invoke step functor to reconfigure this filter... + _Base::dropExhaustedChildren(); // which thereby might become empty + } + } + + /** configure additional chained search condition. - * @param a functor `Filter const& -> filter`, which takes a current filter configuration, - * returning a copy from this configuration, possibly configured differently. + * @param a manipulation functor `void(Filter&)`, which works on the current filter + * to possibly change its configuration. * @note the given functor, lambda or function reference will be wrapped and adapted * to conform to the required function signature. When using a generic lambda, - * the argument type `Filter const&` is assumed + * the argument type `Filter&` is assumed * @remarks the additional chained search condition given here will be applied _after_ * matching all other conditions already in the filter chain. Each such condition * is used to _filter_ the underlying source iterator, i.e. pull it until finding @@ -185,7 +187,7 @@ namespace iter { Step nextStep{forward (configureSearchStep)}; if (_Base::isDisabled()) - this-> filter() = move (nextStep (*this)); // apply first step immediately + nextStep (*this); // apply first step immediately else { stepChain_.emplace_back (move (nextStep)); // append all further steps into the chain... @@ -207,10 +209,9 @@ namespace iter { search (FUN&& filterPredicate) { addStep ([predicate{forward (filterPredicate)}] - (Filter filter) // note: filter taken by value - { + (Filter& filter) + { // manipulte current filter configuration filter.setNewFilter (predicate); - return filter; // return copy of the original state with changed filter }); return move(*this); } @@ -239,17 +240,6 @@ namespace iter { _Base::disableFilter(); return move(*this); } - - private: - Filter - configureFilterChain (Filter const& currentFilterState) - { - uint depth = this->depth(); - if (depth < stepChain_.size()) - return stepChain_[depth](currentFilterState); // augmented copy - else - return Filter{}; // empty filter indicates recursion end - } }; diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index 47d9a9685..ebba4bbc4 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -722,12 +722,6 @@ namespace lib { or *expansions_; } - bool - hasChildren() const - { - return 0 < depth(); - } - void incrementCurrent() { @@ -737,12 +731,28 @@ namespace lib { ++(*this); } + + protected: + /** @internal accessor for downstream layers to allow close collaboration */ + ResIter& + accessCurrentChildIter() + { + REQUIRE (hasChildren()); + return *expansions_; + } + void dropExhaustedChildren() { while (not invariant()) ++expansions_; } + + bool + hasChildren() const + { + return 0 < depth(); + } }; diff --git a/tests/library/iter-chain-search-test.cpp b/tests/library/iter-chain-search-test.cpp index f8cca854a..bfd03e752 100644 --- a/tests/library/iter-chain-search-test.cpp +++ b/tests/library/iter-chain-search-test.cpp @@ -160,7 +160,6 @@ namespace test{ string currVal = *filter; filter.setNewFilter ([=](string const& val){ return val != currVal; }); - return filter; }); ///////////////////////////////////////////////////TODO WIP cout << materialise (search) < - + + + + + + + + + + + + + + + + + + + + + + +

+ ...nach der »reinen Lehre« +

+ +
+ + + + + + + + + + + + + + + + + + + + +

+ ...insofern wir nämlich zwingend auf den jeweilign Kind-Iterator zugreifen müssen. +

+

+ Nicht nur auf den aktuellen Wert (=dereferenzierter Iterator, d.h. die Funktion yield()) +

+ + +
+ + +
+
@@ -32262,6 +32321,105 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ weil ich dann auf dem IterChainSearch unmittelbar die builder-Funktionen definieren kann +

+ + +
+
+
+
+ + + + + + +

+ konfiguriert danach direkt den Filter +

+ + +
+ + + + + + + + + + +

+ ...weil der Basis-Iterator (also der Template-Parameter SRC) +

+

+ explizit und absichtlich einen anderen Typ haben könnte, als der expandierte Kind-Iterator. +

+

+ Das ist ein wesentliches Feature dieses Expander-Designs, würde aber leider eine +

+

+ komplett generische Accessor-Funktion unmöglich machen (das Template würde in +

+

+ einem Solchen Fall insgesamt vom Compiler zurückgewiesen) +

+ + +
+ +
+
+
+
+
+