Functions-Commands: discard the ability to compare functors for equivalence (closes #294)

evil hack R.I.P
This commit is contained in:
Fischlurch 2019-06-23 19:43:47 +02:00
parent 94edb5de86
commit ab90d9c71d
23 changed files with 46 additions and 970 deletions

View file

@ -7,46 +7,6 @@ nonportable hacks, terrorism and other misdemeanour_
Library 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 Binding Placeholders
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
The standard allows function objects to be partially closed; this is achieved by The standard allows function objects to be partially closed; this is achieved by

View file

@ -36,7 +36,6 @@
#include "lib/sync.hpp" #include "lib/sync.hpp"
#include "lib/error.hpp" #include "lib/error.hpp"
#include "lib/depend.hpp" #include "lib/depend.hpp"
#include "lib/functor-util.hpp"
#include "common/instancehandle.hpp" #include "common/instancehandle.hpp"
#include "common/option.hpp" #include "common/option.hpp"

View file

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

View file

@ -58,7 +58,6 @@
#include "lib/util.hpp" #include "lib/util.hpp"
#include "lib/error.hpp" #include "lib/error.hpp"
#include "lib/opaque-holder.hpp" #include "lib/opaque-holder.hpp"
#include "lib/functor-util.hpp"
#include <functional> #include <functional>
@ -140,14 +139,6 @@ namespace meta{
{ {
return get<function<SIG>>(); 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); REQUIRE (fun);
return *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_; } explicit operator bool() const { return funP_; }
bool isValid() const { return funP_; } bool isValid() const { return funP_; }
friend bool
operator== (StoreUncheckedFunPtr const& o1,
StoreUncheckedFunPtr const& o2)
{
return unConst(o1).funP_ == unConst(o2).funP_;
}
}; };

View file

@ -30,15 +30,11 @@
#define LIB_META_MAYBE_COMPARE_H #define LIB_META_MAYBE_COMPARE_H
#include "lib/functor-util.hpp"
#include <functional>
namespace lib { namespace lib {
namespace meta{ namespace meta{
using std::function;
/** /**
* Trait template for invoking equality comparison. * Trait template for invoking equality comparison.
@ -54,19 +50,7 @@ namespace meta{
} }
}; };
/** while the boost function implementation doesn't provide comparison, /* == add specialisations here == */
* 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> template<typename X>

View file

@ -112,7 +112,6 @@ namespace control {
virtual operator string() const =0; virtual operator string() const =0;
virtual bool isValid () const =0; ///< does this closure hold a valid argument tuple? 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 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 (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 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_ virtual void unbindArguments() =0; ///< discard any parameters and return to _unbound state_

View file

@ -29,8 +29,6 @@
** identity and usually located within the (pooled) storage managed by the ** identity and usually located within the (pooled) storage managed by the
** CommandRegistry. Client code gets access to a specific CommandImpl through ** CommandRegistry. Client code gets access to a specific CommandImpl through
** a Command instance, which is a small (refcounting smart-ptr) handle. ** a Command instance, which is a small (refcounting smart-ptr) handle.
**
** //TODO
** **
** @see Command ** @see Command
** @see SteamDispatcher ** @see SteamDispatcher
@ -246,26 +244,6 @@ namespace control {
% canUndo() % canUndo()
% (pClo_? string(*pClo_) : util::FAILURE_INDICATOR); % (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);
}
}; };

View file

@ -83,21 +83,6 @@ namespace control {
LERR_(UNBOUND_ARGUMENTS)); LERR_(UNBOUND_ARGUMENTS));
clo.invoke (func_); 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);
}
}; };

View file

@ -64,7 +64,6 @@ namespace control {
using lib::meta::NullType; using lib::meta::NullType;
using lib::meta::buildTuple; using lib::meta::buildTuple;
using lib::meta::equals_safeInvoke;
using lib::TypedAllocationManager; using lib::TypedAllocationManager;
using std::function; using std::function;
using std::ostream; using std::ostream;
@ -96,20 +95,11 @@ namespace control {
/////////////////////////////////////////////////////////////TICKET #798 : we need to pick up arguments from a lib::diff::Record. /////////////////////////////////////////////////////////////TICKET #798 : we need to pick up arguments from a lib::diff::Record.
ostream& ostream&
dump (ostream& output) const dump (ostream& output) const
{ {
return BASE::dump (output << element() << ','); 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> template<class TUP, uint n>
@ -135,12 +125,6 @@ namespace control {
{ {
return output; return output;
} }
friend bool
compare (ParamAccessor const&, ParamAccessor const&)
{
return true;
}
}; };
@ -218,11 +202,6 @@ namespace control {
else else
return dumped+")"; 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); }
}; };

View file

@ -204,30 +204,6 @@ namespace control {
{ {
arguments_.template create<ArgHolder>(); 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);
}
}; };

View file

@ -255,31 +255,6 @@ namespace control {
{ {
return memento_->getState(); 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);
}
}; };

View file

@ -369,13 +369,6 @@ namespace control {
} }
bool
Command::equivalentImpl (Command const& c1, Command const& c2)
{
return c1.impl() == c2.impl();
}
Symbol Symbol
Command::getID() const noexcept Command::getID() const noexcept
{ {

View file

@ -223,7 +223,6 @@ namespace control {
private: private:
void setArguments (Arguments&); void setArguments (Arguments&);
void setArguments (lib::diff::Rec const&); void setArguments (lib::diff::Rec const&);
static bool equivalentImpl (Command const&, Command const&);
}; };

View file

@ -44,7 +44,6 @@
#include "lib/meta/function-closure.hpp" #include "lib/meta/function-closure.hpp"
#include "steam/control/command-signature.hpp" #include "steam/control/command-signature.hpp"
#include "lib/replaceable-item.hpp" #include "lib/replaceable-item.hpp"
#include "lib/functor-util.hpp"
#include "lib/format-obj.hpp" #include "lib/format-obj.hpp"
#include "lib/util.hpp" #include "lib/util.hpp"
@ -202,20 +201,6 @@ namespace control {
/** for diagnostics: include format-util.hpp */ /** for diagnostics: include format-util.hpp */
operator std::string() const; 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_));
}
}; };

View file

@ -44,7 +44,6 @@
#include "lib/error.hpp" #include "lib/error.hpp"
#include "lib/hash-value.h" #include "lib/hash-value.h"
#include "lib/functor-util.hpp"
#include <functional> #include <functional>
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>

View file

@ -213,7 +213,6 @@ namespace test {
Tracker<string>::instanceCnt = 0; Tracker<string>::instanceCnt = 0;
createTuples (testTuples); createTuples (testTuples);
checkArgumentComparison ();
serialiseArgTuples (testTuples); serialiseArgTuples (testTuples);
testTuples.clear(); 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 /** @test simulate a complete command lifecycle with regards to the
* storage handling of the command parameters and state memento. * storage handling of the command parameters and state memento.
*/ */

View file

@ -137,7 +137,6 @@ namespace test {
CHECK (orig && copy); CHECK (orig && copy);
CHECK (orig->canExec()); CHECK (orig->canExec());
CHECK (copy->canExec()); CHECK (copy->canExec());
CHECK (orig == copy);
// prepare for command invocation on implementation level.... // prepare for command invocation on implementation level....
@ -151,13 +150,11 @@ namespace test {
long state_after_exec1 = command1::check_; long state_after_exec1 = command1::check_;
CHECK (command1::check_ > 0); CHECK (command1::check_ > 0);
CHECK (orig->canUndo()); CHECK (orig->canUndo());
CHECK (orig != copy);
CHECK (!copy->canUndo()); CHECK (!copy->canUndo());
testExec.exec (*copy, "Execute clone"); // EXEC 2 testExec.exec (*copy, "Execute clone"); // EXEC 2
CHECK (command1::check_ != state_after_exec1); CHECK (command1::check_ != state_after_exec1);
CHECK (copy->canUndo()); CHECK (copy->canUndo());
CHECK (copy != orig);
// invoke UNDO on the clone // invoke UNDO on the clone
testExec.undo (*copy, "Undo clone"); // UNDO 2 testExec.undo (*copy, "Undo clone"); // UNDO 2
@ -166,8 +163,6 @@ namespace test {
// invoke UNDO on original // invoke UNDO on original
testExec.undo (*orig, "Undo original"); // UNDO 1 testExec.undo (*orig, "Undo original"); // UNDO 1
CHECK (command1::check_ ==0); CHECK (command1::check_ ==0);
CHECK (copy != orig);
} }
}; };

View file

@ -98,30 +98,15 @@ namespace test {
/*************************************************************************************//** /*************************************************************************************//**
* @test cover command equality detection. * @test cover command equality detection.
* Two commands are deemed equivalent, if they * Two commands are deemed equivalent, if they are based on the same CommandImpl record.
* - build on the same Mutation functors * This means, we only rely on the _identity_ of those commands, but do not check the
* - are either both incomplete or * _equivalence_ of their backing implementations. The latter can not be possibly
* - are bound to equivalent arguments * implemented in a totally airtight fashion, and for this reason, the C++ standard
* - hold equivalent undo state (memento) * decided not to support comparison between std::function objects.
* 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.
* *
* @see control::Command * @see control::Command
* @see control::CmdClosure
* @see control::Mutation
* @see control::UndoMutation
* @see control::MementoTie
* @see control::CommandImpl * @see control::CommandImpl
* @see command-basic-test.hpp * @see command-basic-test.hpp
* @see functor-util.hpp functor equality workaround
*/ */
class CommandEquality_test : public Test class CommandEquality_test : public Test
{ {
@ -133,148 +118,6 @@ namespace test {
CHECK (&capt_1 != &capt_2); CHECK (&capt_1 != &capt_2);
CHECK (&undo_1 != &undo_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) CommandDef (COMMAND1)
.operation (oper_1) .operation (oper_1)
.captureUndo (capt_1) .captureUndo (capt_1)

View file

@ -217,7 +217,6 @@ namespace test {
CHECK (2+cnt_inst == registry.instance_count()); CHECK (2+cnt_inst == registry.instance_count());
CHECK (!isSameObject (*pImpl, *clone)); CHECK (!isSameObject (*pImpl, *clone));
CHECK (*pImpl == *clone);
CHECK (!pImpl->canExec()); CHECK (!pImpl->canExec());
typedef Types<int> ArgType; typedef Types<int> ArgType;
@ -226,12 +225,10 @@ namespace test {
CHECK (pImpl->canExec()); CHECK (pImpl->canExec());
CHECK (!clone->canExec()); // this proves the clone has indeed a separate identity 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 // discard the first clone and overwrite with a new one
clone = registry.createCloneImpl(*pImpl); clone = registry.createCloneImpl(*pImpl);
CHECK (2+cnt_inst == registry.instance_count()); CHECK (2+cnt_inst == registry.instance_count());
CHECK (*pImpl == *clone);
CHECK (clone->canExec()); CHECK (clone->canExec());
clone.reset(); clone.reset();

View file

@ -87,7 +87,6 @@ namespace test {
run (Arg) run (Arg)
{ {
checkStateCapturingMechanism(); checkStateCapturingMechanism();
verifyComparisons();
} }
@ -134,50 +133,6 @@ namespace test {
bound_undo_func(3*rr); bound_undo_func(3*rr);
CHECK (testVal == -20 + 3*rr - (5+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);
}
}; };

View file

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

View file

@ -88,27 +88,6 @@ namespace test {
check_FunctPtrHolder(Efp(testFunc),Efp(&testFunc), Efp(returnIt)); check_FunctPtrHolder(Efp(testFunc),Efp(&testFunc), Efp(returnIt));
check_VoidPtrHolder(Evoid(testFunc),Evoid(&testFunc),Evoid(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(Efun(testFunc), Efun(getterFunc), Efun(membFunc));
detect_unboundFunctor(Efp(testFunc),Efp(&testFunc), Efp(returnIt)); detect_unboundFunctor(Efp(testFunc),Efp(&testFunc), Efp(returnIt));
detect_unboundFunctor(Evoid(testFunc),Evoid(&testFunc),Evoid(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_ == 10+'a'+20+'b'+30+'c');
CHECK (_sum_ == (f3.getFun<int(void)>()) () ); 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 } // 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> template<class HOL>
void void
detect_unboundFunctor (HOL h1, HOL h2, HOL h3) detect_unboundFunctor (HOL h1, HOL h2, HOL h3)

View file

@ -44930,7 +44930,8 @@
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
</node> </node>
</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"> <node CREATED="1446505367113" ID="ID_335245102" LINK="http://issues.lumiera.org/ticket/971" MODIFIED="1557498707242">
<richcontent TYPE="NODE"><html> <richcontent TYPE="NODE"><html>
<head> <head>
@ -45162,8 +45163,8 @@
</node> </node>
</node> </node>
</node> </node>
<node CREATED="1447978374453" HGAP="140" ID="ID_156552320" MODIFIED="1557498707242" TEXT="Compiler" VSHIFT="-10"> <node CREATED="1447978374453" HGAP="140" ID="ID_156552320" MODIFIED="1561311589295" TEXT="Compiler" VSHIFT="-10">
<icon BUILTIN="prepare"/> <icon BUILTIN="go"/>
<node CREATED="1447978472591" ID="ID_281213456" MODIFIED="1557498707243" TEXT="GCC-4.9"> <node CREATED="1447978472591" ID="ID_281213456" MODIFIED="1557498707243" TEXT="GCC-4.9">
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
</node> </node>
@ -45255,11 +45256,11 @@
</richcontent> </richcontent>
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561237831168" ID="ID_1760455064" MODIFIED="1561237839865" TEXT="Juni 2019"> <node COLOR="#338800" CREATED="1561237831168" ID="ID_1760455064" MODIFIED="1561311488940" TEXT="Juni 2019">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561237841287" ID="ID_1588960225" MODIFIED="1561238702212" TEXT="Probleme mit libboost 1.65"> <node COLOR="#435e98" CREATED="1561237841287" ID="ID_1588960225" MODIFIED="1561311497905" 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;"/> <arrowlink COLOR="#37aea5" DESTINATION="ID_584004962" ENDARROW="Default" ENDINCLINATION="295;-171;" ID="Arrow_ID_1368108105" STARTARROW="None" STARTINCLINATION="247;0;"/>
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="button_ok"/>
</node> </node>
</node> </node>
</node> </node>
@ -45731,7 +45732,8 @@
</node> </node>
<node CREATED="1446356359992" HGAP="9" ID="ID_1850896628" MODIFIED="1557498707243" POSITION="left" TEXT="QA" VSHIFT="69"> <node CREATED="1446356359992" HGAP="9" ID="ID_1850896628" MODIFIED="1557498707243" POSITION="left" TEXT="QA" VSHIFT="69">
<icon BUILTIN="prepare"/> <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="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"> <node CREATED="1447985531602" ID="ID_515281257" LINK="http://issues.lumiera.org/ticket/722" MODIFIED="1557498707243">
<richcontent TYPE="NODE"><html> <richcontent TYPE="NODE"><html>
@ -45763,7 +45765,7 @@
</node> </node>
<node CREATED="1447567187010" ID="ID_1008538054" MODIFIED="1557498707243" TEXT="sp&#xe4;ter..."> <node CREATED="1447567187010" ID="ID_1008538054" MODIFIED="1557498707243" TEXT="sp&#xe4;ter...">
<icon BUILTIN="bell"/> <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"/> <icon BUILTIN="ksmiletris"/>
<node CREATED="1447566743461" ID="ID_1971297499" LINK="http://issues.lumiera.org/ticket/973" MODIFIED="1557498707243"> <node CREATED="1447566743461" ID="ID_1971297499" LINK="http://issues.lumiera.org/ticket/973" MODIFIED="1557498707243">
<richcontent TYPE="NODE"><html> <richcontent TYPE="NODE"><html>
@ -45779,7 +45781,7 @@
<icon BUILTIN="messagebox_warning"/> <icon BUILTIN="messagebox_warning"/>
</node> </node>
</node> </node>
<node CREATED="1477665256799" ID="ID_685276209" MODIFIED="1557498707243" TEXT="&#xc4;rger"> <node CREATED="1477665256799" FOLDED="true" ID="ID_685276209" MODIFIED="1561311615971" TEXT="&#xc4;rger">
<icon BUILTIN="smily_bad"/> <icon BUILTIN="smily_bad"/>
<node CREATED="1477665276421" ID="ID_714740974" MODIFIED="1557498707243" TEXT="dlclose #1034"> <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"> <node CREATED="1477665304137" ID="ID_65862146" MODIFIED="1557498707243" TEXT="Assertion, da Library nicht entladen werden kann">
@ -45793,8 +45795,6 @@
</node> </node>
</node> </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"> <node CREATED="1521963965164" FOLDED="true" ID="ID_1027875371" MODIFIED="1561238596029" TEXT="komplexe Probleme">
<icon BUILTIN="go"/> <icon BUILTIN="go"/>
<node COLOR="#435e98" CREATED="1522025948980" ID="ID_295336770" MODIFIED="1557498707243" TEXT="3/2018"> <node COLOR="#435e98" CREATED="1522025948980" ID="ID_295336770" MODIFIED="1557498707243" TEXT="3/2018">
@ -45939,11 +45939,10 @@
</node> </node>
</node> </node>
</node> </node>
<node CREATED="1561238618311" ID="ID_1197206022" MODIFIED="1561238624422" TEXT="Plattform-Evolution"> <node CREATED="1561238618311" ID="ID_1197206022" MODIFIED="1561311521089" TEXT="Plattform-Evolution">
<icon BUILTIN="prepare"/> <icon BUILTIN="go"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561238627847" ID="ID_776424925" MODIFIED="1561238634217" TEXT="Juni 2019"> <node COLOR="#435e98" CREATED="1561238627847" ID="ID_776424925" MODIFIED="1561311477641" TEXT="Juni 2019">
<icon BUILTIN="flag-yellow"/> <node COLOR="#338800" CREATED="1561238635358" FOLDED="true" ID="ID_584004962" MODIFIED="1561311515592" TEXT="Ubuntu/Bionic - libboost 1.65">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561238635358" ID="ID_584004962" MODIFIED="1561238732841" TEXT="Ubuntu/Bionic - libboost 1.65">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head>
@ -45956,10 +45955,9 @@
er wollte &quot;versuchen, Lumiera zu bauen&quot; er wollte &quot;versuchen, Lumiera zu bauen&quot;
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent> <linktarget COLOR="#37aea5" DESTINATION="ID_584004962" ENDARROW="Default" ENDINCLINATION="295;-171;" ID="Arrow_ID_1368108105" SOURCE="ID_1588960225" STARTARROW="None" STARTINCLINATION="247;0;"/>
<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="button_ok"/>
<icon BUILTIN="pencil"/>
<node COLOR="#338800" CREATED="1561237854717" FOLDED="true" ID="ID_682831433" MODIFIED="1561237893434" TEXT="boost::rational"> <node COLOR="#338800" CREATED="1561237854717" FOLDED="true" ID="ID_682831433" MODIFIED="1561237893434" TEXT="boost::rational">
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
<node CREATED="1561237861421" ID="ID_575082452" MODIFIED="1561237891854" TEXT="erlaubt keine implizite signed/unsigned-conversion mehr"> <node CREATED="1561237861421" ID="ID_575082452" MODIFIED="1561237891854" TEXT="erlaubt keine implizite signed/unsigned-conversion mehr">
@ -45988,8 +45986,7 @@
wann sind Funktoren <i>&#228;quivalent</i>&#160;?? wann sind Funktoren <i>&#228;quivalent</i>&#160;??
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head>
@ -46008,8 +46005,7 @@
<i>sei die Dose offen...</i> <i>sei die Dose offen...</i>
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
</node> </node>
<node CREATED="1561293746047" ID="ID_1685820592" MODIFIED="1561293763727" TEXT="ich hatte da einen Hack im Einsatz"> <node CREATED="1561293746047" ID="ID_1685820592" MODIFIED="1561293763727" TEXT="ich hatte da einen Hack im Einsatz">
<icon BUILTIN="clanbomber"/> <icon BUILTIN="clanbomber"/>
@ -46042,8 +46038,7 @@
aber ansonsten alle <i>validen definierten</i>&#160;Funktionen untereinander verschieden sind. aber ansonsten alle <i>validen definierten</i>&#160;Funktionen untereinander verschieden sind.
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
<icon BUILTIN="smiley-oh"/> <icon BUILTIN="smiley-oh"/>
</node> </node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1561293905972" ID="ID_1691379411" MODIFIED="1561294054085" TEXT="Fazit: std::function ist nur partiell geordnet"> <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>
</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;"/> <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="1561294074429" ID="ID_1155061172" MODIFIED="1561294082271" TEXT="sinnvoller use-case?">
<node CREATED="1561294111368" ID="ID_550692627" MODIFIED="1561294116011" TEXT="bisher nur isValid()"> <node CREATED="1561294111368" ID="ID_550692627" MODIFIED="1561294116011" TEXT="bisher nur isValid()">
<node CREATED="1561294121390" ID="ID_1554085271" MODIFIED="1561294146172" TEXT="&#xbb;ist aktiviert und beruht auf dem &quot;gleichen&quot; backend&#xab;"> <node CREATED="1561294121390" ID="ID_1554085271" MODIFIED="1561294146172" TEXT="&#xbb;ist aktiviert und beruht auf dem &quot;gleichen&quot; backend&#xab;">
@ -46073,8 +46068,7 @@
sonst auf <i>&#196;quivalenz</i>&#160;getestet sonst auf <i>&#196;quivalenz</i>&#160;getestet
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
</node> </node>
</node> </node>
<node CREATED="1561294190088" ID="ID_1198524028" MODIFIED="1561294221209"> <node CREATED="1561294190088" ID="ID_1198524028" MODIFIED="1561294221209">
@ -46087,8 +46081,7 @@
und genau das Letztere ist nicht <b>garantiert korrekt</b>&#160;implementierbar und genau das Letztere ist nicht <b>garantiert korrekt</b>&#160;implementierbar
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
</node> </node>
</node> </node>
<node CREATED="1561294330073" ID="ID_608542803" MODIFIED="1561294340821" TEXT="Commands haben Referenz-Symantik"> <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&#228;t</b> Selbst verschiedene Closures haben selbst die noch eine eindeutige <b>Identit&#228;t</b>
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
</node> </node>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561294470021" ID="ID_1846241113" MODIFIED="1561303698905" TEXT="totmachen"> <node COLOR="#338800" CREATED="1561294470021" FOLDED="true" ID="ID_1846241113" MODIFIED="1561311466135" TEXT="totmachen">
<icon BUILTIN="pencil"/> <icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1561295990811" ID="ID_224001495" MODIFIED="1561296000279" TEXT="&#xc4;quivalenz-Check abklemmen"> <node COLOR="#338800" CREATED="1561295990811" ID="ID_224001495" MODIFIED="1561296000279" TEXT="&#xc4;quivalenz-Check abklemmen">
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
</node> </node>
@ -46142,8 +46134,7 @@
d.h. wir brauchen keine &#196;quivalenz? d.h. wir brauchen keine &#196;quivalenz?
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
</node> </node>
<node CREATED="1561305463577" ID="ID_1519337489" MODIFIED="1561305477381" TEXT="folglich w&#xe4;re jeder TypeHandler ein Unikat"/> <node CREATED="1561305463577" ID="ID_1519337489" MODIFIED="1561305477381" TEXT="folglich w&#xe4;re jeder TypeHandler ein Unikat"/>
</node> </node>
@ -46163,20 +46154,23 @@
</node> </node>
</node> </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&#xfc;ckbauen"> <node COLOR="#338800" CREATED="1561296009625" ID="ID_617134183" MODIFIED="1561311456970" TEXT="alle Vergleichs-Operatoren auf Command-Funktor-Ebene zur&#xfc;ckbauen">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="button_ok"/>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561296029622" ID="ID_696325144" MODIFIED="1561296050004" TEXT="die rawComparison zur&#xfc;ckbauen"> <node COLOR="#338800" CREATED="1561296029622" ID="ID_696325144" MODIFIED="1561311458435" TEXT="die rawComparison zur&#xfc;ckbauen">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="button_ok"/>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1561296041852" ID="ID_1450999034" MODIFIED="1561296049476" TEXT="Doku aktualisieren"> <node COLOR="#338800" CREATED="1561296041852" ID="ID_1450999034" MODIFIED="1561311460017" TEXT="Doku aktualisieren">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="button_ok"/>
</node> </node>
</node> </node>
</node> </node>
</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"> <node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1544239377061" ID="ID_1224449803" MODIFIED="1557498707243" TEXT="GUI-Start not yet failsafe">
<icon BUILTIN="broken-line"/> <icon BUILTIN="broken-line"/>
<node COLOR="#435e98" CREATED="1544239394777" ID="ID_626803835" MODIFIED="1557498707243" TEXT="aufgedeckt durch fehlende UI-Resourcen"> <node COLOR="#435e98" CREATED="1544239394777" ID="ID_626803835" MODIFIED="1557498707243" TEXT="aufgedeckt durch fehlende UI-Resourcen">