implement equality comparison on CommandImpl level
This commit is contained in:
parent
eefc40acb7
commit
07de2a767b
9 changed files with 162 additions and 28 deletions
76
src/lib/meta/maybe-compare.hpp
Normal file
76
src/lib/meta/maybe-compare.hpp
Normal 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
|
||||
|
|
@ -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
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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_))
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue