diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index b3a18bbe0..15b6f0b11 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -562,6 +562,24 @@ namespace lib { }; + template + inline void + static_assert_isPredicate() + { + using Res = typename _FunTraits::Res; + static_assert(std::is_constructible::value, "Functor must be a predicate"); + } + + template + inline void + static_assert_isSourceResultCompatible() + { + using ResIter = typename _DecoratorTraits::Res>::SrcIter; + static_assert (std::is_convertible::value, + "the iterator from the expansion must yield compatible values"); + } + + /** * @internal Base of pipe processing decorator chain. @@ -879,17 +897,14 @@ namespace lib { * The filter predicate and thus the source iterator is evaluated _eagerly_, to establish the * *invariant* of this class: _if a "current element" exists, it has already been approved._ */ - template + template class Filter : public SRC { static_assert(can_IterForEach::value, "Lumiera Iterator required as source"); - using _Traits = _FunTraits; - using Res = typename _Traits::Res; - static_assert(std::is_constructible::value, "Functor must be a predicate"); protected: - using FilterPredicate = typename _Traits::Functor; + using FilterPredicate = function; FilterPredicate predicate_; @@ -898,9 +913,10 @@ namespace lib { Filter() =default; // inherited default copy operations + template Filter (SRC&& dataSrc, FUN&& filterFun) : SRC{move (dataSrc)} - , predicate_{forward (filterFun)} + , predicate_{_FunTraits::template adaptFunctor (forward (filterFun))} { pullFilter(); // initially pull to establish the invariant } @@ -947,7 +963,7 @@ namespace lib { bool isDisabled() const { - return not predicate_.boundFunction; + return not bool{predicate_}; } /** @note establishes the invariant: @@ -979,34 +995,22 @@ namespace lib { * @remarks filter predicates can be specified in a wide variety of forms, and will be adapted * automatically. This flexibility also holds for any of the additional clauses provided * for remoulding the filter. Especially this means that functors of different kinds can - * be mixed and combined. To allow for this flexibility, we need to drive the _base class_ - * with the most general form of a predicate functor, corresponding to `bool`. - * Hereby we exploit the fact that the _wrapped filter,_ i.e. the Functor type constructed - * in the _FunTraits traits, boils down to that most generic form, adapting the arguments - * automatically. Thus the initial functor, the one passed to the ctor of this class, is - * effectively wrapped twice, so it can be combined later on with any other form and - * shape of functor. And since everything is inline, the compiler will remove any - * overhead resulting from this redundant wrapping. + * be mixed and combined. */ - template + template class MutableFilter - : public Filter::Functor> + : public Filter { - using _Traits = _FunTraits; - using FilterPredicate = typename _Traits::Functor; - using _Base = Filter; - + using _Filter = Filter; static_assert(can_IterForEach::value, "Lumiera Iterator required as source"); - using Res = typename _Traits::Res; - static_assert(std::is_constructible::value, "Functor must be a predicate"); - public: MutableFilter() =default; // inherited default copy operations + template MutableFilter (SRC&& dataSrc, FUN&& filterFun) - : _Base{move (dataSrc), FilterPredicate{forward (filterFun)}} + : _Filter{move (dataSrc), forward (filterFun)} { } @@ -1110,7 +1114,7 @@ namespace lib { void disableFilter() { - _Base::predicate_.boundFunction = nullptr; + _Filter::predicate_ = nullptr; } @@ -1134,21 +1138,18 @@ namespace lib { void remouldFilter (COND&& additionalClause, COMB buildCombinedClause) { - using _ChainTraits = _FunTraits; - using Res = typename _ChainTraits::Res; - static_assert(std::is_constructible::value, "Chained Functor must be a predicate"); + static_assert_isPredicate(); - using WrappedPredicate = typename _Base::FilterPredicate; - using ChainPredicate = typename _ChainTraits::Functor; + using WrappedPredicate = typename _Filter::FilterPredicate; - WrappedPredicate& firstClause = _Base::predicate_; // pick up the existing filter predicate - ChainPredicate chainClause{forward (additionalClause)}; // wrap the extension predicate in a similar way - - if (_Base::isDisabled()) - firstClause.boundFunction = ACCEPT_ALL; + WrappedPredicate& firstClause = _Filter::predicate_; // pick up the existing filter predicate + WrappedPredicate chainClause{_FunTraits::template adaptFunctor (forward (additionalClause))}; + // wrap the extension predicate in a similar way + if (_Filter::isDisabled()) + _Filter::predicate_ = ACCEPT_ALL; - _Base::predicate_ = WrappedPredicate{buildCombinedClause (firstClause, chainClause)}; - _Base::pullFilter(); // pull to re-establish the Invariant + _Filter::predicate_ = buildCombinedClause (firstClause, chainClause); + _Filter::pullFilter(); // pull to re-establish the Invariant } }; @@ -1455,7 +1456,9 @@ namespace lib { auto filter (FUN&& filterPredicate) { - using ResCore = iter_explorer::Filter; + iter_explorer::static_assert_isPredicate(); + + using ResCore = iter_explorer::Filter; using ResIter = typename _DecoratorTraits::SrcIter; return TreeExplorer (ResCore {move(*this), forward(filterPredicate)}); @@ -1483,7 +1486,9 @@ namespace lib { auto mutableFilter (FUN&& filterPredicate) { - using ResCore = iter_explorer::MutableFilter; + iter_explorer::static_assert_isPredicate(); + + using ResCore = iter_explorer::MutableFilter; using ResIter = typename _DecoratorTraits::SrcIter; return TreeExplorer (ResCore {move(*this), forward(filterPredicate)}); diff --git a/tests/library/iter-tree-explorer-test.cpp b/tests/library/iter-tree-explorer-test.cpp index 914349475..08c3f799b 100644 --- a/tests/library/iter-tree-explorer-test.cpp +++ b/tests/library/iter-tree-explorer-test.cpp @@ -912,26 +912,26 @@ namespace test{ // verify enabling and disabling... - auto seq2 = treeExplore(CountDown{10}) - .mutableFilter(takeTrd); + seq = treeExplore(CountDown{10}) + .mutableFilter(takeTrd); - CHECK (9 == *seq2); - seq2.disableFilter(); - CHECK (9 == *seq2); - ++seq2; - CHECK (8 == *seq2); - seq2.andNotFilter (takeEve); - CHECK (7 == *seq2); - ++seq2; - CHECK (5 == *seq2); - seq2.disableFilter(); - CHECK (5 == *seq2); - ++seq2; - CHECK (4 == *seq2); - ++seq2; - CHECK (3 == *seq2); - seq2.flipFilter(); // everything rejected - CHECK (isnil (seq2)); + CHECK (9 == *seq); + seq.disableFilter(); + CHECK (9 == *seq); + ++seq; + CHECK (8 == *seq); + seq.andNotFilter (takeEve); + CHECK (7 == *seq); + ++seq; + CHECK (5 == *seq); + seq.disableFilter(); + CHECK (5 == *seq); + ++seq; + CHECK (4 == *seq); + ++seq; + CHECK (3 == *seq); + seq.flipFilter(); // everything rejected + CHECK (isnil (seq)); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index bab370530..b63eb3126 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -31126,6 +31126,10 @@ + + + + @@ -31239,7 +31243,8 @@ - + + @@ -31266,6 +31271,9 @@ + + + @@ -31370,11 +31378,11 @@ - - + + - - + +