implemented comparison on function erasure, pending test
This commit is contained in:
parent
5068016805
commit
231278bafe
7 changed files with 109 additions and 99 deletions
|
|
@ -152,7 +152,7 @@ namespace util { ////////////TODO: refactor it. But probably not directly into n
|
|||
* "different" erroneously, due to garbage in
|
||||
* the internal functor data's storage */
|
||||
template<typename SIG>
|
||||
bool
|
||||
inline bool
|
||||
rawComparison (function<SIG> const& f1,
|
||||
function<SIG> const& f2)
|
||||
{
|
||||
|
|
@ -165,13 +165,24 @@ namespace util { ////////////TODO: refactor it. But probably not directly into n
|
|||
/** catch-all for the comparison: functors with
|
||||
* different base type are always "different" */
|
||||
template<typename SIG1, typename SIG2>
|
||||
bool
|
||||
inline bool
|
||||
rawComparison (function<SIG1> const&,
|
||||
function<SIG2> const&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/** variant with unchecked access */
|
||||
inline bool
|
||||
rawComparison (void* f1, void* f2)
|
||||
{
|
||||
typedef HijackedFunction * HijP;
|
||||
|
||||
return (!f1 && !f2)
|
||||
|| *reinterpret_cast<HijP> (f1)
|
||||
== *reinterpret_cast<HijP> (f2);
|
||||
}
|
||||
|
||||
|
||||
} // namespace util
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@
|
|||
#include "lib/functor-util.hpp"
|
||||
|
||||
#include <tr1/functional>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
|
|
@ -69,33 +68,6 @@ namespace typelist{
|
|||
using std::tr1::function;
|
||||
using util::unConst;
|
||||
|
||||
namespace { // comparison access helper functions
|
||||
|
||||
typedef void* RawFunc; ///////////////////TODO
|
||||
|
||||
template<class FH>
|
||||
RawFunc
|
||||
accessRaw (FH funHolder)
|
||||
{
|
||||
////////////////TODO
|
||||
};
|
||||
|
||||
template<class FH>
|
||||
struct IsEqualTo
|
||||
{
|
||||
RawFunc ofunc_;
|
||||
|
||||
IsEqualTo (FH o)
|
||||
: ofunc_(o)
|
||||
{ }
|
||||
|
||||
bool
|
||||
operator() (RawFunc func)
|
||||
{
|
||||
return util::rawComparison(func, ofunc_);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
|
|
@ -115,8 +87,7 @@ namespace typelist{
|
|||
*/
|
||||
template<class FH>
|
||||
struct FunErasure
|
||||
: boost::equality_comparable< FunErasure
|
||||
, FH >
|
||||
: FH
|
||||
{
|
||||
template<typename FUN>
|
||||
FunErasure (FUN const& functor)
|
||||
|
|
@ -124,9 +95,9 @@ namespace typelist{
|
|||
{ }
|
||||
|
||||
friend bool
|
||||
operator== (FunErasure const& fe1, FunErasure const& fe2)
|
||||
operator!= (FunErasure const& fer1, FunErasure const& fer2)
|
||||
{
|
||||
return fe1.query (IsEqualTo (fe2));
|
||||
return !(fer1==fer2); // use equality defined by FH
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -168,6 +139,14 @@ namespace typelist{
|
|||
{
|
||||
return get<function<SIG> >();
|
||||
}
|
||||
|
||||
|
||||
friend bool
|
||||
operator== (StoreFunction const& o1,
|
||||
StoreFunction const& o2)
|
||||
{
|
||||
return util::rawComparison (o1.asBase(),o2.asBase());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -199,6 +178,14 @@ namespace typelist{
|
|||
REQUIRE (fun);
|
||||
return *fun;
|
||||
}
|
||||
|
||||
|
||||
friend bool
|
||||
operator== (StoreFunPtr const& o1,
|
||||
StoreFunPtr const& o2)
|
||||
{
|
||||
return o1.asBase() == o2.asBase();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -231,19 +218,19 @@ namespace typelist{
|
|||
return *reinterpret_cast<SIG*> (funP_);
|
||||
}
|
||||
|
||||
template<class FUN>
|
||||
bool
|
||||
query (FUN predicate)
|
||||
{
|
||||
return predicate (funP_);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
isValid() const
|
||||
{
|
||||
return funP_;
|
||||
}
|
||||
|
||||
friend bool
|
||||
operator== (StoreUncheckedFunPtr const& o1,
|
||||
StoreUncheckedFunPtr const& o2)
|
||||
{
|
||||
return unConst(o1).funP_ == unConst(o2).funP_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -359,6 +359,15 @@ namespace lib {
|
|||
ref.buff().clone (storage_);
|
||||
}
|
||||
|
||||
BaseP
|
||||
asBase () const ///< @internal backdoor e.g. for comparisons
|
||||
{
|
||||
BaseP asBase = buff().getBase();
|
||||
ASSERT (asBase);
|
||||
return asBase;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
|
@ -462,9 +471,7 @@ namespace lib {
|
|||
|
||||
// second try: maybe we can perform a dynamic downcast
|
||||
// or direct conversion to the actual target type.
|
||||
BaseP asBase = buff().getBase();
|
||||
ASSERT (asBase);
|
||||
SUB* content = AccessPolicy::template access<SUB> (asBase);
|
||||
SUB* content = AccessPolicy::template access<SUB> (asBase());
|
||||
if (content)
|
||||
return *content;
|
||||
|
||||
|
|
@ -475,20 +482,6 @@ namespace lib {
|
|||
}
|
||||
|
||||
|
||||
/** invoke a query function on the embedded object,
|
||||
* accessing it as through the common base type.
|
||||
* @note this accessor doesn't require any knowledge
|
||||
* about the concrete type of the target object
|
||||
*/
|
||||
template<typename RET, typename FUN>
|
||||
RET
|
||||
apply (FUN query)
|
||||
{
|
||||
BaseP asBase = buff().getBase();
|
||||
ASSERT (asBase);
|
||||
return query (asBase);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
empty() const
|
||||
|
|
|
|||
|
|
@ -227,6 +227,13 @@ namespace util {
|
|||
return const_cast<OBJ*> (o);
|
||||
}
|
||||
|
||||
template<class OBJ>
|
||||
OBJ&
|
||||
unConst (OBJ const& ro)
|
||||
{
|
||||
return const_cast<OBJ&> (ro);
|
||||
}
|
||||
|
||||
|
||||
/** compare plain object identity,
|
||||
* bypassing any custom comparison operators.
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@
|
|||
#include "proc/control/command-closure.hpp"
|
||||
#include "proc/control/memento-tie.hpp"
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -73,7 +72,6 @@ namespace control {
|
|||
* concealed (erased) on the interface.
|
||||
*/
|
||||
class Mutation
|
||||
: public boost::equality_comparable<Mutation>
|
||||
{
|
||||
const CmdFunctor func_;
|
||||
|
||||
|
|
@ -102,6 +100,12 @@ namespace control {
|
|||
{
|
||||
return (m1.func_ == m2.func_);
|
||||
}
|
||||
|
||||
friend bool
|
||||
operator!= (Mutation const& m1, Mutation const& m2)
|
||||
{
|
||||
return !(m1==m2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -78,23 +78,13 @@ namespace test {
|
|||
typedef string Sig_capt(char);
|
||||
typedef void Sig_undo(char,string);
|
||||
|
||||
typedef function<Sig_oper> Fun_o;
|
||||
typedef function<Sig_capt> Fun_c;
|
||||
typedef function<Sig_undo> Fun_u;
|
||||
|
||||
typedef Tuple<Types<char> > ArgTuple;
|
||||
typedef Closure<Sig_oper> ArgHolder;
|
||||
typedef MementoTie<Sig_oper, string> MemHolder;
|
||||
|
||||
|
||||
struct Testframe ///< test data set
|
||||
{
|
||||
Sig_oper & o_Fun;
|
||||
Sig_capt & c_Fun;
|
||||
Sig_undo & u_Fun;
|
||||
};
|
||||
|
||||
|
||||
Testframe data1 = {oper_1, capt_1, undo_1};
|
||||
Testframe data2 = {oper_2, capt_2, undo_2};
|
||||
|
||||
Testframe nullD;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -140,9 +130,16 @@ namespace test {
|
|||
void
|
||||
verifyMutationEquality()
|
||||
{
|
||||
Mutation mut1 (data1.o_Fun);
|
||||
Mutation muti (data1.o_Fun);
|
||||
Mutation mut2 (data2.o_Fun);
|
||||
Fun_o oFun_1 (oper_1);
|
||||
Fun_o oFun_2 (oper_2);
|
||||
Fun_o oFun_empty;
|
||||
|
||||
Fun_u uFun_1 (undo_1);
|
||||
Fun_u uFun_empty;
|
||||
|
||||
Mutation mut1 (oFun_1);
|
||||
Mutation muti (oFun_1);
|
||||
Mutation mut2 (oFun_2);
|
||||
ASSERT (mut1 == mut1);
|
||||
ASSERT (mut1 == muti);
|
||||
ASSERT (muti == mut1);
|
||||
|
|
@ -151,15 +148,15 @@ namespace test {
|
|||
ASSERT (muti != mut2);
|
||||
ASSERT (mut2 != muti);
|
||||
|
||||
Mutation umu (nullD.o_Fun);
|
||||
Mutation umu (oFun_empty); // empty operation function
|
||||
ASSERT (mut1 != umu);
|
||||
|
||||
Mutation omu (nullD.u_Fun);
|
||||
ASSERT (omu != umu);
|
||||
ASSERT (omu != muti);
|
||||
Mutation mut_u0 (uFun_empty); // empty undo function
|
||||
ASSERT (mut_u0 != umu);
|
||||
ASSERT (mut_u0 != muti);
|
||||
|
||||
omu = Mutation(data1.u_Fun);
|
||||
ASSERT (omu != muti);
|
||||
Mutation mut_u1 (uFun_1);
|
||||
ASSERT (mut_u0 != mut_u1); // function signatures differing
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -185,19 +182,19 @@ namespace test {
|
|||
ASSERT (abuff1 != abuff2);
|
||||
abuff2.bindArguments(newArgs);
|
||||
ASSERT (abuff1 == abuff2);
|
||||
UndoMutation umu1 (abuff1.tie (data1.u_Fun, data1.c_Fun));
|
||||
ASSERT (abuff1 == abuff2); // not detected, as the new memento holder isn't valid yet
|
||||
UndoMutation umu1 (abuff1.tie (undo_1, capt_1));
|
||||
ASSERT (abuff1 == abuff2); // not detected, as the new memento holder isn't valid yet
|
||||
|
||||
UndoMutation umu2 (abuff1.tie (data1.u_Fun, data2.c_Fun)); // note: using different capture function!
|
||||
UndoMutation umu2 (abuff1.tie (undo_1, capt_2)); // note: using different capture function!
|
||||
ASSERT (abuff1 == abuff2);
|
||||
|
||||
umu1.captureState(a1);
|
||||
umu2.captureState(a1);
|
||||
ASSERT (abuff1 != abuff2); // and now the different state (due to the differing capture function) is detected
|
||||
|
||||
umu2 = UndoMutation(abuff1.tie (data1.u_Fun, data1.c_Fun)); // re-bind, now using the "right" capture function
|
||||
UndoMutation umu3 (abuff1.tie (undo_1, capt_1)); // now using the "right" capture function
|
||||
ASSERT (abuff1 != abuff2);
|
||||
umu2.captureState(a1);
|
||||
umu3.captureState(a1);
|
||||
ASSERT (abuff1 == abuff2); // same functions, same memento state
|
||||
}
|
||||
|
||||
|
|
@ -205,10 +202,18 @@ namespace test {
|
|||
void
|
||||
verifyMementoEquality()
|
||||
{
|
||||
MemHolder m11 (data1.u_Fun, data1.c_Fun);
|
||||
MemHolder m12 (data1.u_Fun, data2.c_Fun);
|
||||
MemHolder m21 (data2.u_Fun, nullD.c_Fun); // note: unbound capture function
|
||||
MemHolder m22 (data2.u_Fun, data2.c_Fun);
|
||||
Fun_u uFun_1 (undo_1);
|
||||
Fun_u uFun_2 (undo_2);
|
||||
Fun_c cFun_1 (capt_1);
|
||||
Fun_c cFun_2 (capt_2);
|
||||
Fun_c cFun_empty;
|
||||
|
||||
Fun_c empty_c;
|
||||
|
||||
MemHolder m11 (uFun_1, cFun_1);
|
||||
MemHolder m12 (uFun_1, cFun_2);
|
||||
MemHolder m21 (uFun_2, cFun_empty); // note: unbound capture function
|
||||
MemHolder m22 (uFun_2, cFun_2);
|
||||
|
||||
ASSERT ( (m11 == m11));
|
||||
ASSERT (!(m11 != m11));
|
||||
|
|
@ -255,14 +260,14 @@ namespace test {
|
|||
verifyCommandEquality()
|
||||
{
|
||||
CommandDef (COMMAND1)
|
||||
.operation (data1.o_Fun)
|
||||
.captureUndo (data1.c_Fun)
|
||||
.undoOperation (data1.u_Fun)
|
||||
.operation (oper_1)
|
||||
.captureUndo (capt_1)
|
||||
.undoOperation (undo_1)
|
||||
;
|
||||
CommandDef (COMMAND2)
|
||||
.operation (data2.o_Fun)
|
||||
.captureUndo (data2.c_Fun)
|
||||
.undoOperation (data2.u_Fun)
|
||||
.operation (oper_2)
|
||||
.captureUndo (capt_2)
|
||||
.undoOperation (undo_2)
|
||||
;
|
||||
|
||||
Command c1 = Command::get(COMMAND1);
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ namespace test {
|
|||
check_Comparisons (Efun(pAplFunc), Efun(getterFunc));
|
||||
check_Comparisons (Efun(membFunc), Efun(getterFunc));
|
||||
|
||||
check_Comparisons (Efp(testFunc), Efun(returnIt));
|
||||
check_Comparisons (Efp(testFunc), Efp(returnIt));
|
||||
check_Comparisons (Evoid(testFunc), Evoid(returnIt));
|
||||
|
||||
detect_unboundFunctor(Efun(testFunc), Efun(getterFunc), Efun(membFunc));
|
||||
|
|
@ -224,6 +224,9 @@ namespace test {
|
|||
void
|
||||
check_Comparisons (HOL h1, HOL h2)
|
||||
{
|
||||
ASSERT (h1 == h1); ASSERT (!(h1 != h1));
|
||||
ASSERT (h2 == h2); ASSERT (!(h2 != h2));
|
||||
|
||||
ASSERT (h1 != h2);
|
||||
ASSERT (h2 != h1);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue