/* COMMAND-SIGNATURE.hpp - deriving suitable command function signatures 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 command-signature.hpp ** Metaprogramming helpers for deriving the precise function signatures ** necessary to implement a given command. Basically, commands can be implemented ** by arbitrary functions, but the signatures of the operation function, the ** undo function and the undo state capturing function are required to obey ** fixed relationships. Thus, at various stages of the command definition, ** we need to accept functor objects with a very specific and predetermined ** signature, thus allowing for strict type checking by the compiler. ** ** \par Relation of function signatures (MEM = type of the "memento" for Undo) ** - operation: void(P1,..PN) ** - captureUndo: MEM(P1,..PN) ** - undoOperation void(P1,..PN,MEM) ** - bind takes the arguments:(P1,..PN) ** ** @see Command ** @see CommandDef ** */ #ifndef CONTROL_COMMAND_SIGNATURE_H #define CONTROL_COMMAND_SIGNATURE_H #include "lib/meta/function.hpp" #include "lib/meta/typelist.hpp" #include "lib/meta/typelist-manip.hpp" #include "lib/meta/typeseq-util.hpp" #include namespace proc { namespace control { using std::tr1::function; using lumiera::typelist::FunctionSignature; using lumiera::typelist::FunctionTypedef; using lumiera::typelist::Types; using lumiera::typelist::Append; using lumiera::typelist::SplitLast; /** * Metaprogramming helper for building Command function signatures. * The complete definition context of any command is templated to the signature * of the actual command operation and to the memento type. The typedefs embedded * within CommandSignature allows for accepting suitable typed functions * to implement the command in question. */ template class CommandSignature { typedef typename FunctionSignature< function >::Args Args; typedef typename Args::List ArgList; typedef typename Append::List ExtendedArglist; typedef typename Types::Seq ExtendedArgs; public: typedef typename FunctionTypedef::Sig OperateSig; typedef typename FunctionTypedef::Sig CaptureSig; typedef typename FunctionTypedef::Sig UndoOp_Sig; typedef Args CmdArgs; typedef MEM Memento; }; /** * 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. * * To use this template, it is instantiated with the signature of a functor object * in question. Depending on the actual situation, the compiler will then either * pick Case1 or Case2 -- thus allowing the client in any case to pick up the * correct signatures for Operation, Capture and Undo-function from the * public typedefs within \c UndoSignature */ template class UndoSignature { // preparation: dissect the function signature into arguments and result typedef typename FunctionSignature< function >::Args Args; typedef typename FunctionSignature< function >::Ret Ret; /** Case1: defining the Undo-Capture function */ template struct Case { typedef RET Memento; typedef typename Append::List ExtendedArglist; typedef typename Types::Seq ExtendedArgs; typedef typename FunctionTypedef::Sig OperateSig; typedef typename FunctionTypedef::Sig CaptureSig; typedef typename FunctionTypedef::Sig UndoOp_Sig; }; /** Case2: defining the actual Undo function */ template struct Case { typedef typename ARG::List Args; typedef typename SplitLast::Type Memento; typedef typename SplitLast::List OperationArglist; typedef typename Types::Seq OperationArgs; typedef typename FunctionTypedef::Sig OperateSig; typedef typename FunctionTypedef::Sig CaptureSig; typedef typename FunctionTypedef::Sig UndoOp_Sig; }; public: typedef typename Case::CaptureSig CaptureSig; typedef typename Case::UndoOp_Sig UndoOp_Sig; typedef typename Case::OperateSig OperateSig; typedef typename Case::Memento Memento; }; }} // namespace proc::control #endif