draft version of CmdClosure and Mutation interface now passing compiler
This commit is contained in:
parent
e951c468a7
commit
f358f548d1
9 changed files with 403 additions and 290 deletions
|
|
@ -305,16 +305,17 @@ namespace typelist{
|
|||
|
||||
|
||||
|
||||
Tuple<Types<> >
|
||||
inline
|
||||
Tuple< Types<> >
|
||||
makeNullTuple ()
|
||||
{
|
||||
return Tuple<Types<> > ();
|
||||
}
|
||||
|
||||
|
||||
template< typename T1
|
||||
>
|
||||
Tuple<Types<T1> >
|
||||
template<typename T1>
|
||||
inline
|
||||
Tuple< Types<T1> >
|
||||
make ( T1 a1 =T1()
|
||||
)
|
||||
{
|
||||
|
|
@ -325,7 +326,8 @@ namespace typelist{
|
|||
template< typename T1
|
||||
, typename T2
|
||||
>
|
||||
Tuple<Types<T1,T2> >
|
||||
inline
|
||||
Tuple< Types<T1,T2> >
|
||||
make ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
)
|
||||
|
|
@ -338,7 +340,8 @@ namespace typelist{
|
|||
, typename T2
|
||||
, typename T3
|
||||
>
|
||||
Tuple<Types<T1,T2,T3> >
|
||||
inline
|
||||
Tuple< Types<T1,T2,T3> >
|
||||
make ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
, T3 a3 =T3()
|
||||
|
|
@ -353,7 +356,8 @@ namespace typelist{
|
|||
, typename T3
|
||||
, typename T4
|
||||
>
|
||||
Tuple<Types<T1,T2,T3,T4> >
|
||||
inline
|
||||
Tuple< Types<T1,T2,T3,T4> >
|
||||
make ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
, T3 a3 =T3()
|
||||
|
|
@ -370,7 +374,8 @@ namespace typelist{
|
|||
, typename T4
|
||||
, typename T5
|
||||
>
|
||||
Tuple<Types<T1,T2,T3,T4,T5> >
|
||||
inline
|
||||
Tuple< Types<T1,T2,T3,T4,T5> >
|
||||
make ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
, T3 a3 =T3()
|
||||
|
|
@ -392,7 +397,8 @@ namespace typelist{
|
|||
, typename T8
|
||||
, typename T9
|
||||
>
|
||||
Tuple<Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> >
|
||||
inline
|
||||
Tuple< Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> >
|
||||
make ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
, T3 a3 =T3()
|
||||
|
|
@ -443,7 +449,7 @@ namespace typelist{
|
|||
typedef BuildTupleAccessor<Tail,_X_,TUP, i+1> NextBuilder;
|
||||
typedef typename NextBuilder::Accessor NextAccessor;
|
||||
|
||||
ArgTuple& argData_;
|
||||
ArgTuple const& argData_;
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -456,7 +462,7 @@ namespace typelist{
|
|||
> Accessor;
|
||||
|
||||
|
||||
BuildTupleAccessor (ArgTuple& tup)
|
||||
BuildTupleAccessor (ArgTuple const& tup)
|
||||
: argData_(tup)
|
||||
{ }
|
||||
|
||||
|
|
@ -474,9 +480,18 @@ namespace typelist{
|
|||
class BuildTupleAccessor<Types<>, _X_, TUP, i>
|
||||
{
|
||||
typedef Tuple<Types<> > ArgTuple;
|
||||
ArgTuple const& argData_;
|
||||
|
||||
public:
|
||||
typedef _X_<NullType, TUP, TUP, 0> Accessor;
|
||||
|
||||
BuildTupleAccessor (ArgTuple const& tup)
|
||||
: argData_(tup)
|
||||
{ }
|
||||
|
||||
/** used to get the product of this builder template... */
|
||||
operator Accessor() { return Accessor(argData_); }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -36,25 +36,142 @@
|
|||
#define CONTROL_COMMAND_CLOSURE_H
|
||||
|
||||
//#include "pre.hpp"
|
||||
#include "lib/meta/typelist.hpp"
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/meta/function-closure.hpp"
|
||||
#include "lib/meta/tuple.hpp"
|
||||
|
||||
//#include <tr1/memory>
|
||||
#include <tr1/memory>
|
||||
#include <tr1/functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
#include "lib/test/test-helper.hpp" /////////////////TODO remove this
|
||||
using lib::test::showSizeof;
|
||||
|
||||
using std::cout; //////////////////////////////////TODO remove this
|
||||
using std::endl;
|
||||
|
||||
|
||||
namespace control {
|
||||
|
||||
// using lumiera::Symbol;
|
||||
// using std::tr1::shared_ptr;
|
||||
using std::string;
|
||||
using std::ostream;
|
||||
using std::tr1::function;
|
||||
using lumiera::typelist::FunctionSignature;
|
||||
using lumiera::typelist::Tuple;
|
||||
using lumiera::typelist::BuildTupleAccessor;
|
||||
|
||||
using lumiera::typelist::NullType;
|
||||
|
||||
class CmdClosure;
|
||||
typedef std::tr1::shared_ptr<CmdClosure> PClo; ///< smart-ptr type used for handling concrete closures
|
||||
|
||||
|
||||
/**
|
||||
* @todo Type-comment
|
||||
*/
|
||||
class CommandClosure
|
||||
/** Interface */
|
||||
class CmdClosure
|
||||
{
|
||||
public:
|
||||
virtual ~CmdClosure() {}
|
||||
|
||||
virtual PClo clone() const =0;
|
||||
|
||||
virtual operator string() const =0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline ostream& operator<< (ostream& os, const CmdClosure& clo) { return os << string(clo); }
|
||||
|
||||
|
||||
template
|
||||
< typename TY
|
||||
, class BASE
|
||||
, class TUP
|
||||
, uint idx
|
||||
>
|
||||
class ParamAccessor
|
||||
: public BASE
|
||||
{
|
||||
TY& element() { return BASE::template getAt<idx>(); }
|
||||
|
||||
public:
|
||||
|
||||
ParamAccessor(TUP const& tuple)
|
||||
: BASE(tuple)
|
||||
{
|
||||
cout << showSizeof(element()) << endl; //////////TODO remove this test code
|
||||
}
|
||||
|
||||
string
|
||||
dump (string const& prefix = "(") const
|
||||
{
|
||||
return BASE::dump (prefix+element());
|
||||
}
|
||||
|
||||
|
||||
////////////////////TODO the real access operations (e.g. for serialising) go here
|
||||
};
|
||||
|
||||
template<class TUP>
|
||||
class ParamAccessor<NullType, TUP, TUP, 0>
|
||||
: public TUP
|
||||
{
|
||||
public:
|
||||
ParamAccessor(TUP const& tuple)
|
||||
: TUP(tuple)
|
||||
{ }
|
||||
|
||||
////////////////////TODO the recursion-end of the access operations goes here
|
||||
|
||||
protected:
|
||||
string
|
||||
dump (string const& prefix) const
|
||||
{
|
||||
return prefix+")";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename SIG>
|
||||
class Closure
|
||||
: public CmdClosure
|
||||
{
|
||||
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
||||
|
||||
typedef Tuple<Args> ArgTuple;
|
||||
|
||||
typedef BuildTupleAccessor<Args,ParamAccessor> BuildAccessor;
|
||||
typedef typename BuildAccessor::Accessor ParamStorageTuple;
|
||||
|
||||
ParamStorageTuple params_;
|
||||
|
||||
public:
|
||||
Closure (ArgTuple const& args)
|
||||
: params_(BuildAccessor(args))
|
||||
{ }
|
||||
|
||||
|
||||
/** create a clone copy of this concrete closure,
|
||||
* hidden behind the generic CmdClosure interface
|
||||
* and owned by a shared_ptr PClo.
|
||||
*/
|
||||
PClo
|
||||
clone() const
|
||||
{
|
||||
return PClo (new Closure (this->params_));
|
||||
}
|
||||
|
||||
operator string() const
|
||||
{
|
||||
UNIMPLEMENTED ("how to do a string conversion on the variable argument tuple??");
|
||||
}
|
||||
};
|
||||
////////////////TODO currently just fleshing out the API....
|
||||
|
||||
|
|
|
|||
|
|
@ -52,8 +52,13 @@
|
|||
#include "proc/control/command.hpp"
|
||||
#include "proc/control/command-mutation.hpp"
|
||||
#include "proc/control/command-closure.hpp"
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/meta/typelist.hpp"
|
||||
#include "lib/meta/typelistutil.hpp"
|
||||
#include "lib/meta/tuple.hpp"
|
||||
|
||||
//#include <tr1/memory>
|
||||
#include <tr1/functional>
|
||||
|
||||
|
||||
|
||||
|
|
@ -62,21 +67,187 @@ namespace control {
|
|||
|
||||
using lumiera::Symbol;
|
||||
// using std::tr1::shared_ptr;
|
||||
using std::tr1::function;
|
||||
|
||||
using lumiera::typelist::FunctionSignature;
|
||||
using lumiera::typelist::FunctionTypedef;
|
||||
using lumiera::typelist::Types;
|
||||
//using lumiera::typelist::NullType;
|
||||
using lumiera::typelist::Tuple;
|
||||
using lumiera::typelist::Append;
|
||||
using lumiera::typelist::SplitLast;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Type analysis helper template.
|
||||
* Used for dissecting a given type signature to derive
|
||||
* the related basic operation signature, the signature of a possible Undo-function
|
||||
* and the signature necessary for capturing undo information. The implementation
|
||||
* relies on re-binding an embedded type defining template, based on the actual
|
||||
* case, as identified by the structure of the given parameter signature.
|
||||
*/
|
||||
template<typename SIG>
|
||||
struct UndoSignature
|
||||
{
|
||||
private:
|
||||
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
||||
typedef typename FunctionSignature< function<SIG> >::Ret Ret;
|
||||
|
||||
/** Case1: defining the Undo-Capture function */
|
||||
template<typename RET, typename ARG>
|
||||
struct Case
|
||||
{
|
||||
typedef RET Memento;
|
||||
typedef typename Append<ARG, Memento>::List ExtendedArglist;
|
||||
typedef typename Tuple<ExtendedArglist>::Type ExtendedArgs;
|
||||
|
||||
typedef typename FunctionTypedef<void, ARG>::Sig OperateSig;
|
||||
typedef typename FunctionTypedef<Ret,ARG>::Sig CaptureSig;
|
||||
typedef typename FunctionTypedef<void, ExtendedArgs>::Sig UndoOp_Sig;
|
||||
};
|
||||
/** Case2: defining the actual Undo function */
|
||||
template<typename ARG>
|
||||
struct Case<void,ARG>
|
||||
{
|
||||
typedef typename ARG::List Args;
|
||||
|
||||
typedef typename SplitLast<Args>::Type Memento;
|
||||
typedef typename SplitLast<Args>::List OperationArglist;
|
||||
typedef typename Tuple<OperationArglist>::Type OperationArgs;
|
||||
|
||||
typedef typename FunctionTypedef<void, OperationArgs>::Sig OperateSig;
|
||||
typedef typename FunctionTypedef<Ret,OperationArgs>::Sig CaptureSig;
|
||||
typedef typename FunctionTypedef<void, ARG>::Sig UndoOp_Sig;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename Case<Ret,Args>::CaptureSig CaptureSig;
|
||||
typedef typename Case<Ret,Args>::UndoOp_Sig UndoOp_Sig;
|
||||
typedef typename Case<Ret,Args>::OperateSig OperateSig;
|
||||
typedef typename Case<Ret,Args>::Memento Memento;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @todo Type-comment
|
||||
* Helper class used solely for \em defining a Command-Object.
|
||||
* This technique is known as "fluent API", see http://en.wikipedia.org/wiki/Fluent_interface
|
||||
* The basic idea is for the user to create a disposable instance of this definition helper,
|
||||
* only for calling a chain of definition functions, which internally build the actual Command object.
|
||||
* Finally, the created Command object will be stored into a registry or handed over to the
|
||||
* ProcDispatcher. To give an example:
|
||||
* \code
|
||||
* CommandDefinition ("test.command1")
|
||||
* .operation (command1::operate) // provide the function to be executed as command
|
||||
* .captureUndo (command1::capture) // provide the function capturing Undo state
|
||||
* .undoOperation (command1::undoIt) // provide the function which might undo the command
|
||||
* .bind (obj, randVal) // bind to the actual command parameters
|
||||
* .executeSync(); // convenience call, forwarding the Command to dispatch.
|
||||
* \endcode
|
||||
*
|
||||
* @todo of course, this needs to be extracted into command-definition.hpp
|
||||
*/
|
||||
class CommandDef
|
||||
{
|
||||
Symbol id_;
|
||||
|
||||
template<typename SIG, typename MEM>
|
||||
struct UndoDefinition
|
||||
{
|
||||
typedef typename FunctionSignature< function<SIG> >::Args BasicArgs;
|
||||
typedef typename FunctionTypedef<MEM,BasicArgs>::Sig UndoCaptureSig;
|
||||
|
||||
UndoDefinition (function<UndoCaptureSig>& undoCapOperation)
|
||||
{
|
||||
cout << showSizeof(undoCapOperation) << endl;
|
||||
UNIMPLEMENTED ("re-fetch command definition and augment it with Functor for capturing Undo information");
|
||||
}
|
||||
|
||||
template<typename SIG2>
|
||||
UndoDefinition&
|
||||
undoOperation (SIG2& how_to_Undo)
|
||||
{
|
||||
typedef typename UndoSignature<SIG2>::UndoOp_Sig UndoSig;
|
||||
|
||||
function<UndoSig> opera3 (how_to_Undo);
|
||||
|
||||
UNIMPLEMENTED ("store actual Undo-Functor into the command definition held by the enclosing UndoDefinition instance");
|
||||
return *this;
|
||||
}
|
||||
|
||||
template
|
||||
< typename T1
|
||||
, typename T2
|
||||
>
|
||||
UndoDefinition& ///////TODO return here the completed Command
|
||||
bind ( T1& p1
|
||||
, T2& p2
|
||||
)
|
||||
{
|
||||
typedef Types<T1,T2> ArgTypes;
|
||||
Tuple<ArgTypes> params(p1,p2);
|
||||
Closure<SIG> clo (params);
|
||||
|
||||
cout << showSizeof(clo) << endl;
|
||||
UNIMPLEMENTED ("complete Command definition by closing all functions");
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** type re-binding helper: create a suitable UndoDefinition type,
|
||||
* based on the UndoSignature template instance given as parameter */
|
||||
template<typename U_SIG>
|
||||
struct BuildUndoDefType
|
||||
{
|
||||
typedef UndoDefinition<typename U_SIG::OperateSig, typename U_SIG::Memento> Type;
|
||||
};
|
||||
|
||||
template<typename SIG>
|
||||
struct BasicDefinition
|
||||
{
|
||||
BasicDefinition(function<SIG>& operation)
|
||||
{
|
||||
cout << showSizeof(operation) << endl;
|
||||
UNIMPLEMENTED ("create new command object an store the operation functor");
|
||||
}
|
||||
|
||||
|
||||
template<typename SIG2>
|
||||
typename BuildUndoDefType<UndoSignature<SIG2> >::Type
|
||||
captureUndo (SIG2& how_to_capture_UndoState)
|
||||
{
|
||||
typedef typename UndoSignature<SIG2>::CaptureSig UndoCapSig;
|
||||
typedef typename BuildUndoDefType<UndoSignature<SIG2> >::Type SpecificUndoDefinition;
|
||||
|
||||
function<UndoCapSig> opera2 (how_to_capture_UndoState);
|
||||
return SpecificUndoDefinition (opera2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
CommandDef (Symbol cmdID)
|
||||
: id_(cmdID)
|
||||
{ }
|
||||
|
||||
template<typename SIG>
|
||||
BasicDefinition<SIG>
|
||||
operation (SIG& operation_to_define)
|
||||
{
|
||||
function<SIG> opera1 (operation_to_define);
|
||||
return BasicDefinition<SIG>(opera1);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////TODO currently just fleshing out the API....
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -32,13 +32,18 @@
|
|||
|
||||
|
||||
|
||||
#ifndef CONTROL_MUTATION_H
|
||||
#define CONTROL_MUTATION_H
|
||||
#ifndef CONTROL_COMMAND_MUTATION_H
|
||||
#define CONTROL_COMMAND_MUTATION_H
|
||||
|
||||
//#include "pre.hpp"
|
||||
#include "lib/error.hpp"
|
||||
#include "proc/control/command-closure.hpp"
|
||||
|
||||
//#include <tr1/memory>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <tr1/functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
|
|
@ -46,6 +51,10 @@ namespace control {
|
|||
|
||||
// using lumiera::Symbol;
|
||||
// using std::tr1::shared_ptr;
|
||||
using boost::scoped_ptr;
|
||||
using std::tr1::function;
|
||||
using std::ostream;
|
||||
using std::string;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -53,6 +62,7 @@ namespace control {
|
|||
*/
|
||||
class Mutation
|
||||
{
|
||||
PClo clo_;
|
||||
|
||||
public:
|
||||
template<typename SIG>
|
||||
|
|
@ -63,12 +73,15 @@ namespace control {
|
|||
|
||||
virtual ~Mutation() {}
|
||||
|
||||
|
||||
virtual Mutation&
|
||||
close (CmdClosure const& closure)
|
||||
{
|
||||
UNIMPLEMENTED ("accept and store a parameter closure");
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
operator() ()
|
||||
{
|
||||
|
|
@ -77,7 +90,7 @@ namespace control {
|
|||
|
||||
|
||||
/* == diagnostics == */
|
||||
typedef pClo Mutation::*_unspecified_bool_type;
|
||||
typedef PClo Mutation::*_unspecified_bool_type;
|
||||
|
||||
/** implicit conversion to "bool" */
|
||||
operator _unspecified_bool_type() const { return isValid()? &Mutation::clo_ : 0; } // never throws
|
||||
|
|
@ -85,12 +98,12 @@ namespace control {
|
|||
|
||||
operator string() const
|
||||
{
|
||||
return isValid()? string (*clo) : "Mutation(state missing)";
|
||||
return isValid()? string (*clo_) : "Mutation(state missing)";
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
isValid ()
|
||||
isValid () const
|
||||
{
|
||||
UNIMPLEMENTED ("mutation lifecycle");
|
||||
}
|
||||
|
|
@ -108,14 +121,30 @@ namespace control {
|
|||
class UndoMutation
|
||||
: public Mutation
|
||||
{
|
||||
scoped_ptr<CmdClosure> memento_;
|
||||
|
||||
public:
|
||||
template<typename SIG>
|
||||
UndoMutation (function<SIG> const& func)
|
||||
template<typename SIG_undo, typename SIG_cap>
|
||||
UndoMutation (function<SIG_undo> const& undoFunc, function<SIG_cap> const& captureFunc)
|
||||
: Mutation(undoFunc)
|
||||
{
|
||||
UNIMPLEMENTED ("build a undo Mutation functor object");
|
||||
}
|
||||
|
||||
UndoMutation (UndoMutation const& o)
|
||||
: Mutation(*this),
|
||||
memento_(o.memento_->clone().get())
|
||||
{ }
|
||||
|
||||
UndoMutation&
|
||||
operator= (UndoMutation const& o)
|
||||
{
|
||||
Mutation::operator= (o);
|
||||
memento_.reset(o.memento_->clone().get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Mutation&
|
||||
captureState ()
|
||||
{
|
||||
|
|
@ -132,6 +161,9 @@ namespace control {
|
|||
////////////////TODO currently just fleshing out the API....
|
||||
|
||||
|
||||
LUMIERA_ERROR_DECLARE (UNBOUND_ARGUMENTS); ///< Mutation functor not yet usable, because arguments aren't bound
|
||||
LUMIERA_ERROR_DECLARE (MISSING_MEMENTO); ///< Undo functor not yet usable, because no undo state has been captured
|
||||
|
||||
|
||||
|
||||
} // namespace control
|
||||
|
|
|
|||
|
|
@ -39,8 +39,18 @@
|
|||
|
||||
namespace control {
|
||||
|
||||
/** */
|
||||
LUMIERA_ERROR_DEFINE (UNBOUND_ARGUMENTS, "Mutation functor not yet usable, because arguments aren't bound");
|
||||
LUMIERA_ERROR_DEFINE (MISSING_MEMENTO, "Undo functor not yet usable, because no undo state has been captured");
|
||||
|
||||
|
||||
|
||||
/** */
|
||||
Command&
|
||||
Command::get (Symbol cmdID)
|
||||
{
|
||||
UNIMPLEMENTED ("fetch an existing command from the internal cmd registry");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,12 @@ namespace control {
|
|||
{
|
||||
|
||||
public:
|
||||
static Command& get (Symbol cmdID);
|
||||
|
||||
virtual ~Command() {};
|
||||
|
||||
virtual void operator() () =0;
|
||||
virtual void undo () =0;
|
||||
|
||||
};
|
||||
////////////////TODO currently just fleshing out the API....
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
namespace control {
|
||||
|
||||
using lumiera::Symbol;
|
||||
// using lumiera::Symbol;
|
||||
// using std::tr1::shared_ptr;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -39,9 +39,6 @@
|
|||
#include "lib/meta/typelist.hpp"
|
||||
#include "lib/meta/typelistutil.hpp"
|
||||
#include "lib/meta/generator.hpp"
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/meta/function-closure.hpp"
|
||||
#include "lib/meta/tuple.hpp"
|
||||
|
||||
|
||||
#include <tr1/functional>
|
||||
|
|
@ -69,245 +66,10 @@ namespace test {
|
|||
// using session::test::TestClip;
|
||||
using lumiera::P;
|
||||
|
||||
using lumiera::typelist::FunctionSignature;
|
||||
using lumiera::typelist::FunctionTypedef;
|
||||
|
||||
using lumiera::typelist::Types;
|
||||
using lumiera::typelist::NullType;
|
||||
using lumiera::typelist::Tuple;
|
||||
using lumiera::typelist::Append;
|
||||
using lumiera::typelist::SplitLast;
|
||||
|
||||
using lumiera::typelist::BuildTupleAccessor;
|
||||
|
||||
|
||||
////////////////////////////////////////////TODO braindump
|
||||
|
||||
|
||||
/**
|
||||
* Type analysis helper template.
|
||||
* Used for dissecting a given type signature to derive
|
||||
* the related basic operation signature, the signature of a possible Undo-function
|
||||
* and the signature necessary for capturing undo information. The implementation
|
||||
* relies on re-binding an embedded type defining template, based on the actual
|
||||
* case, as identified by the structure of the given parameter signature.
|
||||
*/
|
||||
template<typename SIG>
|
||||
struct UndoSignature
|
||||
{
|
||||
private:
|
||||
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
||||
typedef typename FunctionSignature< function<SIG> >::Ret Ret;
|
||||
|
||||
/** Case1: defining the Undo-Capture function */
|
||||
template<typename RET, typename ARG>
|
||||
struct Case
|
||||
{
|
||||
typedef RET Memento;
|
||||
typedef typename Append<ARG, Memento>::List ExtendedArglist;
|
||||
typedef typename Tuple<ExtendedArglist>::Type ExtendedArgs;
|
||||
|
||||
typedef typename FunctionTypedef<void, ARG>::Sig OperateSig;
|
||||
typedef typename FunctionTypedef<Ret,ARG>::Sig CaptureSig;
|
||||
typedef typename FunctionTypedef<void, ExtendedArgs>::Sig UndoOp_Sig;
|
||||
};
|
||||
/** Case2: defining the actual Undo function */
|
||||
template<typename ARG>
|
||||
struct Case<void,ARG>
|
||||
{
|
||||
typedef typename ARG::List Args;
|
||||
|
||||
typedef typename SplitLast<Args>::Type Memento;
|
||||
typedef typename SplitLast<Args>::List OperationArglist;
|
||||
typedef typename Tuple<OperationArglist>::Type OperationArgs;
|
||||
|
||||
typedef typename FunctionTypedef<void, OperationArgs>::Sig OperateSig;
|
||||
typedef typename FunctionTypedef<Ret,OperationArgs>::Sig CaptureSig;
|
||||
typedef typename FunctionTypedef<void, ARG>::Sig UndoOp_Sig;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename Case<Ret,Args>::CaptureSig CaptureSig;
|
||||
typedef typename Case<Ret,Args>::UndoOp_Sig UndoOp_Sig;
|
||||
typedef typename Case<Ret,Args>::OperateSig OperateSig;
|
||||
typedef typename Case<Ret,Args>::Memento Memento;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Interface */
|
||||
class CmdClosure
|
||||
{
|
||||
public:
|
||||
virtual ~CmdClosure() {}
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
< typename TY
|
||||
, class BASE
|
||||
, class TUP
|
||||
, uint idx
|
||||
>
|
||||
struct ParamAccessor
|
||||
: BASE
|
||||
{
|
||||
ParamAccessor(TUP& tuple)
|
||||
: BASE(tuple)
|
||||
{
|
||||
cout << showSizeof(tuple.template getAt<idx>()) << endl;
|
||||
}
|
||||
|
||||
////////////////////TODO the real access operations (e.g. for serialising) go here
|
||||
};
|
||||
|
||||
template<class TUP>
|
||||
struct ParamAccessor<NullType, TUP, TUP, 0>
|
||||
: TUP
|
||||
{
|
||||
ParamAccessor(TUP& tuple)
|
||||
: TUP(tuple)
|
||||
{ }
|
||||
|
||||
////////////////////TODO the recursion-end of the access operations goes here
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename SIG>
|
||||
class Closure
|
||||
: public CmdClosure
|
||||
{
|
||||
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
||||
|
||||
typedef Tuple<Args> ArgTuple;
|
||||
|
||||
typedef BuildTupleAccessor<Args,ParamAccessor> BuildAccessor;
|
||||
typedef typename BuildAccessor::Accessor ParamStorageTuple;
|
||||
|
||||
ParamStorageTuple params_;
|
||||
|
||||
public:
|
||||
Closure (ArgTuple& args)
|
||||
: params_(BuildAccessor(args))
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Helper class used solely for \em defining a Command-Object.
|
||||
* This technique is known as "fluent API", see http://en.wikipedia.org/wiki/Fluent_interface
|
||||
* The basic idea is for the user to create a disposable instance of this definition helper,
|
||||
* only for calling a chain of definition functions, which internally build the actual Command object.
|
||||
* Finally, the created Command object will be stored into a registry or handed over to the
|
||||
* ProcDispatcher. To give an example:
|
||||
* \code
|
||||
* CommandDefinition ("test.command1")
|
||||
* .operation (command1::operate) // provide the function to be executed as command
|
||||
* .captureUndo (command1::capture) // provide the function capturing Undo state
|
||||
* .undoOperation (command1::undoIt) // provide the function which might undo the command
|
||||
* .bind (obj, randVal) // bind to the actual command parameters
|
||||
* .executeSync(); // convenience call, forwarding the Command to dispatch.
|
||||
* \endcode
|
||||
*
|
||||
* @todo of course, this needs to be extracted into command-definition.hpp
|
||||
*/
|
||||
class CommDef
|
||||
{
|
||||
Symbol id_;
|
||||
|
||||
template<typename SIG, typename MEM>
|
||||
struct UndoDefinition
|
||||
{
|
||||
typedef typename FunctionSignature< function<SIG> >::Args BasicArgs;
|
||||
typedef typename FunctionTypedef<MEM,BasicArgs>::Sig UndoCaptureSig;
|
||||
|
||||
UndoDefinition (function<UndoCaptureSig>& undoCapOperation)
|
||||
{
|
||||
cout << showSizeof(undoCapOperation) << endl;
|
||||
UNIMPLEMENTED ("re-fetch command definition and augment it with Functor for capturing Undo information");
|
||||
}
|
||||
|
||||
template<typename SIG2>
|
||||
UndoDefinition&
|
||||
undoOperation (SIG2& how_to_Undo)
|
||||
{
|
||||
typedef typename UndoSignature<SIG2>::UndoOp_Sig UndoSig;
|
||||
|
||||
function<UndoSig> opera3 (how_to_Undo);
|
||||
|
||||
UNIMPLEMENTED ("store actual Undo-Functor into the command definition held by the enclosing UndoDefinition instance");
|
||||
return *this;
|
||||
}
|
||||
|
||||
template
|
||||
< typename T1
|
||||
, typename T2
|
||||
>
|
||||
UndoDefinition& ///////TODO return here the completed Command
|
||||
bind ( T1& p1
|
||||
, T2& p2
|
||||
)
|
||||
{
|
||||
typedef Types<T1,T2> ArgTypes;
|
||||
Tuple<ArgTypes> params(p1,p2);
|
||||
Closure<SIG> clo (params);
|
||||
|
||||
cout << showSizeof(clo) << endl;
|
||||
UNIMPLEMENTED ("complete Command definition by closing all functions");
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** type re-binding helper: create a suitable UndoDefinition type,
|
||||
* based on the UndoSignature template instance given as parameter */
|
||||
template<typename U_SIG>
|
||||
struct BuildUndoDefType
|
||||
{
|
||||
typedef UndoDefinition<typename U_SIG::OperateSig, typename U_SIG::Memento> Type;
|
||||
};
|
||||
|
||||
template<typename SIG>
|
||||
struct BasicDefinition
|
||||
{
|
||||
BasicDefinition(function<SIG>& operation)
|
||||
{
|
||||
cout << showSizeof(operation) << endl;
|
||||
UNIMPLEMENTED ("create new command object an store the operation functor");
|
||||
}
|
||||
|
||||
|
||||
template<typename SIG2>
|
||||
typename BuildUndoDefType<UndoSignature<SIG2> >::Type
|
||||
captureUndo (SIG2& how_to_capture_UndoState)
|
||||
{
|
||||
typedef typename UndoSignature<SIG2>::CaptureSig UndoCapSig;
|
||||
typedef typename BuildUndoDefType<UndoSignature<SIG2> >::Type SpecificUndoDefinition;
|
||||
|
||||
function<UndoCapSig> opera2 (how_to_capture_UndoState);
|
||||
return SpecificUndoDefinition (opera2);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
CommDef (Symbol cmdID)
|
||||
: id_(cmdID)
|
||||
{ }
|
||||
|
||||
template<typename SIG>
|
||||
BasicDefinition<SIG>
|
||||
operation (SIG& operation_to_define)
|
||||
{
|
||||
function<SIG> opera1 (operation_to_define);
|
||||
return BasicDefinition<SIG>(opera1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
@ -372,16 +134,16 @@ namespace test {
|
|||
;
|
||||
|
||||
|
||||
Command ourCmd = Command::get("test.command1");
|
||||
Command& ourCmd = Command::get("test.command1");
|
||||
|
||||
// invoke the command
|
||||
ASSERT (obj == Time(5));
|
||||
ASSERT (*obj == Time(5));
|
||||
ourCmd();
|
||||
ASSERT (obj == Time(5) + Time(randVal));
|
||||
ASSERT (*obj == Time(5) + Time(randVal));
|
||||
|
||||
// undo the effect of the command
|
||||
ourCmd.undo();
|
||||
ASSERT (obj == Time(5));
|
||||
ASSERT (*obj == Time(5));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,19 +33,20 @@
|
|||
//#include "proc/mobject/placement-index.hpp"
|
||||
//#include "proc/mobject/explicitplacement.hpp"
|
||||
#include "proc/control/command-mutation.hpp"
|
||||
#include "lib/meta/typelist.hpp"
|
||||
#include "lib/meta/tuple.hpp"
|
||||
//#include "lib/lumitime.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
//#include <tr1/functional>
|
||||
#include <tr1/functional>
|
||||
//#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
//using std::tr1::bind;
|
||||
using std::tr1::bind;
|
||||
//using std::tr1::placeholders::_1;
|
||||
//using std::tr1::placeholders::_2;
|
||||
//using std::tr1::function;
|
||||
using std::tr1::function;
|
||||
//using boost::format;
|
||||
//using lumiera::Time;
|
||||
//using util::contains;
|
||||
|
|
@ -61,8 +62,10 @@ namespace test {
|
|||
|
||||
// using session::test::TestClip;
|
||||
// using lumiera::P;
|
||||
using namespace lumiera::typelist;
|
||||
using lumiera::typelist::Tuple;
|
||||
using control::CommandClosure;
|
||||
|
||||
using control::CmdClosure;
|
||||
|
||||
|
||||
|
||||
|
|
@ -70,22 +73,19 @@ namespace test {
|
|||
|
||||
|
||||
namespace {
|
||||
|
||||
int testVal; ///< used to verify the effect of testFunc
|
||||
|
||||
void
|
||||
operate (P<Time> dummyObj, int randVal)
|
||||
testFunc (int val)
|
||||
{
|
||||
*dummyObj += Time(randVal);
|
||||
testVal += val;
|
||||
}
|
||||
|
||||
Time
|
||||
capture (P<Time> dummyObj, int)
|
||||
int
|
||||
capture ()
|
||||
{
|
||||
return *dummyObj;
|
||||
}
|
||||
|
||||
void
|
||||
undoIt (P<Time> dummyObj, int, Time oldVal)
|
||||
{
|
||||
*dummyObj = oldVal;
|
||||
return testVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -122,14 +122,14 @@ namespace test {
|
|||
void
|
||||
checkMutation ()
|
||||
{
|
||||
function<void(int)> funky (bind (&testFunc));
|
||||
function<void(int)> funky = bind (testFunc, _1);
|
||||
|
||||
Mutation functor (funky);
|
||||
ASSERT (!functor);
|
||||
VERIFY_ERROR (UNBOUND_ARGUMENTS, functor() );
|
||||
|
||||
Tuple<int> param = tuple::make(23);
|
||||
Closure close_over (param);
|
||||
Tuple<Types<int> > param = tuple::make(23);
|
||||
Closure<void(int)> close_over (param);
|
||||
|
||||
CmdClosure& clo (close_over);
|
||||
functor.close(clo);
|
||||
|
|
@ -156,15 +156,15 @@ namespace test {
|
|||
void
|
||||
checkUndoMutation ()
|
||||
{
|
||||
function<void(int)> undo_func (bind (&testFunc));
|
||||
function<int(void)> cap_func (bind (&capture));
|
||||
function<void(int)> undo_func = bind (&testFunc,_1);
|
||||
function<int(void)> cap_func = bind (&capture );
|
||||
|
||||
UndoMutation undoFunctor (undo_func,cap_func);
|
||||
ASSERT (!undoFunctor);
|
||||
VERIFY_ERROR (UNBOUND_ARGUMENTS, undoFunctor() );
|
||||
|
||||
Tuple<> param;
|
||||
Closure clo (param);
|
||||
Tuple<Types<> > param;
|
||||
Closure<void()> clo (param);
|
||||
|
||||
undoFunctor.close(clo);
|
||||
ASSERT (!undoFunctor);
|
||||
|
|
|
|||
Loading…
Reference in a new issue