Functions-Commands: discard the ability to compare functors for equivalence (closes #294)
evil hack R.I.P
This commit is contained in:
parent
94edb5de86
commit
ab90d9c71d
23 changed files with 46 additions and 970 deletions
|
|
@ -7,46 +7,6 @@ nonportable hacks, terrorism and other misdemeanour_
|
|||
Library
|
||||
-------
|
||||
|
||||
Equality of Functors
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
One of the more important recent additions to the C++ language are function objects.
|
||||
In addition to the features actually provided by the boost implementation, the tr1 report
|
||||
also requires function instances to implement an equality operator. Unfortunately the
|
||||
implementation approach choosen by boost makes a 100% correct implementation of
|
||||
comparision very dificult, if not impossible. Thus, the boost developers refused
|
||||
to implement this feature.
|
||||
|
||||
The bad news is that really using the power of opaque function objects quickly drove
|
||||
us (Lumiera) into a situation where such an equalty test and a hash calculation on
|
||||
function objects would be necessary. The whole point of using function objects is
|
||||
the ability to ``erase'' specific details, which has the downside that the resulting
|
||||
generic objects are opaque and often dificult to manage, when it comes to storing
|
||||
and retrieving objects building on such functors.
|
||||
|
||||
Thus I built an hack, based on the implementation details of boost::function.
|
||||
In +functor-util.hpp+ we define a +class HijackedFunction+, which has the same
|
||||
data layout as the original boost::function. After forcibly casting such an function
|
||||
(reference or pointer) into a +HijackedFunction+, we're able to inspect and evaluate
|
||||
the implementation pointers for equality comparison and hash value calculation.
|
||||
This approach works and actually detects copied functions to be _equal_, but is
|
||||
unable to pinpoint _equivalence_, e.g. functors bound to the same function with
|
||||
the same arguments through separate but otherwise identical invocations of +bind+.
|
||||
Besides, should boost or the standard library implementors eventually change the
|
||||
implementation, this workaround will break.
|
||||
|
||||
post C++11
|
||||
^^^^^^^^^^
|
||||
As of this writing (1/2016), this still remains an unsolved issue. +
|
||||
The new standard _does indeed require a comparison_, but only a comparison against
|
||||
`nullptr`, which is equivalent to the `bool` conversion. It seems we need more.
|
||||
|
||||
WARNING: what we have here is a really evil hack, and even the notion of ``equality''
|
||||
is not correct. We admit that real equality can not be achieved with something
|
||||
like `std::function`, but in spite of that, we do have our own needs.
|
||||
|
||||
[red]#TODO# investigate what we _really_ need and come up with a better concept...
|
||||
|
||||
|
||||
Binding Placeholders
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
The standard allows function objects to be partially closed; this is achieved by
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
#include "lib/sync.hpp"
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/depend.hpp"
|
||||
#include "lib/functor-util.hpp"
|
||||
#include "common/instancehandle.hpp"
|
||||
#include "common/option.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
FUNCTOR-UTIL.hpp - collection of helpers for dealing with functors and signals
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, 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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/** @file functor-util.hpp
|
||||
** Collection of small helpers and utilities related to function objects.
|
||||
**
|
||||
** @todo combine with meta/function-closure.hpp and reorganise
|
||||
** @todo 2017 find out to what extent we still need that (looks obsolete)
|
||||
**
|
||||
** @see GuiSubsysDescriptor#start (guifacade.cpp)
|
||||
** @see MementoTie
|
||||
** @see functor-util-test.cpp
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef FUNCTOR_UTIL_H
|
||||
#define FUNCTOR_UTIL_H
|
||||
|
||||
#include "lib/hash-value.h"
|
||||
|
||||
#include <functional>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
|
||||
|
||||
namespace util { ////////////TODO: refactor namespace. But probably not directly into namespace lib. Needs some more consideration though
|
||||
|
||||
using std::function;
|
||||
using std::bind;
|
||||
using std::placeholders::_1;
|
||||
|
||||
namespace { // hiding some nasty details...
|
||||
|
||||
using lib::HashVal;
|
||||
using boost::hash_combine;
|
||||
|
||||
/**
|
||||
* This Class is used to bypass the access protection
|
||||
* and break into the tr1::function implementation.
|
||||
* Thus we can implement a raw comparison function,
|
||||
* as a replacement for the missing functor comparison
|
||||
* facility. (TR1 requires an operator==, but boost
|
||||
* seemingly doesn't provide it, because it can't
|
||||
* be done correctly/properly in all cases. See
|
||||
* the section "FAQ" in the documentation of
|
||||
* the boost/function library)
|
||||
*
|
||||
* The layout of this class is chosen to mimic that
|
||||
* of the boost function implementation, without all
|
||||
* the generic type decoration. For the comparison
|
||||
* we use a conservative approach, by requiring
|
||||
* the concrete invoker, the storage manager and
|
||||
* the actual function and argument data pointers
|
||||
* to be the same.
|
||||
* @todo 2017 is this still necessary today?
|
||||
*/
|
||||
class HijackedFunction
|
||||
: std::_Function_base
|
||||
{
|
||||
typedef void (*DummyInvoker) (void);
|
||||
DummyInvoker invoker_;
|
||||
|
||||
public:
|
||||
|
||||
friend bool
|
||||
operator== (HijackedFunction const& f1,
|
||||
HijackedFunction const& f2)
|
||||
{
|
||||
return (f1.invoker_ == f2.invoker_)
|
||||
&& (f1._M_manager == f2._M_manager)
|
||||
&& (f1._M_functor._M_unused._M_const_object ==
|
||||
f2._M_functor._M_unused._M_const_object );
|
||||
} // note: we don't cover any member pointer offset
|
||||
|
||||
friend HashVal
|
||||
hash_value (HijackedFunction const& fun)
|
||||
{
|
||||
HashVal hash(0);
|
||||
hash_combine (hash, fun.invoker_);
|
||||
hash_combine (hash, fun._M_manager);
|
||||
hash_combine (hash, fun._M_functor._M_unused._M_const_object);
|
||||
return hash; // note: member pointer offset part uncovered
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** temporary workaround: tr1/functional should define
|
||||
* public comparison operators for functor objects, but
|
||||
* in the implementation provided by boost 1.34 it doesn't.
|
||||
* To get at least \em some comparison capability, we do a
|
||||
* brute force comparison of the functor's internal data.
|
||||
* @note use with caution. This implementation relies on
|
||||
* internal details of boost/function; but it is
|
||||
* rather conservative and might deem functors
|
||||
* "different" erroneously, due to garbage in
|
||||
* the internal functor data's storage */
|
||||
template<typename SIG>
|
||||
inline bool
|
||||
rawComparison (function<SIG> const& f1,
|
||||
function<SIG> const& f2)
|
||||
{
|
||||
typedef HijackedFunction const& Hij;
|
||||
|
||||
return reinterpret_cast<Hij> (f1)
|
||||
== reinterpret_cast<Hij> (f2);
|
||||
}
|
||||
|
||||
/** catch-all for the comparison: functors with
|
||||
* different base type are always "different" */
|
||||
template<typename SIG1, typename SIG2>
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/** workaround to calculate a hash value for a given function object.
|
||||
* @note use with caution. This implementation relies on internal details
|
||||
* of boost/function; it can be expected to be rather conservative,
|
||||
* i.e. yielding different hash values for objects, which actually
|
||||
* are semantically equivalent.
|
||||
* @warning especially function objects bound to member functions aren't
|
||||
* fully supported. It \em may happen that we miss differences on the
|
||||
* offset part and only hash the "this" pointer on some platform.
|
||||
*/
|
||||
template<typename SIG>
|
||||
inline HashVal
|
||||
rawHashValue (function<SIG> const& fun)
|
||||
{
|
||||
typedef HijackedFunction const& Hij;
|
||||
|
||||
return hash_value (reinterpret_cast<Hij> (fun));
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
namespace std {
|
||||
|
||||
/** inject into std::tr1 to be picked up by ADL:
|
||||
* @return hash value of given functor
|
||||
* @note use with caution. Hash is calculated
|
||||
* relying on undocumented boost internals.
|
||||
*/
|
||||
// template<typename SIG>
|
||||
// inline lib::HashVal
|
||||
// hash_value (function<SIG> const& fun)
|
||||
// {
|
||||
// return util::rawHashValue (fun);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
#endif /*FUNCTOR_UTIL_H*/
|
||||
|
|
@ -58,7 +58,6 @@
|
|||
#include "lib/util.hpp"
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/opaque-holder.hpp"
|
||||
#include "lib/functor-util.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
|
|
@ -140,14 +139,6 @@ namespace meta{
|
|||
{
|
||||
return get<function<SIG>>();
|
||||
}
|
||||
|
||||
|
||||
friend bool
|
||||
operator== (StoreFunction const& o1,
|
||||
StoreFunction const& o2)
|
||||
{
|
||||
return util::rawComparison (o1.asBase(),o2.asBase());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -179,16 +170,6 @@ namespace meta{
|
|||
REQUIRE (fun);
|
||||
return *fun;
|
||||
}
|
||||
|
||||
|
||||
friend bool
|
||||
operator== (StoreFunPtr const& o1,
|
||||
StoreFunPtr const& o2)
|
||||
{
|
||||
void * *fun1 = reinterpret_cast<void**> (o1.asBase());
|
||||
void * *fun2 = reinterpret_cast<void**> (o2.asBase());
|
||||
return *fun1 == *fun2;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -224,12 +205,6 @@ namespace meta{
|
|||
explicit operator bool() const { return funP_; }
|
||||
bool isValid() const { return funP_; }
|
||||
|
||||
friend bool
|
||||
operator== (StoreUncheckedFunPtr const& o1,
|
||||
StoreUncheckedFunPtr const& o2)
|
||||
{
|
||||
return unConst(o1).funP_ == unConst(o2).funP_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,15 +30,11 @@
|
|||
#define LIB_META_MAYBE_COMPARE_H
|
||||
|
||||
|
||||
#include "lib/functor-util.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
|
||||
namespace lib {
|
||||
namespace meta{
|
||||
|
||||
using std::function;
|
||||
|
||||
/**
|
||||
* Trait template for invoking equality comparison.
|
||||
|
|
@ -54,19 +50,7 @@ namespace meta{
|
|||
}
|
||||
};
|
||||
|
||||
/** 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);
|
||||
}
|
||||
|
||||
};
|
||||
/* == add specialisations here == */
|
||||
|
||||
|
||||
template<typename X>
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ 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 bindArguments (lib::diff::Rec const&) =0; ///< store a set of parameter values, passed as GenNode sequence
|
||||
virtual void unbindArguments() =0; ///< discard any parameters and return to _unbound state_
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@
|
|||
** identity and usually located within the (pooled) storage managed by the
|
||||
** CommandRegistry. Client code gets access to a specific CommandImpl through
|
||||
** a Command instance, which is a small (refcounting smart-ptr) handle.
|
||||
**
|
||||
** //TODO
|
||||
**
|
||||
** @see Command
|
||||
** @see SteamDispatcher
|
||||
|
|
@ -246,26 +244,6 @@ namespace control {
|
|||
% canUndo()
|
||||
% (pClo_? string(*pClo_) : util::FAILURE_INDICATOR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
friend bool
|
||||
operator== (CommandImpl const& ci1, CommandImpl const& ci2)
|
||||
{
|
||||
return (ci1.do_ == ci2.do_)
|
||||
// and (ci1.undo_ == ci2.undo_) // causes failure regularly, due to the missing equality on boost::function. See Ticket #294
|
||||
and (ci1.defaultPatt_ == ci2.defaultPatt_)
|
||||
and (ci1.canExec() == ci2.canExec())
|
||||
and (ci1.canUndo() == ci2.canUndo())
|
||||
and (ci1.pClo_->equals(*ci2.pClo_))
|
||||
;
|
||||
}
|
||||
|
||||
friend bool
|
||||
operator!= (CommandImpl const& ci1, CommandImpl const& ci2)
|
||||
{
|
||||
return not (ci1==ci2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -83,21 +83,6 @@ namespace control {
|
|||
LERR_(UNBOUND_ARGUMENTS));
|
||||
clo.invoke (func_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Supporting equality comparisons...
|
||||
friend bool
|
||||
operator== (Mutation const& m1, Mutation const& m2)
|
||||
{
|
||||
return (m1.func_ == m2.func_);
|
||||
}
|
||||
|
||||
friend bool
|
||||
operator!= (Mutation const& m1, Mutation const& m2)
|
||||
{
|
||||
return not (m1==m2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ namespace control {
|
|||
using lib::meta::NullType;
|
||||
using lib::meta::buildTuple;
|
||||
|
||||
using lib::meta::equals_safeInvoke;
|
||||
using lib::TypedAllocationManager;
|
||||
using std::function;
|
||||
using std::ostream;
|
||||
|
|
@ -96,20 +95,11 @@ namespace control {
|
|||
|
||||
/////////////////////////////////////////////////////////////TICKET #798 : we need to pick up arguments from a lib::diff::Record.
|
||||
|
||||
|
||||
ostream&
|
||||
dump (ostream& output) const
|
||||
{
|
||||
return BASE::dump (output << element() << ',');
|
||||
}
|
||||
|
||||
friend bool
|
||||
compare (ParamAccessor const& p1, ParamAccessor const& p2)
|
||||
{
|
||||
return equals_safeInvoke (p1.element(), p2.element())
|
||||
&& compare ( static_cast<BASE>(p1)
|
||||
, static_cast<BASE>(p2) );
|
||||
}
|
||||
};
|
||||
|
||||
template<class TUP, uint n>
|
||||
|
|
@ -135,12 +125,6 @@ namespace control {
|
|||
{
|
||||
return output;
|
||||
}
|
||||
|
||||
friend bool
|
||||
compare (ParamAccessor const&, ParamAccessor const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -218,11 +202,6 @@ namespace control {
|
|||
else
|
||||
return dumped+")";
|
||||
}
|
||||
|
||||
|
||||
/// Supporting equality comparisons...
|
||||
friend bool operator== (OpClosure const& c1, OpClosure const& c2) { return compare (c1.params_, c2.params_); }
|
||||
friend bool operator!= (OpClosure const& c1, OpClosure const& c2) { return not (c1 == c2); }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -204,30 +204,6 @@ namespace control {
|
|||
{
|
||||
arguments_.template create<ArgHolder>();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
equals (CmdClosure const& other) const override
|
||||
{
|
||||
const SimpleClosure* toCompare = dynamic_cast<const SimpleClosure*> (&other);
|
||||
return (toCompare)
|
||||
and (*this == *toCompare);
|
||||
}
|
||||
|
||||
/// Supporting equality comparisons...
|
||||
friend bool
|
||||
operator== (SimpleClosure const& a1, SimpleClosure const& a2)
|
||||
{
|
||||
return (a1.arguments_->isValid() == a2.arguments_->isValid())
|
||||
and (*a1.arguments_ == *a2.arguments_)
|
||||
;
|
||||
}
|
||||
|
||||
friend bool
|
||||
operator!= (SimpleClosure const& a1, SimpleClosure const& a2)
|
||||
{
|
||||
return not (a1 == a2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -255,31 +255,6 @@ namespace control {
|
|||
{
|
||||
return memento_->getState();
|
||||
}
|
||||
|
||||
bool
|
||||
equals (CmdClosure const& other) const
|
||||
{
|
||||
const StorageHolder* toCompare = dynamic_cast<const StorageHolder*> (&other);
|
||||
return (toCompare)
|
||||
and (*this == *toCompare);
|
||||
}
|
||||
|
||||
/// Supporting equality comparisons...
|
||||
friend bool
|
||||
operator== (StorageHolder const& a1, StorageHolder const& a2)
|
||||
{
|
||||
return (a1.arguments_->isValid() == a2.arguments_->isValid())
|
||||
&& (*a1.arguments_ == *a2.arguments_)
|
||||
&& (a1.memento_->isValid() == a2.memento_->isValid())
|
||||
&& (*a1.memento_ == *a2.memento_)
|
||||
;
|
||||
}
|
||||
|
||||
friend bool
|
||||
operator!= (StorageHolder const& a1, StorageHolder const& a2)
|
||||
{
|
||||
return not (a1 == a2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -369,13 +369,6 @@ namespace control {
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
Command::equivalentImpl (Command const& c1, Command const& c2)
|
||||
{
|
||||
return c1.impl() == c2.impl();
|
||||
}
|
||||
|
||||
|
||||
Symbol
|
||||
Command::getID() const noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -223,7 +223,6 @@ namespace control {
|
|||
private:
|
||||
void setArguments (Arguments&);
|
||||
void setArguments (lib::diff::Rec const&);
|
||||
static bool equivalentImpl (Command const&, Command const&);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
#include "lib/meta/function-closure.hpp"
|
||||
#include "steam/control/command-signature.hpp"
|
||||
#include "lib/replaceable-item.hpp"
|
||||
#include "lib/functor-util.hpp"
|
||||
#include "lib/format-obj.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
|
|
@ -202,20 +201,6 @@ namespace control {
|
|||
/** for diagnostics: include format-util.hpp */
|
||||
operator std::string() const;
|
||||
|
||||
|
||||
/// Supporting equality comparisons...
|
||||
friend bool
|
||||
operator== (MementoTie const& m1, MementoTie const& m2)
|
||||
{
|
||||
return ((!m1.undo_ && !m2.undo_ && !m1.capture_ && !m2.capture_) // either no valid functions
|
||||
|| ( util::rawComparison(m1.undo_, m2.undo_ ) // or identical functions
|
||||
&& util::rawComparison(m1.capture_,m2.capture_ )
|
||||
)
|
||||
)
|
||||
&& (m1.isCaptured_ == m2.isCaptured_) // either both not captured or identical state
|
||||
&& (!m1.isCaptured_
|
||||
|| equals_safeInvoke (m1.memento_, m2.memento_));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/hash-value.h"
|
||||
#include "lib/functor-util.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
|
|
|||
|
|
@ -213,7 +213,6 @@ namespace test {
|
|||
Tracker<string>::instanceCnt = 0;
|
||||
|
||||
createTuples (testTuples);
|
||||
checkArgumentComparison ();
|
||||
serialiseArgTuples (testTuples);
|
||||
testTuples.clear();
|
||||
|
||||
|
|
@ -291,50 +290,6 @@ namespace test {
|
|||
|
||||
|
||||
|
||||
/** @test verify the comparison operators */
|
||||
void
|
||||
checkArgumentComparison ()
|
||||
{
|
||||
StorageHolder<void(int,int), int> one, two;
|
||||
CHECK (one == two); // empty, identically typed argument holders -->equal
|
||||
|
||||
one.tie(dummyU,dummyC)
|
||||
.tieCaptureFunc()(1,9);
|
||||
CHECK (one != two); // now one contains captured UNDO state
|
||||
|
||||
two.tie(dummyU,dummyC)
|
||||
.tieCaptureFunc()(1,9);
|
||||
two.memento() = one.memento(); // put the same UNDO state in both
|
||||
CHECK (one == two); // ...makes them equal again
|
||||
|
||||
one.storeTuple (make_tuple (1,2));
|
||||
CHECK (one != two); // verify argument tuple comparison
|
||||
CHECK (two != one);
|
||||
CHECK (!isnil (one));
|
||||
CHECK ( isnil (two));
|
||||
|
||||
two.storeTuple (make_tuple (3,4));
|
||||
CHECK (!isnil (two));
|
||||
CHECK (one != two);
|
||||
CHECK (two != one);
|
||||
|
||||
one.storeTuple (make_tuple (1,4));
|
||||
CHECK (!isnil (one));
|
||||
CHECK (one != two);
|
||||
CHECK (two != one);
|
||||
|
||||
one.storeTuple (make_tuple (3,4));
|
||||
CHECK (!isnil (one));
|
||||
CHECK (one == two);
|
||||
CHECK (two == one);
|
||||
two.memento() = 12345;
|
||||
CHECK (!isnil (two));
|
||||
CHECK (one != two);
|
||||
CHECK (two != one);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** @test simulate a complete command lifecycle with regards to the
|
||||
* storage handling of the command parameters and state memento.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -137,7 +137,6 @@ namespace test {
|
|||
CHECK (orig && copy);
|
||||
CHECK (orig->canExec());
|
||||
CHECK (copy->canExec());
|
||||
CHECK (orig == copy);
|
||||
|
||||
|
||||
// prepare for command invocation on implementation level....
|
||||
|
|
@ -151,13 +150,11 @@ namespace test {
|
|||
long state_after_exec1 = command1::check_;
|
||||
CHECK (command1::check_ > 0);
|
||||
CHECK (orig->canUndo());
|
||||
CHECK (orig != copy);
|
||||
|
||||
CHECK (!copy->canUndo());
|
||||
testExec.exec (*copy, "Execute clone"); // EXEC 2
|
||||
CHECK (command1::check_ != state_after_exec1);
|
||||
CHECK (copy->canUndo());
|
||||
CHECK (copy != orig);
|
||||
|
||||
// invoke UNDO on the clone
|
||||
testExec.undo (*copy, "Undo clone"); // UNDO 2
|
||||
|
|
@ -166,8 +163,6 @@ namespace test {
|
|||
// invoke UNDO on original
|
||||
testExec.undo (*orig, "Undo original"); // UNDO 1
|
||||
CHECK (command1::check_ ==0);
|
||||
|
||||
CHECK (copy != orig);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -98,30 +98,15 @@ namespace test {
|
|||
|
||||
/*************************************************************************************//**
|
||||
* @test cover command equality detection.
|
||||
* Two commands are deemed equivalent, if they
|
||||
* - build on the same Mutation functors
|
||||
* - are either both incomplete or
|
||||
* - are bound to equivalent arguments
|
||||
* - hold equivalent undo state (memento)
|
||||
* To conduct this test, we set up two sets of functions, and then build both complete
|
||||
* command objects and command implementation facilities based on them.
|
||||
*
|
||||
* @note The hidden problem with those comparisons is the equivalence of function objects.
|
||||
* While required by TR1, unfortunately lib boost refuses to implement functor equality.
|
||||
* Which forces us to resort to a low level hack, based on internals of the boost function
|
||||
* implementation. This workaround reliably pinpoints differing functions, but sometimes
|
||||
* fails to detect equivalent functions under specific circumstances (e.g. when there is
|
||||
* binding involved, and / or the binders have been cloned). Bottom line: \c == is
|
||||
* reliable, \c != might be wrong.
|
||||
* Two commands are deemed equivalent, if they are based on the same CommandImpl record.
|
||||
* This means, we only rely on the _identity_ of those commands, but do not check the
|
||||
* _equivalence_ of their backing implementations. The latter can not be possibly
|
||||
* implemented in a totally airtight fashion, and for this reason, the C++ standard
|
||||
* decided not to support comparison between std::function objects.
|
||||
*
|
||||
* @see control::Command
|
||||
* @see control::CmdClosure
|
||||
* @see control::Mutation
|
||||
* @see control::UndoMutation
|
||||
* @see control::MementoTie
|
||||
* @see control::CommandImpl
|
||||
* @see command-basic-test.hpp
|
||||
* @see functor-util.hpp functor equality workaround
|
||||
*/
|
||||
class CommandEquality_test : public Test
|
||||
{
|
||||
|
|
@ -133,148 +118,6 @@ namespace test {
|
|||
CHECK (&capt_1 != &capt_2);
|
||||
CHECK (&undo_1 != &undo_2);
|
||||
|
||||
verifyMutationEquality();
|
||||
verifyMementoEquality();
|
||||
verifyClosureEquality();
|
||||
verifyCommandEquality();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
verifyMutationEquality()
|
||||
{
|
||||
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);
|
||||
CHECK (mut1 == mut1);
|
||||
CHECK (mut1 == muti);
|
||||
CHECK (muti == mut1);
|
||||
CHECK (mut1 != mut2);
|
||||
CHECK (mut2 != mut1);
|
||||
CHECK (muti != mut2);
|
||||
CHECK (mut2 != muti);
|
||||
|
||||
Mutation umu (oFun_empty); // empty operation function
|
||||
CHECK (mut1 != umu);
|
||||
|
||||
Mutation mut_u0 (uFun_empty); // empty undo function
|
||||
CHECK (mut_u0 != umu);
|
||||
CHECK (mut_u0 != muti);
|
||||
|
||||
Mutation mut_u1 (uFun_1);
|
||||
CHECK (mut_u0 != mut_u1); // function signatures differing
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verifyClosureEquality()
|
||||
{
|
||||
ArgHolder a1 (make_tuple ('a'));
|
||||
ArgHolder a2 (make_tuple ('a'));
|
||||
ArgHolder a3 (make_tuple ('z'));
|
||||
CHECK (a1 == a1);
|
||||
CHECK (a1 == a2);
|
||||
CHECK (a2 == a1);
|
||||
CHECK (a1 != a3);
|
||||
CHECK (a3 != a1);
|
||||
CHECK (a2 != a3);
|
||||
CHECK (a3 != a2);
|
||||
|
||||
typedef StorageHolder<Sig_oper,string> Storage;
|
||||
Storage abuff1;
|
||||
Storage abuff2;
|
||||
CHECK (abuff1 == abuff2);
|
||||
|
||||
TypedArguments<ArgTuple> newArgs (make_tuple ('z'));
|
||||
abuff1.bindArguments(newArgs);
|
||||
CHECK (abuff1 != abuff2);
|
||||
abuff2.bindArguments(newArgs);
|
||||
CHECK (abuff1 == abuff2);
|
||||
UndoMutation umu1 (abuff1.tie (undo_1, capt_1));
|
||||
CHECK (abuff1 != abuff2); // abuff2 isn't tied yet, i.e. has no undo/capture function
|
||||
UndoMutation umu2 (abuff2.tie (undo_1, capt_1));
|
||||
CHECK (abuff1 == abuff2); // same capture function, no memento state!
|
||||
|
||||
Closure args {make_tuple ('u')};
|
||||
umu1.captureState(args);
|
||||
CHECK (abuff1 != abuff2);
|
||||
umu2.captureState(args);
|
||||
CHECK (abuff1 == abuff2); // same functions, same memento state
|
||||
|
||||
check_ += "fake"; // manipulate the "state" to be captured
|
||||
umu2.captureState(args); // capture again...
|
||||
CHECK (abuff1 != abuff2); // captured memento differs!
|
||||
|
||||
UndoMutation umu3 (abuff2.tie (undo_1, capt_2));
|
||||
umu3.captureState(args);
|
||||
CHECK (abuff1 != abuff2); // differing functions detected
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verifyMementoEquality()
|
||||
{
|
||||
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);
|
||||
|
||||
CHECK (m11 == m11);
|
||||
CHECK (m12 == m12);
|
||||
CHECK (m21 == m21);
|
||||
CHECK (m22 == m22);
|
||||
CHECK (!(m11 != m11));
|
||||
|
||||
CHECK (m11 != m12);
|
||||
CHECK (m11 != m21);
|
||||
CHECK (m11 != m22);
|
||||
CHECK (m12 != m11);
|
||||
CHECK (m12 != m21);
|
||||
CHECK (m12 != m22);
|
||||
CHECK (m21 != m11);
|
||||
CHECK (m21 != m12);
|
||||
CHECK (m21 != m22);
|
||||
CHECK (m22 != m11);
|
||||
CHECK (m22 != m12);
|
||||
CHECK (m22 != m21);
|
||||
|
||||
MemHolder m22x (m22); // clone copy
|
||||
CHECK (!m22x);
|
||||
CHECK (m22 == m22x); // same functions, no state --> equal
|
||||
|
||||
m22x.tieCaptureFunc() ('x'); // produce a memento state
|
||||
CHECK (!isnil (m22x.getState()));
|
||||
|
||||
CHECK (m22 != m22x);
|
||||
m22.tieCaptureFunc() ('x'); // get same value into the memento within m22
|
||||
CHECK (m22 == m22x);
|
||||
|
||||
// document shortcomings on UndoMutation comparisons
|
||||
UndoMutation umu11 (m11);
|
||||
UndoMutation umu12 (m11); // note: due to cloning the embedded functor,
|
||||
CHECK (umu11 != umu12); // our hacked-in comparison operator fails
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verifyCommandEquality()
|
||||
{
|
||||
CommandDef (COMMAND1)
|
||||
.operation (oper_1)
|
||||
.captureUndo (capt_1)
|
||||
|
|
|
|||
|
|
@ -217,7 +217,6 @@ namespace test {
|
|||
CHECK (2+cnt_inst == registry.instance_count());
|
||||
|
||||
CHECK (!isSameObject (*pImpl, *clone));
|
||||
CHECK (*pImpl == *clone);
|
||||
|
||||
CHECK (!pImpl->canExec());
|
||||
typedef Types<int> ArgType;
|
||||
|
|
@ -226,12 +225,10 @@ namespace test {
|
|||
CHECK (pImpl->canExec());
|
||||
|
||||
CHECK (!clone->canExec()); // this proves the clone has indeed a separate identity
|
||||
CHECK (*pImpl != *clone);
|
||||
|
||||
// discard the first clone and overwrite with a new one
|
||||
clone = registry.createCloneImpl(*pImpl);
|
||||
CHECK (2+cnt_inst == registry.instance_count());
|
||||
CHECK (*pImpl == *clone);
|
||||
CHECK (clone->canExec());
|
||||
|
||||
clone.reset();
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ namespace test {
|
|||
run (Arg)
|
||||
{
|
||||
checkStateCapturingMechanism();
|
||||
verifyComparisons();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -134,50 +133,6 @@ namespace test {
|
|||
bound_undo_func(3*rr);
|
||||
CHECK (testVal == -20 + 3*rr - (5+rr));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
verifyComparisons()
|
||||
{
|
||||
function<void(short,int)> u1_fun; // deliberately unbound
|
||||
function<void(short,int)> u2_fun = undo;
|
||||
function< int(short)> c1_fun;
|
||||
function< int(short)> c2_fun = capture;
|
||||
|
||||
MemHolder m11 (u1_fun, c1_fun);
|
||||
MemHolder m12 (u1_fun, c2_fun);
|
||||
MemHolder m21 (u2_fun, c1_fun);
|
||||
MemHolder m22 (u2_fun, c2_fun);
|
||||
|
||||
CHECK (!m11 && !m12 && !m21 && !m22);
|
||||
CHECK ( (m11 == m11));
|
||||
CHECK (!(m11 != m11));
|
||||
|
||||
CHECK (m11 != m12);
|
||||
CHECK (m11 != m21);
|
||||
CHECK (m11 != m22);
|
||||
CHECK (m12 != m11);
|
||||
CHECK (m12 != m21);
|
||||
CHECK (m12 != m22);
|
||||
CHECK (m21 != m11);
|
||||
CHECK (m21 != m12);
|
||||
CHECK (m21 != m22);
|
||||
CHECK (m22 != m11);
|
||||
CHECK (m22 != m12);
|
||||
CHECK (m22 != m21);
|
||||
|
||||
MemHolder m22x (m22); // clone copy
|
||||
CHECK (!m22x);
|
||||
CHECK (m22 == m22x); // same functions, no state --> equal
|
||||
|
||||
testVal = 0;
|
||||
m22x.tieCaptureFunc() (1 + (rand() % 9)); // produce a random memento value != 0
|
||||
CHECK (0 < m22x.getState());
|
||||
|
||||
CHECK (m22 != m22x);
|
||||
m22.tieCaptureFunc() (m22x.getState()); // get the same value into the memento within m22
|
||||
CHECK (m22 == m22x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,212 +0,0 @@
|
|||
/*
|
||||
FunctorUtil(Test) - verifying function object and signal utilities
|
||||
|
||||
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.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
/** @file functor-util-test.cpp
|
||||
** unit test \ref FunctorUtil_test
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/functor-util.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using lib::HashVal;
|
||||
using std::cout;
|
||||
using std::function;
|
||||
using boost::hash; // note: only boost::hash allows for easy defining of custom hash functions
|
||||
|
||||
|
||||
namespace util {
|
||||
namespace test {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void fun1 (int i) { cout << "fun1 (" << i << ")\n"; }
|
||||
void fun2 (int i) { cout << "fun2 (" << i << ")\n"; }
|
||||
|
||||
struct Dummy
|
||||
{
|
||||
void gummi (int i) { cout << "gummi (" << i << ")\n"; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************//**
|
||||
* @test verify some aspects of the functor-util's behaviour.
|
||||
* At times, this is just a scrapbook for new ideas....
|
||||
*/
|
||||
class FunctorUtil_test : public Test
|
||||
{
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
// verifyBruteForceComparison();
|
||||
// verifyHashThroughBackdoor();
|
||||
}
|
||||
|
||||
typedef function<void(int)> Fvi;
|
||||
typedef function<int(void)> Fiv;
|
||||
|
||||
typedef function<void(void)> Fvv;
|
||||
|
||||
|
||||
/** @test workaround for the missing functor comparison operator */
|
||||
// void
|
||||
// verifyBruteForceComparison()
|
||||
// {
|
||||
// Fvi f0;
|
||||
// Fvi f1 (fun1);
|
||||
// Fvi f2 (fun2);
|
||||
//
|
||||
// CHECK (!rawComparison(f0, f1));
|
||||
// CHECK (!rawComparison(f1, f2));
|
||||
// CHECK (!rawComparison(f0, f2));
|
||||
//
|
||||
// Fvi f22 (f2);
|
||||
// CHECK ( rawComparison(f2, f22));
|
||||
//
|
||||
// f1 = f2;
|
||||
// CHECK ( rawComparison(f1, f2));
|
||||
//
|
||||
// CHECK (!rawComparison(f0, Fvi())); // note: can't detect they are equivalent
|
||||
// CHECK (!rawComparison(f0, Fiv()));
|
||||
//
|
||||
// f1 = bind (fun2, _1);
|
||||
// CHECK (!rawComparison(f1, f2));
|
||||
//
|
||||
// Dummy dum1, dum2;
|
||||
// Fvi fm1 = bind (&Dummy::gummi, dum1, _1);
|
||||
// Fvi fm2 = bind (&Dummy::gummi, dum2, _1);
|
||||
// Fvv fm3 = bind (&Dummy::gummi, dum1, 23);
|
||||
// Fvv fm4 = bind (&Dummy::gummi, dum1, 24);
|
||||
// Fvv fm5 = bind (&Dummy::gummi, dum2, 24);
|
||||
// Fvv fm6 = bind (&Dummy::gummi, dum2, 24);
|
||||
//
|
||||
// CHECK (!rawComparison(f1, fm1));
|
||||
//
|
||||
// CHECK (!rawComparison(fm1, fm2));
|
||||
// CHECK (!rawComparison(fm1, fm3));
|
||||
// CHECK (!rawComparison(fm1, fm4));
|
||||
// CHECK (!rawComparison(fm1, fm5));
|
||||
// CHECK (!rawComparison(fm1, fm6));
|
||||
// CHECK (!rawComparison(fm2, fm3));
|
||||
// CHECK (!rawComparison(fm2, fm4));
|
||||
// CHECK (!rawComparison(fm2, fm5));
|
||||
// CHECK (!rawComparison(fm2, fm6));
|
||||
// CHECK (!rawComparison(fm3, fm4));
|
||||
// CHECK (!rawComparison(fm3, fm5));
|
||||
// CHECK (!rawComparison(fm3, fm6));
|
||||
// CHECK (!rawComparison(fm4, fm5)); // note: same argument but different functor instance
|
||||
// CHECK (!rawComparison(fm4, fm6));
|
||||
// CHECK (!rawComparison(fm5, fm6)); // again: can't detect they are equivalent
|
||||
// }
|
||||
|
||||
|
||||
/** @test workaround for missing standard hash
|
||||
* calculation for functor objects.
|
||||
* Workaround relying on boost
|
||||
* implementation internals */
|
||||
// void
|
||||
// verifyHashThroughBackdoor()
|
||||
// {
|
||||
// Fvi f0;
|
||||
// Fvi f1 (fun1);
|
||||
// Fvi f2 (fun2);
|
||||
// Fvi f22 (f2);
|
||||
//
|
||||
// hash<Fvi> calculateHash;
|
||||
// CHECK (calculateHash (f0));
|
||||
// CHECK (calculateHash (f1));
|
||||
// CHECK (calculateHash (f2));
|
||||
// CHECK (calculateHash (f22));
|
||||
//
|
||||
// HashVal h0 = calculateHash (f0);
|
||||
// HashVal h1 = calculateHash (f1);
|
||||
// HashVal h2 = calculateHash (f2);
|
||||
// HashVal h22 = calculateHash (f22);
|
||||
//
|
||||
// CHECK (h0 != h1);
|
||||
// CHECK (h0 != h2);
|
||||
// CHECK (h1 != h2);
|
||||
//
|
||||
// CHECK (h2 == h22);
|
||||
//
|
||||
// f1 = f2;
|
||||
// h1 = calculateHash (f1);
|
||||
// CHECK (h1 == h2);
|
||||
// CHECK (h1 != h0);
|
||||
//
|
||||
// CHECK (h0 != calculateHash (Fvi())); // note: equivalence not detected
|
||||
//
|
||||
// // checking functors based on member function(s)
|
||||
// Dummy dum1, dum2;
|
||||
// Fvi fm1 = bind (&Dummy::gummi, dum1, _1);
|
||||
// Fvi fm2 = bind (&Dummy::gummi, dum2, _1);
|
||||
// Fvv fm3 = bind (&Dummy::gummi, dum1, 23);
|
||||
// Fvv fm4 = bind (&Dummy::gummi, dum1, 24);
|
||||
// Fvv fm5 = bind (&Dummy::gummi, dum2, 24);
|
||||
// Fvv fm6 = bind (&Dummy::gummi, dum2, 24);
|
||||
//
|
||||
// HashVal hm1 = calculateHash (fm1);
|
||||
// HashVal hm2 = calculateHash (fm2);
|
||||
//
|
||||
// hash<Fvv> calculateHashVV;
|
||||
// HashVal hm3 = calculateHashVV (fm3);
|
||||
// HashVal hm4 = calculateHashVV (fm4);
|
||||
// HashVal hm5 = calculateHashVV (fm5);
|
||||
// HashVal hm6 = calculateHashVV (fm6);
|
||||
//
|
||||
// CHECK (h1 != hm1);
|
||||
//
|
||||
// CHECK (hm1 != hm2);
|
||||
// CHECK (hm1 != hm3);
|
||||
// CHECK (hm1 != hm4);
|
||||
// CHECK (hm1 != hm5);
|
||||
// CHECK (hm1 != hm6);
|
||||
// CHECK (hm2 != hm3);
|
||||
// CHECK (hm2 != hm4);
|
||||
// CHECK (hm2 != hm5);
|
||||
// CHECK (hm2 != hm6);
|
||||
// CHECK (hm3 != hm4);
|
||||
// CHECK (hm3 != hm5);
|
||||
// CHECK (hm3 != hm6);
|
||||
// CHECK (hm4 != hm5);
|
||||
// CHECK (hm4 != hm6);
|
||||
// CHECK (hm5 != hm6); // again: unable to detect the equivalence
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (FunctorUtil_test, "unit common");
|
||||
|
||||
|
||||
|
||||
}} // namespace util::test
|
||||
|
|
@ -88,27 +88,6 @@ 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), Efp(returnIt));
|
||||
check_Comparisons (Evoid(testFunc), Evoid(returnIt));
|
||||
|
||||
CHECK ( detect_Clone (Efun(testFunc)));
|
||||
CHECK (!detect_Clone (Efun(bindFunc))); //note equality not detected when cloning a bind term
|
||||
CHECK (!detect_Clone (Efun(pAplFunc))); //similarly
|
||||
CHECK (!detect_Clone (Efun(membFunc))); //analogous for bound member function
|
||||
CHECK ( detect_Clone (Efp(testFunc) ));
|
||||
CHECK ( detect_Clone (Evoid(testFunc)));
|
||||
|
||||
detect_unboundFunctor(Efun(testFunc), Efun(getterFunc), Efun(membFunc));
|
||||
detect_unboundFunctor(Efp(testFunc),Efp(&testFunc), Efp(returnIt));
|
||||
detect_unboundFunctor(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt));
|
||||
|
|
@ -194,11 +173,6 @@ namespace test {
|
|||
CHECK (_sum_ == 10+'a'+20+'b'+30+'c');
|
||||
|
||||
CHECK (_sum_ == (f3.getFun<int(void)>()) () );
|
||||
|
||||
#if false ////////////////////////////////////////////////////////TODO: restore throwing ASSERT
|
||||
VERIFY_ERROR (ASSERTION, f1.getFun<int(int)>() );
|
||||
#endif////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -231,27 +205,6 @@ namespace test {
|
|||
} // likely to result in heap corruption or SEGV
|
||||
|
||||
|
||||
template<class HOL>
|
||||
void
|
||||
check_Comparisons (HOL h1, HOL h2)
|
||||
{
|
||||
CHECK (h1 == h1); CHECK (!(h1 != h1));
|
||||
CHECK (h2 == h2); CHECK (!(h2 != h2));
|
||||
|
||||
CHECK (h1 != h2);
|
||||
CHECK (h2 != h1);
|
||||
}
|
||||
|
||||
|
||||
template<class HOL>
|
||||
bool
|
||||
detect_Clone (HOL const& h1)
|
||||
{
|
||||
HOL clone (h1);
|
||||
return (clone == h1);
|
||||
}
|
||||
|
||||
|
||||
template<class HOL>
|
||||
void
|
||||
detect_unboundFunctor (HOL h1, HOL h2, HOL h3)
|
||||
|
|
|
|||
|
|
@ -44930,7 +44930,8 @@
|
|||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1446505444775" HGAP="106" ID="ID_721807850" MODIFIED="1557498707242" TEXT="Buildsystem" VSHIFT="-5">
|
||||
<node CREATED="1446505444775" FOLDED="true" HGAP="106" ID="ID_721807850" MODIFIED="1561311686974" TEXT="Buildsystem" VSHIFT="-5">
|
||||
<icon BUILTIN="go"/>
|
||||
<node CREATED="1446505367113" ID="ID_335245102" LINK="http://issues.lumiera.org/ticket/971" MODIFIED="1557498707242">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
|
@ -45162,8 +45163,8 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1447978374453" HGAP="140" ID="ID_156552320" MODIFIED="1557498707242" TEXT="Compiler" VSHIFT="-10">
|
||||
<icon BUILTIN="prepare"/>
|
||||
<node CREATED="1447978374453" HGAP="140" ID="ID_156552320" MODIFIED="1561311589295" TEXT="Compiler" VSHIFT="-10">
|
||||
<icon BUILTIN="go"/>
|
||||
<node CREATED="1447978472591" ID="ID_281213456" MODIFIED="1557498707243" TEXT="GCC-4.9">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
@ -45255,11 +45256,11 @@
|
|||
</richcontent>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561237831168" ID="ID_1760455064" MODIFIED="1561237839865" TEXT="Juni 2019">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561237841287" ID="ID_1588960225" MODIFIED="1561238702212" TEXT="Probleme mit libboost 1.65">
|
||||
<arrowlink COLOR="#c64162" DESTINATION="ID_584004962" ENDARROW="Default" ENDINCLINATION="295;-171;" ID="Arrow_ID_1368108105" STARTARROW="None" STARTINCLINATION="247;0;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1561237831168" ID="ID_1760455064" MODIFIED="1561311488940" TEXT="Juni 2019">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1561237841287" ID="ID_1588960225" MODIFIED="1561311497905" TEXT="Probleme mit libboost 1.65">
|
||||
<arrowlink COLOR="#37aea5" DESTINATION="ID_584004962" ENDARROW="Default" ENDINCLINATION="295;-171;" ID="Arrow_ID_1368108105" STARTARROW="None" STARTINCLINATION="247;0;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -45731,7 +45732,8 @@
|
|||
</node>
|
||||
<node CREATED="1446356359992" HGAP="9" ID="ID_1850896628" MODIFIED="1557498707243" POSITION="left" TEXT="QA" VSHIFT="69">
|
||||
<icon BUILTIN="prepare"/>
|
||||
<node CREATED="1447985496639" ID="ID_1191711297" MODIFIED="1557498707243" TEXT="untersuchen">
|
||||
<node CREATED="1447985496639" ID="ID_1191711297" MODIFIED="1561311638128" TEXT="untersuchen">
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1447985501798" ID="ID_732609615" MODIFIED="1557498707243" TEXT="std::hash-Spezialisierung">
|
||||
<node CREATED="1447985531602" ID="ID_515281257" LINK="http://issues.lumiera.org/ticket/722" MODIFIED="1557498707243">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
@ -45763,7 +45765,7 @@
|
|||
</node>
|
||||
<node CREATED="1447567187010" ID="ID_1008538054" MODIFIED="1557498707243" TEXT="später...">
|
||||
<icon BUILTIN="bell"/>
|
||||
<node CREATED="1447567193361" ID="ID_661445245" MODIFIED="1557498707243" TEXT="preliminary optimization">
|
||||
<node CREATED="1447567193361" FOLDED="true" ID="ID_661445245" MODIFIED="1561311629097" TEXT="premature optimization">
|
||||
<icon BUILTIN="ksmiletris"/>
|
||||
<node CREATED="1447566743461" ID="ID_1971297499" LINK="http://issues.lumiera.org/ticket/973" MODIFIED="1557498707243">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
|
|
@ -45779,7 +45781,7 @@
|
|||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1477665256799" ID="ID_685276209" MODIFIED="1557498707243" TEXT="Ärger">
|
||||
<node CREATED="1477665256799" FOLDED="true" ID="ID_685276209" MODIFIED="1561311615971" TEXT="Ärger">
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
<node CREATED="1477665276421" ID="ID_714740974" MODIFIED="1557498707243" TEXT="dlclose #1034">
|
||||
<node CREATED="1477665304137" ID="ID_65862146" MODIFIED="1557498707243" TEXT="Assertion, da Library nicht entladen werden kann">
|
||||
|
|
@ -45793,8 +45795,6 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#990000" CREATED="1446356368070" ID="ID_768449868" MODIFIED="1557498707243" TEXT="Au Au">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1521963965164" FOLDED="true" ID="ID_1027875371" MODIFIED="1561238596029" TEXT="komplexe Probleme">
|
||||
<icon BUILTIN="go"/>
|
||||
<node COLOR="#435e98" CREATED="1522025948980" ID="ID_295336770" MODIFIED="1557498707243" TEXT="3/2018">
|
||||
|
|
@ -45939,11 +45939,10 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1561238618311" ID="ID_1197206022" MODIFIED="1561238624422" TEXT="Plattform-Evolution">
|
||||
<icon BUILTIN="prepare"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561238627847" ID="ID_776424925" MODIFIED="1561238634217" TEXT="Juni 2019">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561238635358" ID="ID_584004962" MODIFIED="1561238732841" TEXT="Ubuntu/Bionic - libboost 1.65">
|
||||
<node CREATED="1561238618311" ID="ID_1197206022" MODIFIED="1561311521089" TEXT="Plattform-Evolution">
|
||||
<icon BUILTIN="go"/>
|
||||
<node COLOR="#435e98" CREATED="1561238627847" ID="ID_776424925" MODIFIED="1561311477641" TEXT="Juni 2019">
|
||||
<node COLOR="#338800" CREATED="1561238635358" FOLDED="true" ID="ID_584004962" MODIFIED="1561311515592" TEXT="Ubuntu/Bionic - libboost 1.65">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
|
|
@ -45956,10 +45955,9 @@
|
|||
er wollte "versuchen, Lumiera zu bauen"
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<linktarget COLOR="#c64162" DESTINATION="ID_584004962" ENDARROW="Default" ENDINCLINATION="295;-171;" ID="Arrow_ID_1368108105" SOURCE="ID_1588960225" STARTARROW="None" STARTINCLINATION="247;0;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
</html></richcontent>
|
||||
<linktarget COLOR="#37aea5" DESTINATION="ID_584004962" ENDARROW="Default" ENDINCLINATION="295;-171;" ID="Arrow_ID_1368108105" SOURCE="ID_1588960225" STARTARROW="None" STARTINCLINATION="247;0;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1561237854717" FOLDED="true" ID="ID_682831433" MODIFIED="1561237893434" TEXT="boost::rational">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1561237861421" ID="ID_575082452" MODIFIED="1561237891854" TEXT="erlaubt keine implizite signed/unsigned-conversion mehr">
|
||||
|
|
@ -45988,8 +45986,7 @@
|
|||
wann sind Funktoren <i>äquivalent</i> ??
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
|
|
@ -46008,8 +46005,7 @@
|
|||
<i>sei die Dose offen...</i>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1561293746047" ID="ID_1685820592" MODIFIED="1561293763727" TEXT="ich hatte da einen Hack im Einsatz">
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
|
|
@ -46042,8 +46038,7 @@
|
|||
aber ansonsten alle <i>validen definierten</i> Funktionen untereinander verschieden sind.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="smiley-oh"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1561293905972" ID="ID_1691379411" MODIFIED="1561294054085" TEXT="Fazit: std::function ist nur partiell geordnet">
|
||||
|
|
@ -46053,9 +46048,9 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561294009342" ID="ID_1015641085" MODIFIED="1561294046278" TEXT="#294 re-evaluate command equality comparisons">
|
||||
<node COLOR="#338800" CREATED="1561294009342" ID="ID_1015641085" MODIFIED="1561311468701" TEXT="#294 re-evaluate command equality comparisons">
|
||||
<linktarget COLOR="#3044e4" DESTINATION="ID_1015641085" ENDARROW="Default" ENDINCLINATION="51;-54;" ID="Arrow_ID_44253813" SOURCE="ID_1691379411" STARTARROW="None" STARTINCLINATION="-282;0;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1561294074429" ID="ID_1155061172" MODIFIED="1561294082271" TEXT="sinnvoller use-case?">
|
||||
<node CREATED="1561294111368" ID="ID_550692627" MODIFIED="1561294116011" TEXT="bisher nur isValid()">
|
||||
<node CREATED="1561294121390" ID="ID_1554085271" MODIFIED="1561294146172" TEXT="»ist aktiviert und beruht auf dem "gleichen" backend«">
|
||||
|
|
@ -46073,8 +46068,7 @@
|
|||
sonst auf <i>Äquivalenz</i> getestet
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1561294190088" ID="ID_1198524028" MODIFIED="1561294221209">
|
||||
|
|
@ -46087,8 +46081,7 @@
|
|||
und genau das Letztere ist nicht <b>garantiert korrekt</b> implementierbar
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1561294330073" ID="ID_608542803" MODIFIED="1561294340821" TEXT="Commands haben Referenz-Symantik">
|
||||
|
|
@ -46110,12 +46103,11 @@
|
|||
Selbst verschiedene Closures haben selbst die noch eine eindeutige <b>Identität</b>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561294470021" ID="ID_1846241113" MODIFIED="1561303698905" TEXT="totmachen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1561294470021" FOLDED="true" ID="ID_1846241113" MODIFIED="1561311466135" TEXT="totmachen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1561295990811" ID="ID_224001495" MODIFIED="1561296000279" TEXT="Äquivalenz-Check abklemmen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
|
|
@ -46142,8 +46134,7 @@
|
|||
d.h. wir brauchen keine Äquivalenz?
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1561305463577" ID="ID_1519337489" MODIFIED="1561305477381" TEXT="folglich wäre jeder TypeHandler ein Unikat"/>
|
||||
</node>
|
||||
|
|
@ -46163,20 +46154,23 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561296009625" ID="ID_617134183" MODIFIED="1561296050381" TEXT="alle Vergleichs-Operatoren auf Command-Funktor-Ebene zurückbauen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1561296009625" ID="ID_617134183" MODIFIED="1561311456970" TEXT="alle Vergleichs-Operatoren auf Command-Funktor-Ebene zurückbauen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561296029622" ID="ID_696325144" MODIFIED="1561296050004" TEXT="die rawComparison zurückbauen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1561296029622" ID="ID_696325144" MODIFIED="1561311458435" TEXT="die rawComparison zurückbauen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561296041852" ID="ID_1450999034" MODIFIED="1561296049476" TEXT="Doku aktualisieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1561296041852" ID="ID_1450999034" MODIFIED="1561311460017" TEXT="Doku aktualisieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#990000" CREATED="1446356368070" HGAP="42" ID="ID_768449868" MODIFIED="1561311570056" TEXT="Au Au" VSHIFT="78">
|
||||
<edge COLOR="#c14b4b" STYLE="sharp_bezier"/>
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1544239377061" ID="ID_1224449803" MODIFIED="1557498707243" TEXT="GUI-Start not yet failsafe">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node COLOR="#435e98" CREATED="1544239394777" ID="ID_626803835" MODIFIED="1557498707243" TEXT="aufgedeckt durch fehlende UI-Resourcen">
|
||||
|
|
|
|||
Loading…
Reference in a new issue