rectify-design(#301): disentangle CmdClosure hierarchy
Completely removed the nested hierarchy, where the top-level implementation forwarded to yet another sub-implementation of the same interface. Rather, this sub-implementation (OpClosure) is now a mere implementation detail class without VTable, and without half-baked re-implementation of the CmdClosure interface. And the state-switch from unbound to bound arguments is now implemented as a plain-flat boolean flag, instead of hiding it in the VTable. To make this possible, without having to rewrite lots of tests, I've created a clone of StorageHolder as a "proof-of-concept" dummy implementation, for the sole purpose of writing test fixtures. This one behaves similar to the real-world thing, but cares only for closing the command operation and omits all the gory details of memento capturing and undo.
This commit is contained in:
parent
9515e45723
commit
e0f866092d
10 changed files with 300 additions and 115 deletions
|
|
@ -468,7 +468,10 @@ namespace func{
|
|||
|
||||
/**
|
||||
* Closure-creating template.
|
||||
* @note we take functor objects \em and parameters by reference
|
||||
* The instance is linked (reference) to a given concrete argument tuple.
|
||||
* A functor with a matching signature may then either be _closed_ over
|
||||
* this argument values, or even be invoked right away with theses arguments.
|
||||
* @warning we take functor objects _and parameters_ by reference
|
||||
*/
|
||||
template<typename SIG>
|
||||
class TupleApplicator
|
||||
|
|
|
|||
|
|
@ -101,9 +101,6 @@ namespace control {
|
|||
class CommandImplCloneBuilder;
|
||||
|
||||
|
||||
class CmdClosure;
|
||||
typedef std::shared_ptr<CmdClosure> PClo;
|
||||
|
||||
|
||||
|
||||
/** Interface */
|
||||
|
|
@ -124,17 +121,7 @@ namespace control {
|
|||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class AbstractClosure
|
||||
: public CmdClosure
|
||||
{
|
||||
bool isValid() const override { return false; }
|
||||
bool isCaptured() const override { return false; }
|
||||
void accept (CommandImplCloneBuilder&) const override {}
|
||||
};
|
||||
|
||||
using PClo = std::shared_ptr<CmdClosure>;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -110,14 +110,14 @@ namespace control {
|
|||
* of the embedded FunErasure objects holding the command operation
|
||||
* and undo functors, and the vtable of the embedded CmdClosure */
|
||||
template<typename ARG>
|
||||
CommandImpl (shared_ptr<ARG> pArgHolder
|
||||
CommandImpl (shared_ptr<ARG> pStorageHolder
|
||||
,_TY (Func_op) const& operFunctor
|
||||
,_TY (Func_cap) const& captFunctor
|
||||
,_TY (Func_undo) const& undoFunctor
|
||||
)
|
||||
: do_(operFunctor)
|
||||
, undo_(pArgHolder->tie (undoFunctor, captFunctor))
|
||||
, pClo_(pArgHolder)
|
||||
, undo_(pStorageHolder->tie (undoFunctor, captFunctor))
|
||||
, pClo_(pStorageHolder)
|
||||
, defaultPatt_(HandlingPattern::defaultID())
|
||||
{ }
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ namespace control {
|
|||
ParamAccessor& operator= (ParamAccessor const&) =delete;
|
||||
ParamAccessor& operator= (ParamAccessor&&) =delete;
|
||||
ParamAccessor (ParamAccessor const&) =default;
|
||||
ParamAccessor (ParamAccessor&&) =default;
|
||||
|
||||
|
||||
////////////////////TODO the recursion-end of the access operations goes here
|
||||
|
|
@ -151,7 +152,6 @@ namespace control {
|
|||
*/
|
||||
template<typename SIG>
|
||||
class OpClosure
|
||||
: public AbstractClosure
|
||||
{
|
||||
using Args = typename FunctionSignature< function<SIG> >::Args;
|
||||
using Builder = BuildTupleAccessor<ParamAccessor, Args>;
|
||||
|
|
@ -159,45 +159,36 @@ namespace control {
|
|||
using ParamStorageTuple =typename Builder::Product;
|
||||
|
||||
ParamStorageTuple params_;
|
||||
|
||||
protected:
|
||||
OpClosure()
|
||||
: params_(Tuple<Args>())
|
||||
{ }
|
||||
bool activated_;
|
||||
|
||||
public:
|
||||
using ArgTuple = Tuple<Args>;
|
||||
|
||||
|
||||
OpClosure()
|
||||
: params_(Tuple<Args>())
|
||||
, activated_(false)
|
||||
{ }
|
||||
|
||||
explicit
|
||||
OpClosure (ArgTuple const& args)
|
||||
: params_(args)
|
||||
, activated_(true)
|
||||
{ }
|
||||
|
||||
/** create a clone copy of this, without disclosing the exact type */
|
||||
PClo
|
||||
createClone (TypedAllocationManager& storageManager)
|
||||
/** we deliberately support immutable types as command arguments */
|
||||
OpClosure& operator= (OpClosure const&) =delete;
|
||||
OpClosure& operator= (OpClosure&&) =delete;
|
||||
OpClosure (OpClosure const&) =default;
|
||||
OpClosure (OpClosure&&) =default;
|
||||
|
||||
|
||||
bool
|
||||
isValid () const
|
||||
{
|
||||
return storageManager.create<OpClosure> (*this);
|
||||
return activated_;
|
||||
}
|
||||
|
||||
/** assign a new parameter tuple to this */
|
||||
void
|
||||
bindArguments (Arguments& args) override
|
||||
{
|
||||
//params_ = args.get<ArgTuple>();
|
||||
}
|
||||
|
||||
/** assign a new set of parameter values to this.
|
||||
* @note the values are passed packaged into a sequence
|
||||
* of GenNode elements. This is the usual way
|
||||
* arguments are passed from the UI-Bus
|
||||
*/
|
||||
void
|
||||
bindArguments (lib::diff::Rec const& paramData) override
|
||||
{
|
||||
//params_ = buildTuple<Args> (paramData);
|
||||
}
|
||||
|
||||
|
||||
/** Core operation: use the embedded argument tuple for invoking a functor
|
||||
* @param unboundFunctor an function object, whose function arguments are
|
||||
|
|
@ -208,7 +199,7 @@ namespace control {
|
|||
* Thus this function can't be const.
|
||||
*/
|
||||
void
|
||||
invoke (CmdFunctor const& unboundFunctor) override
|
||||
invoke (CmdFunctor const& unboundFunctor)
|
||||
{
|
||||
TupleApplicator<SIG> apply_this_arguments(params_);
|
||||
apply_this_arguments (unboundFunctor.getFun<SIG>());
|
||||
|
|
@ -216,7 +207,7 @@ namespace control {
|
|||
|
||||
|
||||
|
||||
operator string() const override
|
||||
operator string() const
|
||||
{
|
||||
std::ostringstream buff;
|
||||
params_.dump (buff << "OpClosure(" );
|
||||
|
|
@ -230,19 +221,9 @@ namespace control {
|
|||
}
|
||||
|
||||
|
||||
bool isValid () const override { return true; }
|
||||
|
||||
/// 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); }
|
||||
|
||||
bool
|
||||
equals (CmdClosure const& other) const override
|
||||
{
|
||||
const OpClosure* toCompare = dynamic_cast<const OpClosure*> (&other);
|
||||
return (toCompare)
|
||||
&& (*this == *toCompare);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
223
src/proc/control/command-simple-closure.hpp
Normal file
223
src/proc/control/command-simple-closure.hpp
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
COMMAND-SIMPLE-CLOSURE.hpp - demo implementation of command closure
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2016, 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 command-simple-closure.hpp
|
||||
** Proof-of-concept implementation of CmdClosure.
|
||||
** This is used for test only, to invoke an arbitrary matching functor with
|
||||
** arguments stored embedded within this closure. In the real system, a more
|
||||
** [elaborate version](\ref StorageHolder) of the same concept is used, with
|
||||
** the additional complication of managing the UNDO operation as well.
|
||||
**
|
||||
** \par historical note
|
||||
** This proof-of-concept variation was split off in an attempt to improve the
|
||||
** overall design of the command / closure system. The original design had the
|
||||
** embedded argument holder also implement the CmdClosure interface, which is
|
||||
** a clever implementation and code-reuse trick, but otherwise caused confusion.
|
||||
**
|
||||
** @see Ticket #301
|
||||
** @see CommandMutation_test
|
||||
** @see StorageHolder
|
||||
** @see OpClosure
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef CONTROL_COMMAND_SIMPLE_CLOSURE_H
|
||||
#define CONTROL_COMMAND_SIMPLE_CLOSURE_H
|
||||
|
||||
#include "lib/typed-allocation-manager.hpp"
|
||||
#include "proc/control/command-op-closure.hpp"
|
||||
#include "lib/opaque-holder.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
namespace proc {
|
||||
namespace control {
|
||||
|
||||
using lib::InPlaceBuffer;
|
||||
using std::string;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Dummy / proof-of-concept implementation of CmdClosure.
|
||||
* It is a specifically typed subclass, which serves to hold
|
||||
* storage for the concrete invocation arguments within an
|
||||
* inline buffer.
|
||||
* @note for demonstration and unit testing
|
||||
* @see StorageHolder real world implementation
|
||||
*/
|
||||
template<typename SIG>
|
||||
class SimpleClosure
|
||||
: public CmdClosure
|
||||
{
|
||||
using ArgHolder = OpClosure<SIG>;
|
||||
using ArgumentBuff = InPlaceBuffer<ArgHolder>;
|
||||
|
||||
using ArgTuple = typename ArgHolder::ArgTuple;
|
||||
using Args = typename Types<ArgTuple>::Seq;
|
||||
|
||||
|
||||
/* ====== in-place argument storage ====== */
|
||||
|
||||
ArgumentBuff arguments_;
|
||||
|
||||
|
||||
|
||||
/* ==== proxied CmdClosure interface ==== */
|
||||
|
||||
public:
|
||||
virtual bool
|
||||
isValid () const override
|
||||
{
|
||||
return arguments_->isValid();
|
||||
}
|
||||
|
||||
virtual bool
|
||||
isCaptured() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** assign a new parameter tuple to this */
|
||||
virtual void
|
||||
bindArguments (Arguments& args) override
|
||||
{
|
||||
storeTuple (args.get<ArgTuple>());
|
||||
}
|
||||
|
||||
/** assign a new set of parameter values to this.
|
||||
* @note the values are passed packaged into a sequence
|
||||
* of GenNode elements. This is the usual way
|
||||
* arguments are passed from the UI-Bus
|
||||
*/
|
||||
virtual void
|
||||
bindArguments (lib::diff::Rec const& paramData) override
|
||||
{
|
||||
storeTuple (buildTuple<Args> (paramData));
|
||||
}
|
||||
|
||||
|
||||
virtual void
|
||||
invoke (CmdFunctor const& func) override
|
||||
{
|
||||
if (!isValid())
|
||||
throw lumiera::error::State ("Lifecycle error: can't bind functor, "
|
||||
"command arguments not yet provided",
|
||||
LUMIERA_ERROR_UNBOUND_ARGUMENTS);
|
||||
|
||||
arguments_->invoke(func);
|
||||
}
|
||||
|
||||
|
||||
virtual
|
||||
operator string() const override
|
||||
{
|
||||
return "Command-Closure{ arguments="
|
||||
+ (arguments_->isValid()? string(*arguments_) : "unbound")
|
||||
+ " }"
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** per default, all data within StorageHolder
|
||||
* is set up in \em empty state. Later on, the
|
||||
* command arguments are to be provided by #bind ,
|
||||
* whereas the undo functions will be wired by #tie
|
||||
*/
|
||||
SimpleClosure ()
|
||||
: arguments_()
|
||||
{ }
|
||||
|
||||
explicit
|
||||
SimpleClosure (ArgTuple const& args)
|
||||
: arguments_()
|
||||
{
|
||||
storeTuple (args);
|
||||
}
|
||||
|
||||
SimpleClosure (SimpleClosure const& oAh)
|
||||
: arguments_()
|
||||
{
|
||||
if (oAh.arguments_->isValid()) // don't clone garbage from invalid arguments
|
||||
arguments_.template create<ArgHolder> (*oAh.arguments_);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
accept (CommandImplCloneBuilder&) const override
|
||||
{
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
|
||||
/** has undo state capturing been invoked? */
|
||||
bool canUndo () const { return false; }
|
||||
bool empty () const { return !arguments_->isValid(); }
|
||||
|
||||
|
||||
/** store a new argument tuple within this StorageHolder,
|
||||
* discarding any previously stored arguments */
|
||||
void
|
||||
storeTuple (ArgTuple const& argTup)
|
||||
{
|
||||
arguments_.template create<ArgHolder> (argTup);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}} // namespace proc::control
|
||||
#endif /*CONTROL_COMMAND_SIMPLE_CLOSURE_H*/
|
||||
|
|
@ -61,23 +61,6 @@ namespace control {
|
|||
using std::string;
|
||||
|
||||
|
||||
namespace { // empty state marker objects for StorageHolder
|
||||
|
||||
template<typename SIG>
|
||||
struct MissingArguments
|
||||
: OpClosure<SIG>
|
||||
{
|
||||
virtual bool isValid () const override { return false; }
|
||||
};
|
||||
|
||||
|
||||
template<typename SIG, typename MEM>
|
||||
struct UntiedMemento
|
||||
: MementoTie<SIG,MEM>
|
||||
{ };
|
||||
|
||||
} // (END) impl details / empty state marker objects
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -94,17 +77,13 @@ namespace control {
|
|||
*/
|
||||
template<typename SIG, typename MEM>
|
||||
class StorageHolder
|
||||
: public AbstractClosure
|
||||
: public CmdClosure
|
||||
{
|
||||
/** copy construction allowed(but no assignment)*/
|
||||
StorageHolder& operator= (StorageHolder const&);
|
||||
|
||||
|
||||
using ArgHolder = OpClosure<SIG>;
|
||||
using MemHolder = MementoTie<SIG,MEM>;
|
||||
|
||||
using ArgumentBuff = InPlaceBuffer<ArgHolder, sizeof(ArgHolder), MissingArguments<SIG>>;
|
||||
using MementoBuff = InPlaceBuffer<MemHolder, sizeof(MemHolder), UntiedMemento<SIG,MEM>>;
|
||||
using ArgumentBuff = InPlaceBuffer<ArgHolder>;
|
||||
using MementoBuff = InPlaceBuffer<MemHolder>;
|
||||
|
||||
using ArgTuple = typename ArgHolder::ArgTuple;
|
||||
using Args = typename Types<ArgTuple>::Seq;
|
||||
|
|
@ -169,7 +148,7 @@ namespace control {
|
|||
operator string() const override
|
||||
{
|
||||
return "Command-State{ arguments="
|
||||
+ (*arguments_? string(*arguments_) : "unbound")
|
||||
+ (arguments_->isValid()? string(*arguments_) : "unbound")
|
||||
+ ", "+string(*memento_)+"}"
|
||||
;
|
||||
}
|
||||
|
|
@ -186,7 +165,10 @@ namespace control {
|
|||
, memento_()
|
||||
{ }
|
||||
|
||||
/** copy construction allowed(but no assignment) */
|
||||
/** copy construction allowed(but no assignment).
|
||||
* @remarks rationale is to support immutable argument values,
|
||||
* which means default/copy construction is OK
|
||||
*/
|
||||
StorageHolder (StorageHolder const& oAh)
|
||||
: arguments_()
|
||||
, memento_()
|
||||
|
|
@ -198,6 +180,12 @@ namespace control {
|
|||
memento_.template create<MemHolder> (*oAh.memento_);
|
||||
}
|
||||
|
||||
|
||||
/** copy construction allowed(but no assignment)*/
|
||||
StorageHolder& operator= (StorageHolder const&) = delete;
|
||||
|
||||
|
||||
|
||||
/** assist with creating a clone copy;
|
||||
* this results in invocation of the copy ctor */
|
||||
void
|
||||
|
|
@ -259,7 +247,7 @@ namespace control {
|
|||
{
|
||||
const StorageHolder* toCompare = dynamic_cast<const StorageHolder*> (&other);
|
||||
return (toCompare)
|
||||
&& (*this == *toCompare);
|
||||
and (*this == *toCompare);
|
||||
}
|
||||
|
||||
/// Supporting equality comparisons...
|
||||
|
|
|
|||
|
|
@ -110,13 +110,11 @@ namespace control {
|
|||
}
|
||||
|
||||
|
||||
protected:
|
||||
public:
|
||||
MementoTie()
|
||||
: MementoTie (function<SIG_undo>(), function<SIG_cap>())
|
||||
{ }
|
||||
|
||||
public:
|
||||
|
||||
/** creates an execution context tying together the provided functions.
|
||||
* Bound copies of these functors may be pulled from the MementoTie,
|
||||
* in order to build the closures (with the concrete operation arguments)
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ END
|
|||
|
||||
|
||||
TEST "Command functor and UNDO functor" CommandMutation_test <<END
|
||||
out: empty placeholder closure: OpClosure\(0\)
|
||||
out: param values: OpClosure\(23\)
|
||||
out: saved state: 11
|
||||
out-lit: empty placeholder closure: Command-Closure{ arguments=unbound }
|
||||
out-lit: param values: Command-Closure{ arguments=OpClosure(23) }
|
||||
out-lit: saved state: 11
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "proc/control/command-mutation.hpp"
|
||||
#include "proc/control/argument-erasure.hpp"
|
||||
#include "proc/control/command-storage-holder.hpp"
|
||||
#include "proc/control/command-simple-closure.hpp"
|
||||
#include "proc/control/memento-tie.hpp"
|
||||
#include "lib/meta/tuple-helper.hpp"
|
||||
#include "lib/format-cout.hpp"
|
||||
|
|
@ -86,16 +87,18 @@ namespace test {
|
|||
using ArgTuple = Tuple<Types<char>>;
|
||||
using ArgHolder = OpClosure<Sig_oper>;
|
||||
using MemHolder = MementoTie<Sig_oper, string>;
|
||||
using Closure = SimpleClosure<Sig_oper>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************************//**
|
||||
* @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)
|
||||
* @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.
|
||||
*
|
||||
|
|
@ -171,20 +174,22 @@ namespace test {
|
|||
verifyClosureEquality()
|
||||
{
|
||||
ArgHolder a1 (make_tuple ('a'));
|
||||
ArgHolder a2 (make_tuple ('z'));
|
||||
ArgHolder a2 (make_tuple ('a'));
|
||||
ArgHolder a3 (make_tuple ('z'));
|
||||
CHECK (a1 == a1);
|
||||
CHECK (a1 != a2);
|
||||
CHECK (a2 != a1);
|
||||
|
||||
TypedArguments<ArgTuple> newArgs (make_tuple ('z'));
|
||||
a1.bindArguments(newArgs);
|
||||
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);
|
||||
|
|
@ -194,17 +199,18 @@ namespace test {
|
|||
UndoMutation umu2 (abuff2.tie (undo_1, capt_1));
|
||||
CHECK (abuff1 == abuff2); // same capture function, no memento state!
|
||||
|
||||
umu1.captureState(a1);
|
||||
Closure args {make_tuple ('u')};
|
||||
umu1.captureState(args);
|
||||
CHECK (abuff1 != abuff2);
|
||||
umu2.captureState(a1);
|
||||
umu2.captureState(args);
|
||||
CHECK (abuff1 == abuff2); // same functions, same memento state
|
||||
|
||||
check_ += "fake"; // manipulate the "state" to be captured
|
||||
umu2.captureState(a1); // capture again...
|
||||
umu2.captureState(args); // capture again...
|
||||
CHECK (abuff1 != abuff2); // captured memento differs!
|
||||
|
||||
UndoMutation umu3 (abuff2.tie (undo_1, capt_2));
|
||||
umu3.captureState(a1);
|
||||
umu3.captureState(args);
|
||||
CHECK (abuff1 != abuff2); // differing functions detected
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include "lib/test/run.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "proc/control/command-mutation.hpp"
|
||||
#include "proc/control/command-storage-holder.hpp"
|
||||
#include "proc/control/command-simple-closure.hpp"
|
||||
#include "proc/control/memento-tie.hpp"
|
||||
#include "lib/meta/tuple-helper.hpp"
|
||||
#include "lib/meta/typelist.hpp"
|
||||
|
|
@ -90,8 +90,7 @@ namespace test {
|
|||
}
|
||||
|
||||
|
||||
/** @test check the Mutation functor w#include "lib/meta/typelist.hpp"
|
||||
hich is bound to our \c testFunc(int) .
|
||||
/** @test check the Mutation functor which is bound to our `testFunc(int)`.
|
||||
* Then create a argument closure and use this to invoke the Mutation
|
||||
* and verify actually \c testFunc(param) is executed.
|
||||
*/
|
||||
|
|
@ -103,16 +102,16 @@ hich is bound to our \c testFunc(int) .
|
|||
|
||||
Mutation functor (funky);
|
||||
|
||||
MissingArguments<SIG_fun> nullClosure;
|
||||
CHECK (!nullClosure);
|
||||
SimpleClosure<SIG_fun> nullClosure;
|
||||
CHECK (not nullClosure.isValid());
|
||||
cout << "empty placeholder closure: " << nullClosure << endl;
|
||||
VERIFY_ERROR (UNBOUND_ARGUMENTS, functor(nullClosure) );
|
||||
|
||||
// now create a real closure....
|
||||
Tuple<Types<int> > param = std::make_tuple (23);
|
||||
OpClosure<void(int)> close_over (param);
|
||||
SimpleClosure<void(int)> closed_over{param};
|
||||
|
||||
CmdClosure& closure (close_over);
|
||||
CmdClosure& closure (closed_over);
|
||||
CHECK (closure);
|
||||
|
||||
cout << "param values: " << closure << endl;
|
||||
|
|
@ -152,12 +151,12 @@ hich is bound to our \c testFunc(int) .
|
|||
UndoMutation undoFunctor (mementoHolder);
|
||||
CHECK (!mementoHolder);
|
||||
|
||||
MissingArguments<void(void)> nullClosure;
|
||||
SimpleClosure<void(void)> nullClosure;
|
||||
VERIFY_ERROR (UNBOUND_ARGUMENTS, undoFunctor(nullClosure) );
|
||||
VERIFY_ERROR (UNBOUND_ARGUMENTS, undoFunctor.captureState(nullClosure) );
|
||||
|
||||
Tuple<Types<> > param;
|
||||
OpClosure<void()> clo (param);
|
||||
SimpleClosure<void()> clo{param};
|
||||
|
||||
CHECK (!mementoHolder);
|
||||
VERIFY_ERROR (MISSING_MEMENTO, undoFunctor (clo) );
|
||||
|
|
|
|||
Loading…
Reference in a new issue