implemented comparison on function erasure, pending test

This commit is contained in:
Fischlurch 2009-10-05 00:49:37 +02:00
parent 5068016805
commit 231278bafe
7 changed files with 109 additions and 99 deletions

View file

@ -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

View file

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

View file

@ -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

View file

@ -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.

View file

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

View file

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

View file

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