diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index b78cfd8b5..c26e859d5 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -303,6 +303,15 @@ namespace lib { IterSourceIter (ISO* heap_allocated_IterSource) : ISO::iterator{ISO::build (heap_allocated_IterSource)} { } + + using Source = ISO; + + Source& + source() + { + REQUIRE (ISO::iterator::isValid()); + return static_cast (*ISO::iterator::source()); + } }; }//(End) namespace iter_explorer : basic iterator wrappers @@ -319,6 +328,7 @@ namespace lib { using meta::_Fun; using std::__and_; using std::__not_; + using std::is_base_of; using std::is_convertible; using std::remove_reference_t; using meta::can_IterForEach; @@ -401,14 +411,14 @@ namespace lib { }; template - struct _DecoratorTraits, ISO>>> + struct _DecoratorTraits, ISO>>> { using SrcIter = iter_explorer::IterSourceIter; using SrcVal = typename ISO::value_type; }; template - struct _DecoratorTraits, ISO>>> + struct _DecoratorTraits, ISO>>> { using SrcIter = iter_explorer::IterSourceIter; using SrcVal = typename ISO::value_type; @@ -491,6 +501,17 @@ namespace lib { static auto build() { return [](auto& iter) { return *iter; }; } }; + /** adapt to a functor collaborating with an IterSource based iterator pipeline */ + template + struct ArgAccessor, typename IT::Source> + , is_base_of, remove_reference_t> + > >> + { + using Source = typename IT::Source; + + static auto build() { return [](auto& iter) -> Source& { return iter.source(); }; } + }; + /** holder for the suitably adapted _expansion functor_ */ struct Functor diff --git a/tests/library/iter-tree-explorer-test.cpp b/tests/library/iter-tree-explorer-test.cpp index 30dd26ffa..205cd73e7 100644 --- a/tests/library/iter-tree-explorer-test.cpp +++ b/tests/library/iter-tree-explorer-test.cpp @@ -849,8 +849,17 @@ namespace test{ - /** @test ability to wrap and handle IterSource based iteration - * + + /** @test ability to wrap and handle IterSource based iteration. + * Contrary to the preceding test case, here the point is to _base the whole pipleine_ + * on a data source accessible through the IterSource (VTable based) interface. The notable + * point with this technique is the ability to use some _extended sub interface of IterSource_ + * and to rely on this interface to implement some functor bound into the TreeExplorer pipeline. + * Especially this allows to delegate the "child expansion" through such an interface and just + * return a compatible IterSource as result. This way, the opaque implementation gains total + * freedom regarding the concrete implementation of the "child series" iterator. In fact, + * it may even use a different implementation on each level or even on each individual call; + * only the result type and thus the base interface need to match. */ void verify_IterSource() @@ -874,7 +883,7 @@ namespace test{ virtual PrivateSource* expandChildren() const override { - return new VerySpecivicIter{*wrappedIter() - 1}; + return new VerySpecivicIter{*wrappedIter() - 2}; } uint @@ -892,45 +901,44 @@ namespace test{ - VerySpecivicIter vsit{4}; - // attach to an IterSource living here in local scope... - auto ii = treeExplore(vsit); + VerySpecivicIter vsit{5}; + + // ...and build a child expansion on top, which calls through the PrivateSource-API + // Effectively this means we do not know the concrete type of the "expanded children" iterator, + // only that it adheres to the same IterSource sub-interface as used on the base iterator. + auto ii = treeExplore(vsit) + .expand ([](PrivateSource& source){ return source.expandChildren(); }); CHECK (not isnil (ii)); + CHECK (5 == *ii); + CHECK (5 == vsit.currentVal()); + ++ii; CHECK (4 == *ii); CHECK (4 == vsit.currentVal()); + + CHECK (0 == ii.depth()); + ii.expandChildren(); // note: calls through source's VTable to invoke VerySpecificIter::expandChildren() + CHECK (1 == ii.depth()); + + CHECK (2 == *ii); ++ii; + CHECK (1 == *ii); + + CHECK (3 == vsit.currentVal()); + CHECK (1 == ii.depth()); + ++ii; + CHECK (0 == ii.depth()); CHECK (3 == *ii); CHECK (3 == vsit.currentVal()); - -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888 - auto jj = ii.explore([](PrivateSource& source){ return source.expandChildren(); }); - - CHECK (3 == *jj); - CHECK (3 == vsit.currentVal()); - - CHECK (0 == jj.depth()); - jj.expandChildren(); - CHECK (1 == jj.depth()); - - CHECK (2 == *jj); - ++jj; - CHECK (1 == *jj); - + ++ii; + CHECK (2 == *ii); CHECK (2 == vsit.currentVal()); - CHECK (1 == jj.depth()); - ++jj; - CHECK (0 == jj.depth()); - CHECK (2 == *jj); - CHECK (2 == vsit.currentVal()); - ++jj; - CHECK (1 == *jj); + ++ii; + CHECK (1 == *ii); CHECK (1 == vsit.currentVal()); - ++jj; - CHECK (isnil (jj)); - CHECK (0 == vsit.currentVal()); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #888 + ++ii; + CHECK (isnil (ii)); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index aab077306..1bd5d100d 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -5149,7 +5149,7 @@ - + @@ -5892,7 +5892,7 @@ - + @@ -6364,17 +6364,17 @@ - + - + - - + + - - + + @@ -6749,7 +6749,7 @@ - + @@ -7065,13 +7065,16 @@ - - + + - - + + + + + @@ -8130,9 +8133,9 @@ - + - +