diff --git a/src/lib/meta/function-erasure.hpp b/src/lib/meta/function-erasure.hpp index c267be175..167d6c0bc 100644 --- a/src/lib/meta/function-erasure.hpp +++ b/src/lib/meta/function-erasure.hpp @@ -57,8 +57,10 @@ #include "lib/error.hpp" #include "lib/bool-checkable.hpp" #include "lib/opaque-holder.hpp" +#include "lib/functor-util.hpp" #include +#include namespace lumiera { @@ -67,6 +69,33 @@ namespace typelist{ using std::tr1::function; using util::unConst; + namespace { // comparison access helper functions + + typedef void* RawFunc; ///////////////////TODO + + template + RawFunc + accessRaw (FH funHolder) + { + ////////////////TODO + }; + + template + struct IsEqualTo + { + RawFunc ofunc_; + + IsEqualTo (FH o) + : ofunc_(o) + { } + + bool + operator() (RawFunc func) + { + return util::rawComparison(func, ofunc_); + } + }; + } /****************************************************** @@ -86,12 +115,19 @@ namespace typelist{ */ template struct FunErasure - : FH + : boost::equality_comparable< FunErasure + , FH > { template FunErasure (FUN const& functor) : FH(functor) { } + + friend bool + operator== (FunErasure const& fe1, FunErasure const& fe2) + { + return fe1.query (IsEqualTo (fe2)); + } }; @@ -195,6 +231,13 @@ namespace typelist{ return *reinterpret_cast (funP_); } + template + bool + query (FUN predicate) + { + return predicate (funP_); + } + bool isValid() const diff --git a/src/lib/opaque-holder.hpp b/src/lib/opaque-holder.hpp index f91cf9265..5ebee8aa3 100644 --- a/src/lib/opaque-holder.hpp +++ b/src/lib/opaque-holder.hpp @@ -475,6 +475,21 @@ 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 + RET + apply (FUN query) + { + BaseP asBase = buff().getBase(); + ASSERT (asBase); + return query (asBase); + } + + bool empty() const { diff --git a/src/proc/control/command-mutation.hpp b/src/proc/control/command-mutation.hpp index b1bc12787..4621c03aa 100644 --- a/src/proc/control/command-mutation.hpp +++ b/src/proc/control/command-mutation.hpp @@ -51,6 +51,7 @@ #include "proc/control/command-closure.hpp" #include "proc/control/memento-tie.hpp" +#include #include #include @@ -72,6 +73,7 @@ namespace control { * concealed (erased) on the interface. */ class Mutation + : public boost::equality_comparable { const CmdFunctor func_; @@ -92,6 +94,14 @@ namespace control { clo.invoke (func_); } + + + /// Supporting equality comparisons... + friend bool + operator== (Mutation const& m1, Mutation const& m2) + { + return (m1.func_ == m2.func_); + } }; diff --git a/tests/components/proc/control/command-equality-test.cpp b/tests/components/proc/control/command-equality-test.cpp index a2472f0bc..1c8bdd44d 100644 --- a/tests/components/proc/control/command-equality-test.cpp +++ b/tests/components/proc/control/command-equality-test.cpp @@ -85,16 +85,14 @@ namespace test { struct Testframe ///< test data set { - char param; - - function o_Fun; - function c_Fun; - function u_Fun; + Sig_oper & o_Fun; + Sig_capt & c_Fun; + Sig_undo & u_Fun; }; - Testframe data1 = {'a', &oper_1, &capt_1, &undo_1}; - Testframe data2 = {'z', &oper_2, &capt_2, &undo_2}; + Testframe data1 = {oper_1, capt_1, undo_1}; + Testframe data2 = {oper_2, capt_2, undo_2}; Testframe nullD; } @@ -168,13 +166,13 @@ namespace test { void verifyClosureEquality() { - ArgHolder a1 (tuple::make (data1.param)); - ArgHolder a2 (tuple::make (data2.param)); + ArgHolder a1 (tuple::make ('a')); + ArgHolder a2 (tuple::make ('z')); ASSERT (a1 == a1); ASSERT (a1 != a2); ASSERT (a2 != a1); - TypedArguments newArgs (tuple::make (data2.param)); + TypedArguments newArgs (tuple::make ('z')); a1.bindArguments(newArgs); ASSERT (a1 == a2); ASSERT (a2 == a1); diff --git a/tests/lib/meta/function-erasure-test.cpp b/tests/lib/meta/function-erasure-test.cpp index 3320dcc72..6db81fc3b 100644 --- a/tests/lib/meta/function-erasure-test.cpp +++ b/tests/lib/meta/function-erasure-test.cpp @@ -84,6 +84,20 @@ namespace test { check_FunctPtrHolder(Efp(testFunc),Efp(&testFunc), Efp(returnIt)); check_VoidPtrHolder(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt)); + check_Comparisons (Efun(testFunc), Efun(bindFunc)); + check_Comparisons (Efun(testFunc), Efun(pAplFunc)); + check_Comparisons (Efun(testFunc), Efun(membFunc)); + check_Comparisons (Efun(testFunc), Efun(getterFunc)); + check_Comparisons (Efun(bindFunc), Efun(pAplFunc)); + check_Comparisons (Efun(bindFunc), Efun(membFunc)); + check_Comparisons (Efun(bindFunc), Efun(getterFunc)); + check_Comparisons (Efun(pAplFunc), Efun(membFunc)); + check_Comparisons (Efun(pAplFunc), Efun(getterFunc)); + check_Comparisons (Efun(membFunc), Efun(getterFunc)); + + check_Comparisons (Efp(testFunc), Efun(returnIt)); + check_Comparisons (Evoid(testFunc), Evoid(returnIt)); + detect_unboundFunctor(Efun(testFunc), Efun(getterFunc), Efun(membFunc)); detect_unboundFunctor(Efp(testFunc),Efp(&testFunc), Efp(returnIt)); detect_unboundFunctor(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt)); @@ -208,7 +222,20 @@ namespace test { template void - detect_unboundFunctor(HOL h1, HOL h2, HOL h3) + check_Comparisons (HOL h1, HOL h2) + { + ASSERT (h1 != h2); + ASSERT (h2 != h1); + + HOL clone (h1); + ASSERT (clone == h1); + ASSERT (clone != h2); + } + + + template + void + detect_unboundFunctor (HOL h1, HOL h2, HOL h3) { // fabricate an unbound functor...