implement equality comparison on CommandImpl level

This commit is contained in:
Fischlurch 2009-10-05 04:29:06 +02:00
parent eefc40acb7
commit 07de2a767b
9 changed files with 162 additions and 28 deletions

View file

@ -0,0 +1,76 @@
/*
MAYBE-COMPARE.hpp - guarded invocation of comparisons
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
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 <tr1/functional>
namespace lumiera {
namespace typelist {
using std::tr1::function;
/**
* Trait template for invoking equality comparison.
* This allows to treat some types specifically....
*/
template<typename X>
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<typename SIG>
struct Comparator<function<SIG> >
{
static bool
equals (function<SIG> const& f1, function<SIG> const& f2)
{
return util::rawComparison(f1,f2);
}
};
template<typename X>
inline bool
equals_safeInvoke (X const& x1, X const& x2)
{
return Comparator<X>::equals(x1,x2);
}
}} // namespace lumiera::typelist
#endif

View file

@ -32,12 +32,10 @@
#include <boost/utility/enable_if.hpp>
#include <string>
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<typename X>
struct can_lexical2string
{
enum { value = is_arithmetic<X>::value
enum { value = boost::is_arithmetic<X>::value
};
};

View file

@ -238,6 +238,14 @@ namespace control {
return memento_->getState();
}
bool
equals (CmdClosure const& other) const
{
const ArgumentHolder* toCompare = dynamic_cast<const ArgumentHolder*> (&other);
return (toCompare)
&& (*this == *toCompare);
}
/// Supporting equality comparisons...
friend bool
operator== (ArgumentHolder const& a1, ArgumentHolder const& a2)

View file

@ -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<BASE>(p1)
, static_cast<BASE>(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<const Closure*> (&other);
return (toCompare)
&& (*this == *toCompare);
}
};

View file

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

View file

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

View file

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

View file

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

View file

@ -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<typename TY>
int Tracker<TY>::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<Time> TTime;
typedef Tracker<string> Tstr;
typedef struct{ int i[5]; } Sint5;