From ab90d9c71d1d85417b3c2dec6939de019fc8c0f4 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 23 Jun 2019 19:43:47 +0200 Subject: [PATCH] Functions-Commands: discard the ability to compare functors for equivalence (closes #294) evil hack R.I.P --- doc/technical/code/darkCorners.txt | 40 ---- src/common/guifacade.cpp | 1 - src/lib/functor-util.hpp | 190 ---------------- src/lib/meta/function-erasure.hpp | 25 --- src/lib/meta/maybe-compare.hpp | 18 +- src/steam/control/command-closure.hpp | 1 - src/steam/control/command-impl.hpp | 22 -- src/steam/control/command-mutation.hpp | 15 -- src/steam/control/command-op-closure.hpp | 21 -- src/steam/control/command-simple-closure.hpp | 24 -- src/steam/control/command-storage-holder.hpp | 25 --- src/steam/control/command.cpp | 7 - src/steam/control/command.hpp | 1 - src/steam/control/memento-tie.hpp | 15 -- src/steam/engine/type-handler.hpp | 1 - .../steam/control/command-argument-test.cpp | 45 ---- .../control/command-clone-builder-test.cpp | 5 - .../steam/control/command-equality-test.cpp | 167 +------------- .../steam/control/command-registry-test.cpp | 3 - tests/core/steam/control/memento-tie-test.cpp | 45 ---- tests/library/functor-util-test.cpp | 212 ------------------ tests/library/meta/function-erasure-test.cpp | 47 ---- wiki/thinkPad.ichthyo.mm | 86 ++++--- 23 files changed, 46 insertions(+), 970 deletions(-) delete mode 100644 src/lib/functor-util.hpp delete mode 100644 tests/library/functor-util-test.cpp diff --git a/doc/technical/code/darkCorners.txt b/doc/technical/code/darkCorners.txt index 771ec6175..8e40f0831 100644 --- a/doc/technical/code/darkCorners.txt +++ b/doc/technical/code/darkCorners.txt @@ -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 diff --git a/src/common/guifacade.cpp b/src/common/guifacade.cpp index 1b11bac13..0efed9e21 100644 --- a/src/common/guifacade.cpp +++ b/src/common/guifacade.cpp @@ -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" diff --git a/src/lib/functor-util.hpp b/src/lib/functor-util.hpp deleted file mode 100644 index 92ed46633..000000000 --- a/src/lib/functor-util.hpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - FUNCTOR-UTIL.hpp - collection of helpers for dealing with functors and signals - - Copyright (C) Lumiera.org - 2008, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - - -/** @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 -#include - - - -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 - inline bool - rawComparison (function const& f1, - function const& f2) - { - typedef HijackedFunction const& Hij; - - return reinterpret_cast (f1) - == reinterpret_cast (f2); - } - - /** catch-all for the comparison: functors with - * different base type are always "different" */ - template - inline bool - rawComparison (function const&, - function const&) - { - return false; - } - - /** variant with unchecked access */ - inline bool - rawComparison (void* f1, void* f2) - { - typedef HijackedFunction * HijP; - - return (!f1 && !f2) - || *reinterpret_cast (f1) - == *reinterpret_cast (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 - inline HashVal - rawHashValue (function const& fun) - { - typedef HijackedFunction const& Hij; - - return hash_value (reinterpret_cast (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 -// inline lib::HashVal -// hash_value (function const& fun) -// { -// return util::rawHashValue (fun); -// } - -} - -#endif /*FUNCTOR_UTIL_H*/ diff --git a/src/lib/meta/function-erasure.hpp b/src/lib/meta/function-erasure.hpp index 47764a6ea..6f41e78aa 100644 --- a/src/lib/meta/function-erasure.hpp +++ b/src/lib/meta/function-erasure.hpp @@ -58,7 +58,6 @@ #include "lib/util.hpp" #include "lib/error.hpp" #include "lib/opaque-holder.hpp" -#include "lib/functor-util.hpp" #include @@ -140,14 +139,6 @@ namespace meta{ { return get>(); } - - - 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 (o1.asBase()); - void * *fun2 = reinterpret_cast (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_; - } }; diff --git a/src/lib/meta/maybe-compare.hpp b/src/lib/meta/maybe-compare.hpp index 3564495ba..0cb56e408 100644 --- a/src/lib/meta/maybe-compare.hpp +++ b/src/lib/meta/maybe-compare.hpp @@ -30,15 +30,11 @@ #define LIB_META_MAYBE_COMPARE_H -#include "lib/functor-util.hpp" - -#include 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 - struct Comparator> - { - static bool - equals (function const& f1, function const& f2) - { - return util::rawComparison(f1,f2); - } - - }; + /* == add specialisations here == */ template diff --git a/src/steam/control/command-closure.hpp b/src/steam/control/command-closure.hpp index 1951f1827..8d92a8617 100644 --- a/src/steam/control/command-closure.hpp +++ b/src/steam/control/command-closure.hpp @@ -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_ diff --git a/src/steam/control/command-impl.hpp b/src/steam/control/command-impl.hpp index d1e06c8c0..437c7a8c4 100644 --- a/src/steam/control/command-impl.hpp +++ b/src/steam/control/command-impl.hpp @@ -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); - } }; diff --git a/src/steam/control/command-mutation.hpp b/src/steam/control/command-mutation.hpp index 282443169..1184e9503 100644 --- a/src/steam/control/command-mutation.hpp +++ b/src/steam/control/command-mutation.hpp @@ -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); - } }; diff --git a/src/steam/control/command-op-closure.hpp b/src/steam/control/command-op-closure.hpp index f97282a74..e04040482 100644 --- a/src/steam/control/command-op-closure.hpp +++ b/src/steam/control/command-op-closure.hpp @@ -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(p1) - , static_cast(p2) ); - } }; template @@ -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); } }; diff --git a/src/steam/control/command-simple-closure.hpp b/src/steam/control/command-simple-closure.hpp index 0a64ec06f..dc10d49f5 100644 --- a/src/steam/control/command-simple-closure.hpp +++ b/src/steam/control/command-simple-closure.hpp @@ -204,30 +204,6 @@ namespace control { { arguments_.template create(); } - - - bool - equals (CmdClosure const& other) const override - { - const SimpleClosure* toCompare = dynamic_cast (&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); - } }; diff --git a/src/steam/control/command-storage-holder.hpp b/src/steam/control/command-storage-holder.hpp index e818f1c16..236c228a8 100644 --- a/src/steam/control/command-storage-holder.hpp +++ b/src/steam/control/command-storage-holder.hpp @@ -255,31 +255,6 @@ namespace control { { return memento_->getState(); } - - bool - equals (CmdClosure const& other) const - { - const StorageHolder* toCompare = dynamic_cast (&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); - } }; diff --git a/src/steam/control/command.cpp b/src/steam/control/command.cpp index 2844408f4..9f09f10f5 100644 --- a/src/steam/control/command.cpp +++ b/src/steam/control/command.cpp @@ -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 { diff --git a/src/steam/control/command.hpp b/src/steam/control/command.hpp index 7b1191976..33f3dd5f2 100644 --- a/src/steam/control/command.hpp +++ b/src/steam/control/command.hpp @@ -223,7 +223,6 @@ namespace control { private: void setArguments (Arguments&); void setArguments (lib::diff::Rec const&); - static bool equivalentImpl (Command const&, Command const&); }; diff --git a/src/steam/control/memento-tie.hpp b/src/steam/control/memento-tie.hpp index 71535cf45..50f70f97a 100644 --- a/src/steam/control/memento-tie.hpp +++ b/src/steam/control/memento-tie.hpp @@ -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_)); - } }; diff --git a/src/steam/engine/type-handler.hpp b/src/steam/engine/type-handler.hpp index cf49bcd9e..0eae6666f 100644 --- a/src/steam/engine/type-handler.hpp +++ b/src/steam/engine/type-handler.hpp @@ -44,7 +44,6 @@ #include "lib/error.hpp" #include "lib/hash-value.h" -#include "lib/functor-util.hpp" #include #include diff --git a/tests/core/steam/control/command-argument-test.cpp b/tests/core/steam/control/command-argument-test.cpp index ba3b39c80..1b6a4155b 100644 --- a/tests/core/steam/control/command-argument-test.cpp +++ b/tests/core/steam/control/command-argument-test.cpp @@ -213,7 +213,6 @@ namespace test { Tracker::instanceCnt = 0; createTuples (testTuples); - checkArgumentComparison (); serialiseArgTuples (testTuples); testTuples.clear(); @@ -291,50 +290,6 @@ namespace test { - /** @test verify the comparison operators */ - void - checkArgumentComparison () - { - StorageHolder 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. */ diff --git a/tests/core/steam/control/command-clone-builder-test.cpp b/tests/core/steam/control/command-clone-builder-test.cpp index bccb0df22..27d399b17 100644 --- a/tests/core/steam/control/command-clone-builder-test.cpp +++ b/tests/core/steam/control/command-clone-builder-test.cpp @@ -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); } }; diff --git a/tests/core/steam/control/command-equality-test.cpp b/tests/core/steam/control/command-equality-test.cpp index 963bee5d5..513a21abf 100644 --- a/tests/core/steam/control/command-equality-test.cpp +++ b/tests/core/steam/control/command-equality-test.cpp @@ -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 Storage; - Storage abuff1; - Storage abuff2; - CHECK (abuff1 == abuff2); - - TypedArguments 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) diff --git a/tests/core/steam/control/command-registry-test.cpp b/tests/core/steam/control/command-registry-test.cpp index 0e9e118fa..364b46b16 100644 --- a/tests/core/steam/control/command-registry-test.cpp +++ b/tests/core/steam/control/command-registry-test.cpp @@ -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 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(); diff --git a/tests/core/steam/control/memento-tie-test.cpp b/tests/core/steam/control/memento-tie-test.cpp index 7b5e73495..0bc5d96cb 100644 --- a/tests/core/steam/control/memento-tie-test.cpp +++ b/tests/core/steam/control/memento-tie-test.cpp @@ -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 u1_fun; // deliberately unbound - function 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); - } }; diff --git a/tests/library/functor-util-test.cpp b/tests/library/functor-util-test.cpp deleted file mode 100644 index ad1e11c7b..000000000 --- a/tests/library/functor-util-test.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - FunctorUtil(Test) - verifying function object and signal utilities - - Copyright (C) Lumiera.org - 2009, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -* *****************************************************/ - -/** @file functor-util-test.cpp - ** unit test \ref FunctorUtil_test - */ - - - -#include "lib/test/run.hpp" -#include "lib/functor-util.hpp" - -#include -#include -#include - -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 Fvi; - typedef function Fiv; - - typedef function 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 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 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 diff --git a/tests/library/meta/function-erasure-test.cpp b/tests/library/meta/function-erasure-test.cpp index 9cda013e6..60dfeb7f5 100644 --- a/tests/library/meta/function-erasure-test.cpp +++ b/tests/library/meta/function-erasure-test.cpp @@ -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()) () ); - -#if false ////////////////////////////////////////////////////////TODO: restore throwing ASSERT - VERIFY_ERROR (ASSERTION, f1.getFun() ); -#endif//////////////////////////////////////////////////////////// - } @@ -231,27 +205,6 @@ namespace test { } // likely to result in heap corruption or SEGV - template - 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 - bool - detect_Clone (HOL const& h1) - { - HOL clone (h1); - return (clone == h1); - } - - template void detect_unboundFunctor (HOL h1, HOL h2, HOL h3) diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index cdba0726f..7cbd61f5e 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -44930,7 +44930,8 @@ - + + @@ -45162,8 +45163,8 @@ - - + + @@ -45255,11 +45256,11 @@ - - - - - + + + + + @@ -45731,7 +45732,8 @@ - + + @@ -45763,7 +45765,7 @@ - + @@ -45779,7 +45781,7 @@ - + @@ -45793,8 +45795,6 @@ - - @@ -45939,11 +45939,10 @@ - - - - - + + + + @@ -45956,10 +45955,9 @@ er wollte "versuchen, Lumiera zu bauen"

- -
- - + + + @@ -45988,8 +45986,7 @@ wann sind Funktoren äquivalent ??

- - + @@ -46008,8 +46005,7 @@ sei die Dose offen...

- -
+
@@ -46042,8 +46038,7 @@ aber ansonsten alle validen definierten Funktionen untereinander verschieden sind.

- - +
@@ -46053,9 +46048,9 @@
- + - + @@ -46073,8 +46068,7 @@ sonst auf Äquivalenz getestet

- - +
@@ -46087,8 +46081,7 @@ und genau das Letztere ist nicht garantiert korrekt implementierbar

- - +
@@ -46110,12 +46103,11 @@ Selbst verschiedene Closures haben selbst die noch eine eindeutige Identität

- - +
- - + + @@ -46142,8 +46134,7 @@ d.h. wir brauchen keine Äquivalenz?

- - +
@@ -46163,20 +46154,23 @@
- - + + - - + + - - + +
+ + +