TreeExplorer: refactor Filter in a similar way

This commit is contained in:
Fischlurch 2018-09-09 15:27:25 +02:00
parent 1e657acbff
commit 36d79be8b2
3 changed files with 77 additions and 64 deletions

View file

@ -562,6 +562,24 @@ namespace lib {
};
template<typename FUN, typename SRC>
inline void
static_assert_isPredicate()
{
using Res = typename _FunTraits<FUN,SRC>::Res;
static_assert(std::is_constructible<bool, Res>::value, "Functor must be a predicate");
}
template<typename FUN, typename SRC>
inline void
static_assert_isSourceResultCompatible()
{
using ResIter = typename _DecoratorTraits<typename _FunTraits<FUN,SRC>::Res>::SrcIter;
static_assert (std::is_convertible<typename ResIter::value_type, typename SRC::value_type>::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<class SRC, class FUN>
template<class SRC>
class Filter
: public SRC
{
static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
using _Traits = _FunTraits<FUN,SRC>;
using Res = typename _Traits::Res;
static_assert(std::is_constructible<bool, Res>::value, "Functor must be a predicate");
protected:
using FilterPredicate = typename _Traits::Functor;
using FilterPredicate = function<bool(SRC&)>;
FilterPredicate predicate_;
@ -898,9 +913,10 @@ namespace lib {
Filter() =default;
// inherited default copy operations
template<typename FUN>
Filter (SRC&& dataSrc, FUN&& filterFun)
: SRC{move (dataSrc)}
, predicate_{forward<FUN> (filterFun)}
, predicate_{_FunTraits<FUN,SRC>::template adaptFunctor<SRC> (forward<FUN> (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<SRC&>`.
* 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<class SRC, class FUN>
template<class SRC>
class MutableFilter
: public Filter<SRC, typename _FunTraits<FUN,SRC>::Functor>
: public Filter<SRC>
{
using _Traits = _FunTraits<FUN,SRC>;
using FilterPredicate = typename _Traits::Functor;
using _Base = Filter<SRC,FilterPredicate>;
using _Filter = Filter<SRC>;
static_assert(can_IterForEach<SRC>::value, "Lumiera Iterator required as source");
using Res = typename _Traits::Res;
static_assert(std::is_constructible<bool, Res>::value, "Functor must be a predicate");
public:
MutableFilter() =default;
// inherited default copy operations
template<typename FUN>
MutableFilter (SRC&& dataSrc, FUN&& filterFun)
: _Base{move (dataSrc), FilterPredicate{forward<FUN> (filterFun)}}
: _Filter{move (dataSrc), forward<FUN> (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<COND,SRC>;
using Res = typename _ChainTraits::Res;
static_assert(std::is_constructible<bool, Res>::value, "Chained Functor must be a predicate");
static_assert_isPredicate<COND,SRC>();
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<COND> (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<COND,SRC>::template adaptFunctor<SRC> (forward<COND> (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<SRC, FUN>;
iter_explorer::static_assert_isPredicate<FUN,SRC>();
using ResCore = iter_explorer::Filter<SRC>;
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
return TreeExplorer<ResIter> (ResCore {move(*this), forward<FUN>(filterPredicate)});
@ -1483,7 +1486,9 @@ namespace lib {
auto
mutableFilter (FUN&& filterPredicate)
{
using ResCore = iter_explorer::MutableFilter<SRC, FUN>;
iter_explorer::static_assert_isPredicate<FUN,SRC>();
using ResCore = iter_explorer::MutableFilter<SRC>;
using ResIter = typename _DecoratorTraits<ResCore>::SrcIter;
return TreeExplorer<ResIter> (ResCore {move(*this), forward<FUN>(filterPredicate)});

View file

@ -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));
}

View file

@ -31126,6 +31126,10 @@
<icon BUILTIN="broken-line"/>
</node>
</node>
<node COLOR="#338800" CREATED="1536499475717" ID="ID_1987289240" MODIFIED="1536499534632" TEXT="Nach Refactoring TreeExplorer nun m&#xf6;glich">
<arrowlink COLOR="#5cb3a1" DESTINATION="ID_1315131204" ENDARROW="Default" ENDINCLINATION="691;0;" ID="Arrow_ID_86390894" STARTARROW="None" STARTINCLINATION="167;37;"/>
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
</node>
@ -31239,7 +31243,8 @@
<node CREATED="1536420678842" ID="ID_1524886712" MODIFIED="1536420681830" TEXT="Ergebnis-Typ"/>
</node>
</node>
<node CREATED="1536420803778" ID="ID_1315131204" MODIFIED="1536420809629" TEXT="Funktions-Signatur verbergen">
<node CREATED="1536420803778" ID="ID_1315131204" MODIFIED="1536499525208" TEXT="Funktions-Signatur verbergen">
<linktarget COLOR="#5cb3a1" DESTINATION="ID_1315131204" ENDARROW="Default" ENDINCLINATION="691;0;" ID="Arrow_ID_86390894" SOURCE="ID_1987289240" STARTARROW="None" STARTINCLINATION="167;37;"/>
<node CREATED="1536420811265" ID="ID_1167994865" MODIFIED="1536420823683" TEXT="reduzieren auf res(SRC)"/>
<node CREATED="1536420824983" ID="ID_784540518" MODIFIED="1536420836185" TEXT="konkrete Funktion in Adapter setzen"/>
<node CREATED="1536420932944" ID="ID_512498364" MODIFIED="1536420940219" TEXT="ArgAccessor beim Aufruf">
@ -31266,6 +31271,9 @@
</richcontent>
</node>
</node>
<node CREATED="1536499557658" ID="ID_1939855291" MODIFIED="1536499572569" TEXT="daf&#xfc;r verschwindet konkreter Funktor-Typ vom Template">
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
</node>
@ -31370,11 +31378,11 @@
</node>
<node CREATED="1536455947209" ID="ID_1054869208" MODIFIED="1536455959131" TEXT="innerer Funktor ist aber direkt dort eingebettet"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1536453368676" ID="ID_1560078731" MODIFIED="1536453372397" TEXT="Filter">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1536453368676" ID="ID_1560078731" MODIFIED="1536499292336" TEXT="Filter">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1536453373605" ID="ID_1544724438" MODIFIED="1536453376828" TEXT="MutableFilter">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1536453373605" ID="ID_1544724438" MODIFIED="1536499295024" TEXT="MutableFilter">
<icon BUILTIN="button_ok"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1536453408359" ID="ID_63715215" MODIFIED="1536453414663" TEXT="Anpassen an Expander">
<icon BUILTIN="flag-yellow"/>