/* COMMAND-INVOCATION.hpp - shortcuts and helpers for calling Proc-Layer commands 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-invocation.hpp ** Some additional helpers and convenience shortcuts to ease command invocation. ** Especially, this header defines a set of free \c invoke(...) functions, ** allowing to bind to specific arguments and then invoke through the default ** HandlingPatern in a single call. ** ** While in some cases, a command will be set up completely finished and closed ** over all it's arguments, usually the CommandDef will just specify the command operation ** and undo function, thus leaving the task of binding concrete arguments to the client code. ** Thus, depending on the circumstances, there might be usage situations where the exact number ** and type of arguments can be detected and checked at compile time, while otherwise this check ** needs to be deferred to happen at runtime, when the binding is actually invoked. ** ** @see Command ** @see CommandDef ** @see command-binding.hpp ** @see command-use1-test.cpp ** */ #ifndef CONTROL_COMMAND_INVOCACTION_H #define CONTROL_COMMAND_INVOCACTION_H //#include "pre.hpp" #include "proc/control/command.hpp" #include "proc/control/handling-pattern.hpp" #include "proc/control/argument-tuple-accept.hpp" namespace control { using namespace lumiera::typelist; namespace com { ///< Proc-Layer command implementation details // define transient invoker objects, to allow for arbitrary bindings template struct _DefineBindFunc { typedef ExecResult SIG_Bind(int); }; /** @internal transient invoker object for invoking the command based * on a function provided at compile time. Because of the * known signature, we're able to expose a precisely typed * function invocation operator. */ template struct CommandInvoker : AcceptArgumentTuple< typename _DefineBindFunc::SIG_Bind , CommandInvoker > { Command com_; CommandInvoker (Command c) : com_(c) { } template ExecResult bindArg (Tuple const& args) { com_.bindArg(args); ASSERT (com_.canExec()); return com_(); } }; /** @internal transient invoker object, usable when the exact signature * of the command's operation isn't known at compile time. * In this case, we allow any invocation call to compile, * but the command will reject unsuitable signatures * at runtime, when fetching the operation functor. */ struct RuntimeCheckedCommandInvoker { Command com_; RuntimeCheckedCommandInvoker (Command c) : com_(c) { } template< typename T1> ExecResult //_________________________________ operator() (T1 a1) ///< Invoke command with 1 Argument. { com_.bind(a1); return com_(); } template< typename T1 , typename T2 > ExecResult //_________________________________ operator() (T1 a1, T2 a2) ///< Invoke command with 2 Arguments { com_.bind(a1,a2); return com_(); } template< typename T1 , typename T2 , typename T3 > ExecResult //_________________________________ operator() (T1 a1, T2 a2, T3 a3) ///< Invoke command with 3 Arguments { com_.bind(a1,a2,a3); return com_(); } template< typename T1 , typename T2 , typename T3 , typename T4 > ExecResult //_________________________________ operator() (T1 a1, T2 a2, T3 a3, T4 a4) ///< Invoke command with 4 Arguments { com_.bind(a1,a2,a3,a4); return com_(); } template< typename T1 , typename T2 , typename T3 , typename T4 , typename T5 > ExecResult //_________________________________ operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) ///< Invoke command with 5 Arguments { com_.bind(a1,a2,a3,a4,a5); return com_(); } template< typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 > ExecResult //_________________________________ operator() (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) ///< Invoke command with 6 Arguments { com_.bind(a1,a2,a3,a4,a5,a6); return com_(); } }; } template inline com::CommandInvoker invoke (SIG& operation_func) { Command command = Command::get ((FuncPtr)&operation_func); ASSERT (command); return com::CommandInvoker (command); } inline com::RuntimeCheckedCommandInvoker invoke (Symbol cmdID) { Command command = Command::get (cmdID); ASSERT (command); return com::RuntimeCheckedCommandInvoker (command); } inline com::RuntimeCheckedCommandInvoker invoke (const char* cmdID) { return invoke(Symbol(cmdID)); } } // namespace control #endif