diff --git a/src/lib/itertools.hpp b/src/lib/itertools.hpp index 47b91f797..fa925977f 100644 --- a/src/lib/itertools.hpp +++ b/src/lib/itertools.hpp @@ -358,6 +358,20 @@ namespace lib { * modified, current head of iteration gets re-evaluated * and possible fast-forwarded to the next element * satisfying the now extended filter condition. + * @note changing the condition modifies a given iterator in place. + * Superficially this might look as if the storage remains + * the same, but in fact we're adding a lambda closure, + * which the runtime usually allocates on the heap, + * holding the previous functor and a second functor + * for the added clause. + * @warning the addition of disjunctive and negated clauses might + * actually weaken the filter condition. Yet still there is + * \em no reset of the source iterator, i.e. we don't + * re-evaluate from start, but just from current head. + * Which means we might miss elements in the already consumed + * part of the source sequence, which theoretically would + * pass the now altered filter condition. + * @see IterTools_test::verify_filterExtension */ template class ExtensibleFilterIter @@ -396,6 +410,64 @@ namespace lib { reEvaluate(); return *this; } + + template + ExtensibleFilterIter& + andNotFilter (COND conjunctiveClause) + { + function& filter = this->core_.predicate_; + + filter = [=](Val val) + { + return filter(val) + and not conjunctiveClause(val); + }; + reEvaluate(); + return *this; + } + + template + ExtensibleFilterIter& + orFilter (COND disjunctiveClause) + { + function& filter = this->core_.predicate_; + + filter = [=](Val val) + { + return filter(val) + or disjunctiveClause(val); + }; + reEvaluate(); + return *this; + } + + template + ExtensibleFilterIter& + orNotFilter (COND disjunctiveClause) + { + function& filter = this->core_.predicate_; + + filter = [=](Val val) + { + return filter(val) + or not disjunctiveClause(val); + }; + reEvaluate(); + return *this; + } + + ExtensibleFilterIter& + flipFilter () + { + function& filter = this->core_.predicate_; + + filter = [=](Val val) + { + return not filter(val); + }; + reEvaluate(); + return *this; + } }; diff --git a/tests/12metaprogramming.tests b/tests/12metaprogramming.tests index 39bce4b62..ca708eb61 100644 --- a/tests/12metaprogramming.tests +++ b/tests/12metaprogramming.tests @@ -206,15 +206,18 @@ END TEST "Lumiera Iterator Tools" IterTools_test 20 <