diff --git a/src/lib/meta/maybe-compare.hpp b/src/lib/meta/maybe-compare.hpp new file mode 100644 index 000000000..385e90bd3 --- /dev/null +++ b/src/lib/meta/maybe-compare.hpp @@ -0,0 +1,76 @@ +/* + MAYBE-COMPARE.hpp - guarded invocation of comparisons + + Copyright (C) Lumiera.org + 2009, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +#ifndef LUMIERA_META_MAYBE_COMPARE_H +#define LUMIERA_META_MAYBE_COMPARE_H + + +#include "lib/functor-util.hpp" + +#include + + +namespace lumiera { +namespace typelist { + + using std::tr1::function; + + /** + * Trait template for invoking equality comparison. + * This allows to treat some types specifically.... + */ + template + struct Comparator + { + static bool + equals (X const& x1, X const& x2) + { + return x1 == x2; + } + }; + + /** while the boost function implementation doesn't provide comparison, + * we'll use our private hack, which at least detects equivalence + * in \em some cases... */ + template + struct Comparator > + { + static bool + equals (function const& f1, function const& f2) + { + return util::rawComparison(f1,f2); + } + + }; + + + template + inline bool + equals_safeInvoke (X const& x1, X const& x2) + { + return Comparator::equals(x1,x2); + } + + +}} // namespace lumiera::typelist +#endif diff --git a/src/lib/meta/trait.hpp b/src/lib/meta/trait.hpp index 608888561..323ae0ac4 100644 --- a/src/lib/meta/trait.hpp +++ b/src/lib/meta/trait.hpp @@ -32,12 +32,10 @@ #include #include - + namespace lumiera { namespace typelist { - - using boost::enable_if; - using boost::is_arithmetic; + /** Trait template for detecting if a type can be converted to string. @@ -66,7 +64,7 @@ namespace typelist { template struct can_lexical2string { - enum { value = is_arithmetic::value + enum { value = boost::is_arithmetic::value }; }; diff --git a/src/proc/control/command-argument-holder.hpp b/src/proc/control/command-argument-holder.hpp index 2a2226593..c18e18b06 100644 --- a/src/proc/control/command-argument-holder.hpp +++ b/src/proc/control/command-argument-holder.hpp @@ -238,6 +238,14 @@ namespace control { return memento_->getState(); } + bool + equals (CmdClosure const& other) const + { + const ArgumentHolder* toCompare = dynamic_cast (&other); + return (toCompare) + && (*this == *toCompare); + } + /// Supporting equality comparisons... friend bool operator== (ArgumentHolder const& a1, ArgumentHolder const& a2) diff --git a/src/proc/control/command-closure.hpp b/src/proc/control/command-closure.hpp index 1519ec113..7bef71521 100644 --- a/src/proc/control/command-closure.hpp +++ b/src/proc/control/command-closure.hpp @@ -74,6 +74,7 @@ #include "lib/meta/function-closure.hpp" #include "lib/meta/function-erasure.hpp" #include "lib/meta/tuple.hpp" +#include "lib/meta/maybe-compare.hpp" #include "lib/format.hpp" #include "lib/util.hpp" #include "proc/control/argument-erasure.hpp" @@ -98,6 +99,7 @@ namespace control { using lumiera::typelist::StoreFunction; using lumiera::typelist::NullType; + using lumiera::typelist::equals_safeInvoke; using lib::TypedAllocationManager; using util::unConst; using std::tr1::function; @@ -130,6 +132,7 @@ namespace control { virtual operator string() const =0; virtual bool isValid () const =0; ///< does this closure hold a valid argument tuple? virtual bool isCaptured () const =0; ///< does this closure hold captured UNDO state? + virtual bool equals (CmdClosure const&) const =0; ///< is equivalent to the given other closure? virtual void bindArguments (Arguments&) =0; ///< store a set of parameter values within this closure virtual void invoke (CmdFunctor const&) =0; ///< invoke functor using the stored parameter values virtual PClo createClone (TypedAllocationManager&) =0; ///< create clone allocation without disclosing concrete type @@ -172,7 +175,7 @@ namespace control { friend bool compare (ParamAccessor const& p1, ParamAccessor const& p2) { - return (p1.element() == p2.element()) + return equals_safeInvoke (p1.element(), p2.element()) && compare ( static_cast(p1) , static_cast(p2) ); } @@ -272,10 +275,17 @@ namespace control { bool isValid () const { return true; } bool isCaptured() const { return false; } - /// Supporting equality comparisons... friend bool operator== (Closure const& c1, Closure const& c2) { return compare (c1.params_, c2.params_); } friend bool operator!= (Closure const& c1, Closure const& c2) { return ! (c1 == c2); } + + bool + equals (CmdClosure const& other) const + { + const Closure* toCompare = dynamic_cast (&other); + return (toCompare) + && (*this == *toCompare); + } }; diff --git a/src/proc/control/command-impl.hpp b/src/proc/control/command-impl.hpp index 0a2161cbe..f209ba3c0 100644 --- a/src/proc/control/command-impl.hpp +++ b/src/proc/control/command-impl.hpp @@ -188,10 +188,18 @@ namespace control { } - ////////////////////////////////////////////////////////////////////////////////////TODO comparisons - - private: - + + friend bool + operator== (CommandImpl const& ci1, CommandImpl const& ci2) + { + return (ci1.do_ == ci2.do_) + && (ci1.undo_ == ci2.undo_) + && (ci1.defaultPatt_ == ci2.defaultPatt_) + && (ci1.canExec() == ci2.canExec()) + && (ci1.canUndo() == ci2.canUndo()) + && (ci1.pClo_->equals(*ci2.pClo_)) + ; + } }; diff --git a/src/proc/control/command.cpp b/src/proc/control/command.cpp index 98d888c57..4c10f658f 100644 --- a/src/proc/control/command.cpp +++ b/src/proc/control/command.cpp @@ -239,6 +239,14 @@ namespace control { } + bool + Command::equivalentImpl (Command const& c1, Command const& c2) + { + return c1.impl() == c2.impl(); + } + + + /** diagnostics: shows the commandID, if any, * and the degree of definition of this command */ diff --git a/src/proc/control/command.hpp b/src/proc/control/command.hpp index f4f00fe5b..502d77bbf 100644 --- a/src/proc/control/command.hpp +++ b/src/proc/control/command.hpp @@ -177,6 +177,7 @@ namespace control { private: void setArguments (Arguments&); + static bool equivalentImpl (Command const&, Command const&); }; @@ -205,7 +206,9 @@ namespace control { operator== (Command const& c1, Command const& c2) { return (!c1 && !c2) - || ( c1 && c2 && (&c1.impl() == &c2.impl())); + || ( c1 && c2 && ( &c1.impl() == &c2.impl() + || Command::equivalentImpl (c1,c2) + )); } inline bool diff --git a/src/proc/control/memento-tie.hpp b/src/proc/control/memento-tie.hpp index c9a1052d9..bbab73313 100644 --- a/src/proc/control/memento-tie.hpp +++ b/src/proc/control/memento-tie.hpp @@ -41,6 +41,7 @@ #define CONTROL_MEMENTO_TIE_H #include "lib/bool-checkable.hpp" +#include "lib/meta/maybe-compare.hpp" #include "lib/meta/function-closure.hpp" #include "proc/control/command-signature.hpp" #include "lib/functor-util.hpp" @@ -57,6 +58,7 @@ namespace control { using boost::equality_comparable; using lumiera::typelist::func::bindLast; using lumiera::typelist::func::chained; + using lumiera::typelist::equals_safeInvoke; LUMIERA_ERROR_DECLARE (MISSING_MEMENTO); ///< Undo functor not yet usable, because no undo state has been captured @@ -202,7 +204,7 @@ namespace control { ) && (m1.isCaptured_ == m2.isCaptured_) // either both not captured or identical state && (!m1.isCaptured_ - || (m1.memento_ == m2.memento_)); + || equals_safeInvoke (m1.memento_, m2.memento_)); } }; diff --git a/tests/components/proc/control/command-argument-test.cpp b/tests/components/proc/control/command-argument-test.cpp index a1a2c6562..2b9368bd3 100644 --- a/tests/components/proc/control/command-argument-test.cpp +++ b/tests/components/proc/control/command-argument-test.cpp @@ -77,26 +77,48 @@ namespace test { Tracker (TY init = TY()) : element_(init) { ++instanceCnt; } Tracker (Tracker const& otr) : element_(otr.element_) { ++instanceCnt; } ~Tracker() { --instanceCnt; } - - TY& - operator* () - { - return element_; - } - - friend ostream& - operator<< (ostream& out, const Tracker& tra) - { - return out << tra.element_; - } - - operator string() const { return element_; } + + TY& + operator* () + { + return element_; + } + + operator string() const { return element_; } + + friend ostream& + operator<< (ostream& out, const Tracker& tra) + { + return out << tra.element_; + } + + friend bool + operator== (Tracker const& tra1, Tracker const& tra2) + { + return tra1.element_ == tra2.element_; + } }; template int Tracker::instanceCnt (0); + /** Dummy custom memento datatype + * @note memento needs to be equality comparable + */ + struct Sint5 + { + int i[5]; + + friend bool + operator== (Sint5 const& i1, Sint5 const& i2) + { + return i1.i == i2.i; + } + }; + + + /* === functions to implement test-"operation" & UNDO === */ void @@ -184,7 +206,6 @@ namespace test { typedef Tracker