diff --git a/src/lib/meta/function-closure.hpp b/src/lib/meta/function-closure.hpp index f85d3953d..499728d24 100644 --- a/src/lib/meta/function-closure.hpp +++ b/src/lib/meta/function-closure.hpp @@ -40,6 +40,7 @@ #include "lib/meta/typelist.hpp" /////////////TODO #include "lib/meta/generator.hpp" /////////////TODO #include "lib/meta/function.hpp" +#include "lib/meta/tuple.hpp" #include @@ -52,386 +53,287 @@ namespace typelist{ //using std::tr1::placeholders::_1; //using std::tr1::placeholders::_2; using std::tr1::function; - - - template< typename SIG> - struct FunctionSignature; - - template< typename RET> - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types<> Args; - }; - - template< typename RET - , typename A1 - > - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types Args; - }; - - template< typename RET - , typename A1 - , typename A2 - > - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types Args; - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - > - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types Args; - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - , typename A4 - > - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types Args; - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - , typename A4 - , typename A5 - > - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types Args; - }; - - - template - struct FunctionTypedef; - - template< typename RET> - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(); - }; - - template< typename RET - , typename A1 - > - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(A1); - }; - - template< typename RET - , typename A1 - , typename A2 - > - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(A1,A2); - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - > - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(A1,A2,A3); - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - , typename A4 - > - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(A1,A2,A3,A4); - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - , typename A4 - , typename A5 - > - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(A1,A2,A3,A4,A5); - }; - /////////////////////////very basic facility: Typed tuples + namespace func { // helpers for binding and applying a function to an argument tuple + + using tuple::element; + + /** + * this Helper with repetitive specialisations for up to nine arguments + * is used either to apply a function to arguments given as a tuple, or + * to create the actual closure (functor) over all function arguments. + */ + template + struct Apply; + + + template<> //_________________________________ + struct Apply<1> ///< Apply function with 1 Argument + { + template + static RET + invoke (FUN f, TUP & arg) + { + return f (element<1>(arg)); + } + + template + static RET + bind (FUN f, TUP & arg) + { + return std::tr1::bind (f, element<1>(arg)); + } + }; + + + template<> //_________________________________ + struct Apply<2> ///< Apply function with 2 Arguments + { + template + static RET + invoke (FUN f, TUP & arg) + { + return f ( element<1>(arg) + , element<2>(arg) + ); + } + + template + static RET + bind (FUN f, TUP & arg) + { + return std::tr1::bind (f, element<1>(arg) + , element<2>(arg) + ); + } + }; + + + template<> //_________________________________ + struct Apply<3> ///< Apply function with 3 Arguments + { + template + static RET + invoke (FUN f, TUP & arg) + { + return f ( element<1>(arg) + , element<2>(arg) + , element<3>(arg) + ); + } + + template + static RET + bind (FUN f, TUP & arg) + { + return std::tr1::bind (f, element<1>(arg) + , element<2>(arg) + , element<3>(arg) + ); + } + }; + + + template<> //_________________________________ + struct Apply<4> ///< Apply function with 4 Arguments + { + template + static RET + invoke (FUN f, TUP & arg) + { + return f ( element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + ); + } + + template + static RET + bind (FUN f, TUP & arg) + { + return std::tr1::bind (f, element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + ); + } + }; + + + template<> //_________________________________ + struct Apply<5> ///< Apply function with 5 Arguments + { + template + static RET + invoke (FUN f, TUP & arg) + { + return f ( element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + , element<5>(arg) + ); + } + + template + static RET + bind (FUN f, TUP & arg) + { + return std::tr1::bind (f, element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + , element<5>(arg) + ); + } + }; + + + template<> //_________________________________ + struct Apply<6> ///< Apply function with 6 Arguments + { + template + static RET + invoke (FUN f, TUP & arg) + { + return f ( element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + , element<5>(arg) + , element<6>(arg) + ); + } + + template + static RET + bind (FUN f, TUP & arg) + { + return std::tr1::bind (f, element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + , element<5>(arg) + , element<6>(arg) + ); + } + }; + + + template<> //_________________________________ + struct Apply<7> ///< Apply function with 7 Arguments + { + template + static RET + invoke (FUN f, TUP & arg) + { + return f ( element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + , element<5>(arg) + , element<6>(arg) + , element<7>(arg) + ); + } + + template + static RET + bind (FUN f, TUP & arg) + { + return std::tr1::bind (f, element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + , element<5>(arg) + , element<6>(arg) + , element<7>(arg) + ); + } + }; + + + template<> //_________________________________ + struct Apply<8> ///< Apply function with 8 Arguments + { + template + static RET + invoke (FUN f, TUP & arg) + { + return f ( element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + , element<5>(arg) + , element<6>(arg) + , element<7>(arg) + , element<8>(arg) + ); + } + + template + static RET + bind (FUN f, TUP & arg) + { + return std::tr1::bind (f, element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + , element<5>(arg) + , element<6>(arg) + , element<7>(arg) + , element<8>(arg) + ); + } + }; + + + template<> //_________________________________ + struct Apply<9> ///< Apply function with 9 Arguments + { + template + static RET + invoke (FUN f, TUP & arg) + { + return f ( element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + , element<5>(arg) + , element<6>(arg) + , element<7>(arg) + , element<8>(arg) + , element<9>(arg) + ); + } + + template + static RET + bind (FUN f, TUP & arg) + { + return std::tr1::bind (f, element<1>(arg) + , element<2>(arg) + , element<3>(arg) + , element<4>(arg) + , element<5>(arg) + , element<6>(arg) + , element<7>(arg) + , element<8>(arg) + , element<9>(arg) + ); + } + }; + + } // (END) impl-namespace (func) - template - struct Prepend; - - template< typename A1 - , typename A2 - , typename A3 - , typename A4 - , typename A5 - , typename IGN - > - struct Prepend > - { - typedef Types Tuple; - }; - - template - struct Tuple; - - template<> - struct Tuple - { - typedef NullType HeadType; - typedef Types<> TailType; - typedef Types<> Type; - - typedef NullType ArgList_; - typedef Tuple ThisTuple; - typedef Tuple Tail; - enum { SIZE = 0 }; - - NullType getHead() { return NullType(); } - Tail& getTail() { return *this; } - - Tuple (HeadType const&, Tail const&) { } - Tuple () { } - }; - - template - struct Tuple > - : Tuple - { - typedef TY HeadType; - typedef typename Tuple::Type TailType; - typedef typename Prepend::Tuple Type; - - typedef Node ArgList_; - typedef Tuple ThisTuple; - typedef Tuple Tail; - enum { SIZE = count::value }; - - Tuple ( TY a1 =TY() - , Tail tail =Tail() - ) - : Tuple (tail.getHead(), tail.getTail()), - val_(a1) - { } - - TY & getHead() { return val_; } - Tail& getTail() { return static_cast (*this); } - - private: - TY val_; - }; - - ////TODO move in sub-scope - template - struct Shifted - { - typedef typename TUP::Tail Tail; - typedef typename Shifted::TupleType TupleType; - }; - template - struct Shifted - { - typedef Tuple TupleType; - }; - - - template< typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 - > - struct Tuple > - : Tuple::List> - { - typedef T1 HeadType; - typedef Types TailType; - typedef Types Type; - - typedef typename Type::List ArgList_; - typedef Tuple ThisTuple; - typedef Tuple Tail; - enum { SIZE = count::value }; - - Tuple ( T1 a1 =T1() - , T2 a2 =T2() - , T3 a3 =T3() - , T4 a4 =T4() - , T5 a5 =T5() - ) - : Tuple(a1, Tuple(a2,a3,a4,a5)) - { } - - using Tuple::getHead; - using Tuple::getTail; - - template - typename Shifted::TupleType& - getShifted () - { - typedef typename Shifted::TupleType Tail_I; - return static_cast (*this); - } - - template - typename Shifted::TupleType::HeadType& - getAt () - { - return getShifted().getHead(); - } - - NullType& - getNull() - { - static NullType nix; - return nix; - } - }; /** - * Decorating a tuple type with auxiliary data access operations. - * This helper template builds up a subclass of the given BASE type - * (which is assumed to be a Tuple or at least need to be copy constructible - * from \c Tuple ). The purpose is to use the Tuple as storage, but - * to add a layer of access functions, which in turn might rely on the exact - * type of the individual elements within the Tuple. To achieve this, for each - * type within the Tuple, the BASE type is decorated with an instance of the - * template passed in as template template parameter _X_. Each of these - * decorating instances is provided with a member pointer to access "his" - * specific element within the underlying tuple. - * - * The decorating template _X_ need to take its own base class as template - * parameter. Typically, operations on _X_ will be defined in a recursive fashion, - * calling down into this templated base class. To support this, an instantiation - * of _X_ with the 0 member ptr is generated for detecting recursion end - * (built as innermost decorator, i.e. immediate subclass of BASE) + * Closure-creating template. */ - template - < typename TYPES - , template class _X_ - , class BASE =Tuple - , uint i = 0 - > - class BuildTupleAccessor - { - typedef Tuple ArgTuple; - typedef typename ArgTuple::HeadType Head; - typedef typename ArgTuple::TailType Tail; -// typedef Head ArgTuple::*getElm(); - typedef BuildTupleAccessor NextBuilder; - typedef typename NextBuilder::Accessor NextAccessor; - - ArgTuple& argData_; - - public: - - /** type of the product created by this template. - * Will be a subclass of BASE */ - typedef _X_ Accessor; - - BuildTupleAccessor (ArgTuple& tup) - : argData_(tup) - { } - - operator Accessor() { return Accessor(argData_); } - - }; - - template - < class BASE - , template class _X_ - , uint i - > - class BuildTupleAccessor, _X_, BASE, i> - { - typedef Tuple > ArgTuple; -// typedef NullType BASE::*getElm(); - - public: - typedef _X_ Accessor; - }; - - - ///////////////////////// creating functional closures - - namespace tuple { - template - struct Apply; - - template<> - struct Apply<1> - { - template - static RET - invoke (FUN f, TUP & arg) - { - return f (arg.template getAt<1>()); - } - - template - static RET - bind (FUN f, TUP & arg) - { - return std::tr1::bind (f, arg.template getAt<1>()); - } - }; - - template<> - struct Apply<2> - { - template - static RET - invoke (FUN f, TUP & arg) - { - return f ( arg.template getAt<1>() - , arg.template getAt<2>() - ); - } - - template - static RET - bind (FUN f, TUP & arg) - { - return std::tr1::bind (f, arg.template getAt<1>() - , arg.template getAt<2>() - ); - } - }; - } // (END) sub-namespace - template class TupleApplicator { @@ -449,11 +351,11 @@ namespace typelist{ : params_(args) { } - function bind (SIG& f) { return tuple::Apply::bind (f, params_); } - function bind (function const& f) { return tuple::Apply::bind (f, params_); } + function bind (SIG& f) { return func::Apply::bind (f, params_); } + function bind (function const& f) { return func::Apply::bind (f, params_); } - Ret operator() (SIG& f) { return tuple::Apply::invoke (f, params_); } - Ret operator() (function const& f) { return tuple::Apply::invoke (f, params_); } + Ret operator() (SIG& f) { return func::Apply::invoke (f, params_); } + Ret operator() (function const& f) { return func::Apply::invoke (f, params_); } }; @@ -484,41 +386,6 @@ namespace typelist{ }; -/* - template - struct BuildClosure - : InstantiateWithIndex - { - - }; -*/ - - ///////////////////////// additional typelist manipulators - - template - struct SplitLast; - - template<> - struct SplitLast - { - typedef NullType Type; - typedef NullType Prefix; - }; - - template - struct SplitLast > - { - typedef TY Type; - typedef NullType Prefix; - }; - - template - struct SplitLast > - { - typedef typename SplitLast::Type Type; - typedef typename Append::Prefix>::List Prefix; - }; - }} // namespace lumiera::typelist diff --git a/src/lib/meta/function.hpp b/src/lib/meta/function.hpp index 9cdb8e89d..57faab310 100644 --- a/src/lib/meta/function.hpp +++ b/src/lib/meta/function.hpp @@ -37,6 +37,7 @@ ** and rest assured: you aren't alone. ** ** @see control::CommandDef usage example + ** @see function-closure.hpp generic function application ** @see typelist.hpp ** @see tuple.hpp ** @@ -47,8 +48,6 @@ #define LUMIERA_META_FUNCTION_H #include "lib/meta/typelist.hpp" -#include "lib/meta/generator.hpp" -#include "lib/meta/typelistutil.hpp" #include @@ -57,15 +56,23 @@ namespace lumiera { namespace typelist{ - using std::tr1::bind; - //using std::tr1::placeholders::_1; - //using std::tr1::placeholders::_2; using std::tr1::function; - - + + + + + /** + * Extract the type information contained in a + * function or functor type, so it can be manipulated + * by metaprogramming. Up to 9 function arguments are + * supported and can be extracted as a type sequence. + * The bare function signature serving as input can be + * obtained by capturing a function reference or pointer. + */ template< typename SIG> struct FunctionSignature; + template< typename RET> struct FunctionSignature< function > { @@ -73,6 +80,7 @@ namespace typelist{ typedef Types<> Args; }; + template< typename RET , typename A1 > @@ -82,6 +90,7 @@ namespace typelist{ typedef Types Args; }; + template< typename RET , typename A1 , typename A2 @@ -92,6 +101,7 @@ namespace typelist{ typedef Types Args; }; + template< typename RET , typename A1 , typename A2 @@ -103,6 +113,7 @@ namespace typelist{ typedef Types Args; }; + template< typename RET , typename A1 , typename A2 @@ -115,6 +126,7 @@ namespace typelist{ typedef Types Args; }; + template< typename RET , typename A1 , typename A2 @@ -129,9 +141,85 @@ namespace typelist{ }; - template + template< typename RET + , typename A1 + , typename A2 + , typename A3 + , typename A4 + , typename A5 + , typename A6 + > + struct FunctionSignature< function > + { + typedef RET Ret; + typedef Types Args; + }; + + + template< typename RET + , typename A1 + , typename A2 + , typename A3 + , typename A4 + , typename A5 + , typename A6 + , typename A7 + > + struct FunctionSignature< function > + { + typedef RET Ret; + typedef Types Args; + }; + + + template< typename RET + , typename A1 + , typename A2 + , typename A3 + , typename A4 + , typename A5 + , typename A6 + , typename A7 + , typename A8 + > + struct FunctionSignature< function > + { + typedef RET Ret; + typedef Types Args; + }; + + + template< typename RET + , typename A1 + , typename A2 + , typename A3 + , typename A4 + , typename A5 + , typename A6 + , typename A7 + , typename A8 + , typename A9 + > + struct FunctionSignature< function > + { + typedef RET Ret; + typedef Types Args; + }; + + + + + /** + * Build function types from given Argument types. + * As embedded typedefs, you'll find a tr1 functor #Func + * and the bare function signature #Sig + * @param RET the function return type + * @param ARGS a type sequence describing the arguments + */ + template struct FunctionTypedef; + template< typename RET> struct FunctionTypedef > { @@ -139,6 +227,7 @@ namespace typelist{ typedef RET Sig(); }; + template< typename RET , typename A1 > @@ -148,6 +237,7 @@ namespace typelist{ typedef RET Sig(A1); }; + template< typename RET , typename A1 , typename A2 @@ -158,6 +248,7 @@ namespace typelist{ typedef RET Sig(A1,A2); }; + template< typename RET , typename A1 , typename A2 @@ -169,6 +260,7 @@ namespace typelist{ typedef RET Sig(A1,A2,A3); }; + template< typename RET , typename A1 , typename A2 @@ -181,6 +273,7 @@ namespace typelist{ typedef RET Sig(A1,A2,A3,A4); }; + template< typename RET , typename A1 , typename A2 @@ -195,340 +288,74 @@ namespace typelist{ }; - - /////////////////////////very basic facility: Typed tuples - - template - struct Prepend; - - template< typename A1 + template< typename RET + , typename A1 , typename A2 , typename A3 , typename A4 , typename A5 - , typename IGN + , typename A6 > - struct Prepend > + struct FunctionTypedef > { - typedef Types Tuple; + typedef function Func; + typedef RET Sig(A1,A2,A3,A4,A5,A6); }; - - template - struct Tuple; - - template<> - struct Tuple - { - typedef NullType HeadType; - typedef Types<> TailType; - typedef Types<> Type; - - typedef NullType ArgList_; - typedef Tuple ThisTuple; - typedef Tuple Tail; - enum { SIZE = 0 }; - - NullType getHead() { return NullType(); } - Tail& getTail() { return *this; } - - Tuple (HeadType const&, Tail const&) { } - Tuple () { } - }; - template - struct Tuple > - : Tuple - { - typedef TY HeadType; - typedef typename Tuple::Type TailType; - typedef typename Prepend::Tuple Type; - - typedef Node ArgList_; - typedef Tuple ThisTuple; - typedef Tuple Tail; - enum { SIZE = count::value }; - - Tuple ( TY a1 =TY() - , Tail tail =Tail() - ) - : Tuple (tail.getHead(), tail.getTail()), - val_(a1) - { } - - TY & getHead() { return val_; } - Tail& getTail() { return static_cast (*this); } - - private: - TY val_; - }; - ////TODO move in sub-scope - template - struct Shifted - { - typedef typename TUP::Tail Tail; - typedef typename Shifted::TupleType TupleType; - }; - template - struct Shifted - { - typedef Tuple TupleType; - }; - - - template< typename T1 - , typename T2 - , typename T3 - , typename T4 - , typename T5 + template< typename RET + , typename A1 + , typename A2 + , typename A3 + , typename A4 + , typename A5 + , typename A6 + , typename A7 > - struct Tuple > - : Tuple::List> - { - typedef T1 HeadType; - typedef Types TailType; - typedef Types Type; - - typedef typename Type::List ArgList_; - typedef Tuple ThisTuple; - typedef Tuple Tail; - enum { SIZE = count::value }; - - Tuple ( T1 a1 =T1() - , T2 a2 =T2() - , T3 a3 =T3() - , T4 a4 =T4() - , T5 a5 =T5() - ) - : Tuple(a1, Tuple(a2,a3,a4,a5)) - { } - - using Tuple::getHead; - using Tuple::getTail; - - template - typename Shifted::TupleType& - getShifted () - { - typedef typename Shifted::TupleType Tail_I; - return static_cast (*this); - } - - template - typename Shifted::TupleType::HeadType& - getAt () - { - return getShifted().getHead(); - } - - NullType& - getNull() - { - static NullType nix; - return nix; - } - }; + struct FunctionTypedef > + { + typedef function Func; + typedef RET Sig(A1,A2,A3,A4,A5,A6,A7); + }; - /** - * Decorating a tuple type with auxiliary data access operations. - * This helper template builds up a subclass of the given BASE type - * (which is assumed to be a Tuple or at least need to be copy constructible - * from \c Tuple ). The purpose is to use the Tuple as storage, but - * to add a layer of access functions, which in turn might rely on the exact - * type of the individual elements within the Tuple. To achieve this, for each - * type within the Tuple, the BASE type is decorated with an instance of the - * template passed in as template template parameter _X_. Each of these - * decorating instances is provided with a member pointer to access "his" - * specific element within the underlying tuple. - * - * The decorating template _X_ need to take its own base class as template - * parameter. Typically, operations on _X_ will be defined in a recursive fashion, - * calling down into this templated base class. To support this, an instantiation - * of _X_ with the 0 member ptr is generated for detecting recursion end - * (built as innermost decorator, i.e. immediate subclass of BASE) - */ - template - < typename TYPES - , template class _X_ - , class BASE =Tuple - , uint i = 0 - > - class BuildTupleAccessor - { - typedef Tuple ArgTuple; - typedef typename ArgTuple::HeadType Head; - typedef typename ArgTuple::TailType Tail; -// typedef Head ArgTuple::*getElm(); - typedef BuildTupleAccessor NextBuilder; - typedef typename NextBuilder::Accessor NextAccessor; - - ArgTuple& argData_; - - public: - - /** type of the product created by this template. - * Will be a subclass of BASE */ - typedef _X_ Accessor; - - BuildTupleAccessor (ArgTuple& tup) - : argData_(tup) - { } - - operator Accessor() { return Accessor(argData_); } - - }; - - template - < class BASE - , template class _X_ - , uint i - > - class BuildTupleAccessor, _X_, BASE, i> - { - typedef Tuple > ArgTuple; -// typedef NullType BASE::*getElm(); - - public: - typedef _X_ Accessor; - }; + template< typename RET + , typename A1 + , typename A2 + , typename A3 + , typename A4 + , typename A5 + , typename A6 + , typename A7 + , typename A8 + > + struct FunctionTypedef > + { + typedef function Func; + typedef RET Sig(A1,A2,A3,A4,A5,A6,A7,A8); + }; - ///////////////////////// creating functional closures - - namespace tuple { - template - struct Apply; - - template<> - struct Apply<1> - { - template - static RET - invoke (FUN f, TUP & arg) - { - return f (arg.template getAt<1>()); - } - - template - static RET - bind (FUN f, TUP & arg) - { - return std::tr1::bind (f, arg.template getAt<1>()); - } - }; - - template<> - struct Apply<2> - { - template - static RET - invoke (FUN f, TUP & arg) - { - return f ( arg.template getAt<1>() - , arg.template getAt<2>() - ); - } - - template - static RET - bind (FUN f, TUP & arg) - { - return std::tr1::bind (f, arg.template getAt<1>() - , arg.template getAt<2>() - ); - } - }; - } // (END) sub-namespace - - template - class TupleApplicator - { - typedef typename FunctionSignature< function >::Args Args; - typedef typename FunctionSignature< function >::Ret Ret; - - enum { ARG_CNT = count::value }; - - - /** storing a ref to the parameter tuple */ - Tuple& params_; - - public: - TupleApplicator (Tuple& args) - : params_(args) - { } - - function bind (SIG& f) { return tuple::Apply::bind (f, params_); } - function bind (function const& f) { return tuple::Apply::bind (f, params_); } - - Ret operator() (SIG& f) { return tuple::Apply::invoke (f, params_); } - Ret operator() (function const& f) { return tuple::Apply::invoke (f, params_); } - }; + template< typename RET + , typename A1 + , typename A2 + , typename A3 + , typename A4 + , typename A5 + , typename A6 + , typename A7 + , typename A8 + , typename A9 + > + struct FunctionTypedef > + { + typedef function Func; + typedef RET Sig(A1,A2,A3,A4,A5,A6,A7,A8,A9); + }; - /** - * Closing a function over its arguments. - * This is a small usage example or spin-off, - * having almost the same effect than invoking tr1::bind. - * The notable difference is that the function arguments for - * creating the closure are passed in as one compound tuple. - */ - template - class FunctionClosure - { - typedef typename FunctionSignature< function >::Args Args; - typedef typename FunctionSignature< function >::Ret Ret; - - function closure_; - - public: - FunctionClosure (SIG& f, Tuple& arg) - : closure_(TupleApplicator(arg).bind(f)) - { } - FunctionClosure (function const& f, Tuple& arg) - : closure_(TupleApplicator(arg).bind(f)) - { } - - Ret operator() () { return closure_(); } - }; -/* - template - struct BuildClosure - : InstantiateWithIndex - { - - }; -*/ - - ///////////////////////// additional typelist manipulators - - template - struct SplitLast; - - template<> - struct SplitLast - { - typedef NullType Type; - typedef NullType Prefix; - }; - - template - struct SplitLast > - { - typedef TY Type; - typedef NullType Prefix; - }; - - template - struct SplitLast > - { - typedef typename SplitLast::Type Type; - typedef typename Append::Prefix>::List Prefix; - }; - - }} // namespace lumiera::typelist #endif diff --git a/src/lib/meta/tuple.hpp b/src/lib/meta/tuple.hpp index 2db8a6673..19eb272fd 100644 --- a/src/lib/meta/tuple.hpp +++ b/src/lib/meta/tuple.hpp @@ -47,175 +47,140 @@ #define LUMIERA_META_TUPLE_H #include "lib/meta/typelist.hpp" -#include "lib/meta/generator.hpp" #include "lib/meta/typelistutil.hpp" -#include - namespace lumiera { namespace typelist{ - using std::tr1::bind; - //using std::tr1::placeholders::_1; - //using std::tr1::placeholders::_2; - using std::tr1::function; - - template< typename SIG> - struct FunctionSignature; - - template< typename RET> - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types<> Args; - }; - - template< typename RET - , typename A1 - > - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types Args; - }; - - template< typename RET - , typename A1 - , typename A2 - > - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types Args; - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - > - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types Args; - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - , typename A4 - > - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types Args; - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - , typename A4 - , typename A5 - > - struct FunctionSignature< function > - { - typedef RET Ret; - typedef Types Args; - }; - - - template - struct FunctionTypedef; - - template< typename RET> - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(); - }; - - template< typename RET - , typename A1 - > - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(A1); - }; - - template< typename RET - , typename A1 - , typename A2 - > - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(A1,A2); - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - > - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(A1,A2,A3); - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - , typename A4 - > - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(A1,A2,A3,A4); - }; - - template< typename RET - , typename A1 - , typename A2 - , typename A3 - , typename A4 - , typename A5 - > - struct FunctionTypedef > - { - typedef function Func; - typedef RET Sig(A1,A2,A3,A4,A5); - }; - - - - /////////////////////////very basic facility: Typed tuples + /** + * Helper: prepend a type to an existing type sequence, + * thus shifting all elements within the sequence + * to the right, eventually dropping the last element + */ template struct Prepend; - template< typename A1 - , typename A2 - , typename A3 - , typename A4 - , typename A5 + template< typename T01 + , typename T02 + , typename T03 + , typename T04 + , typename T05 + , typename T06 + , typename T07 + , typename T08 + , typename T09 + , typename T10 + , typename T11 + , typename T12 + , typename T13 + , typename T14 + , typename T15 + , typename T16 + , typename T17 + , typename T18 + , typename T19 + , typename T20 , typename IGN > - struct Prepend > + struct Prepend > { - typedef Types Tuple; + typedef Types< T01,T02,T03,T04,T05 + , T06,T07,T08,T09,T10 + , T11,T12,T13,T14,T15 + , T16,T17,T18,T19,T20 > Tuple; }; + + + + + /** Helper: separate parts of a type sequence */ + template + struct Split; + + template< typename T01 + , typename T02 + , typename T03 + , typename T04 + , typename T05 + , typename T06 + , typename T07 + , typename T08 + , typename T09 + , typename T10 + , typename T11 + , typename T12 + , typename T13 + , typename T14 + , typename T15 + , typename T16 + , typename T17 + , typename T18 + , typename T19 + , typename T20 + > + struct Split > + { + typedef T01 Head; + typedef Types< T01 > First; + typedef Types< T01,T02,T03,T04,T05 + , T06,T07,T08,T09,T10 + , T11,T12,T13,T14,T15 + , T16,T17,T18,T19 > Prefix; + typedef Types< T02,T03,T04,T05 + , T06,T07,T08,T09,T10 + , T11,T12,T13,T14,T15 + , T16,T17,T18,T19,T20 > Tail; + typedef Types< T20 > Last; + typedef T20 End; + }; + + + + + /** + * Helper: generate a type sequence left shifted + * by i steps, filling in NullType at the end + */ + template + class Shifted + { + typedef typename Split::Tail Tail; + public: + typedef typename Shifted::Types Types; + typedef typename Split::Head Head; + }; + + template + struct Shifted + { + typedef TYPES Types; + typedef typename Types::List::Head Head; + }; + + /** + * simple generic Tuple datatype. + * Usable both for metaprogramming and as a generic record. + * The types within this tuple can either be specified + * as Type sequence or as typelist + */ template struct Tuple; - + + template<> struct Tuple { @@ -223,10 +188,10 @@ namespace typelist{ typedef Types<> TailType; typedef Types<> Type; - typedef NullType ArgList_; - typedef Tuple ThisTuple; + typedef NullType ArgList; + typedef Tuple ThisTuple; typedef Tuple Tail; - enum { SIZE = 0 }; + enum { SIZE = 0 }; NullType getHead() { return NullType(); } Tail& getTail() { return *this; } @@ -235,6 +200,7 @@ namespace typelist{ Tuple () { } }; + template struct Tuple > : Tuple @@ -243,12 +209,12 @@ namespace typelist{ typedef typename Tuple::Type TailType; typedef typename Prepend::Tuple Type; - typedef Node ArgList_; - typedef Tuple ThisTuple; - typedef Tuple Tail; - enum { SIZE = count::value }; + typedef Node ArgList; + typedef Tuple ThisTuple; + typedef Tuple Tail; + enum { SIZE = count::value }; - Tuple ( TY a1 =TY() + Tuple ( TY a1 =TY() , Tail tail =Tail() ) : Tuple (tail.getHead(), tail.getTail()), @@ -262,74 +228,189 @@ namespace typelist{ TY val_; }; - ////TODO move in sub-scope - template - struct Shifted - { - typedef typename TUP::Tail Tail; - typedef typename Shifted::TupleType TupleType; - }; - template - struct Shifted - { - typedef Tuple TupleType; - }; - template< typename T1 , typename T2 , typename T3 , typename T4 , typename T5 + , typename T6 + , typename T7 + , typename T8 + , typename T9 > - struct Tuple > - : Tuple::List> + struct Tuple > + : Tuple::List> { - typedef T1 HeadType; - typedef Types TailType; - typedef Types Type; + typedef T1 HeadType; + typedef Types TailType; + typedef Types Type; - typedef typename Type::List ArgList_; - typedef Tuple ThisTuple; - typedef Tuple Tail; - enum { SIZE = count::value }; + typedef typename Type::List ArgList; + typedef Tuple ThisTuple; + typedef Tuple Tail; + enum { SIZE = count::value }; Tuple ( T1 a1 =T1() , T2 a2 =T2() , T3 a3 =T3() , T4 a4 =T4() , T5 a5 =T5() + , T6 a6 =T6() + , T7 a7 =T7() + , T8 a8 =T8() + , T9 a9 =T9() ) - : Tuple(a1, Tuple(a2,a3,a4,a5)) + : Tuple(a1, Tuple(a2,a3,a4,a5,a6,a7,a8,a9)) { } - using Tuple::getHead; - using Tuple::getTail; + using Tuple::getHead; + using Tuple::getTail; template - typename Shifted::TupleType& + class ShiftedTuple + { + typedef typename Tuple::Type OurType_; + typedef typename Shifted::Types ShiftedTypes_; + public: + typedef Tuple Type; + }; + + template + typename ShiftedTuple::Type& getShifted () { - typedef typename Shifted::TupleType Tail_I; + typedef typename ShiftedTuple::Type Tail_I; return static_cast (*this); } template - typename Shifted::TupleType::HeadType& + typename Shifted::Head& getAt () { return getShifted().getHead(); } - - NullType& - getNull() - { - static NullType nix; - return nix; - } }; + + namespace tuple { // some convenience access functions + + template + typename TUP::template ShiftedTuple::Type::Head& + element (TUP& tup) + { + return tup.template getAt(); + } + + + + Tuple > + makeNullTuple () + { + return Tuple > (); + } + + + template< typename T1 + > + Tuple > + make ( T1 a1 =T1() + ) + { + return Tuple > (a1); + } + + + template< typename T1 + , typename T2 + > + Tuple > + make ( T1 a1 =T1() + , T2 a2 =T2() + ) + { + return Tuple > (a1,a2); + } + + + template< typename T1 + , typename T2 + , typename T3 + > + Tuple > + make ( T1 a1 =T1() + , T2 a2 =T2() + , T3 a3 =T3() + ) + { + return Tuple > (a1,a2,a3); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + > + Tuple > + make ( T1 a1 =T1() + , T2 a2 =T2() + , T3 a3 =T3() + , T4 a4 =T4() + ) + { + return Tuple > (a1,a2,a3,a4); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + > + Tuple > + make ( T1 a1 =T1() + , T2 a2 =T2() + , T3 a3 =T3() + , T4 a4 =T4() + , T5 a5 =T5() + ) + { + return Tuple > (a1,a2,a3,a4,a5); + } + + + template< typename T1 + , typename T2 + , typename T3 + , typename T4 + , typename T5 + , typename T6 + , typename T7 + , typename T8 + , typename T9 + > + Tuple > + make ( T1 a1 =T1() + , T2 a2 =T2() + , T3 a3 =T3() + , T4 a4 =T4() + , T5 a5 =T5() + , T6 a6 =T6() + , T7 a7 =T7() + , T8 a8 =T8() + , T9 a9 =T9() + ) + { + return Tuple > (a1,a2,a3,a4,a5,a6,a7,a8,a9); + } + + } + + + /** * Decorating a tuple type with auxiliary data access operations. * This helper template builds up a subclass of the given BASE type @@ -349,18 +430,17 @@ namespace typelist{ * (built as innermost decorator, i.e. immediate subclass of BASE) */ template - < typename TYPES - , template class _X_ - , class BASE =Tuple - , uint i = 0 + < typename TYPES ///< Type sequence to use within the Accessor (usually the Tuple Types) + , template class _X_ ///< user provided template + , class TUP =Tuple ///< the tuple type to build on + , uint i = 0 ///< tuple element index counter > class BuildTupleAccessor { typedef Tuple ArgTuple; typedef typename ArgTuple::HeadType Head; typedef typename ArgTuple::TailType Tail; -// typedef Head ArgTuple::*getElm(); - typedef BuildTupleAccessor NextBuilder; + typedef BuildTupleAccessor NextBuilder; typedef typename NextBuilder::Accessor NextAccessor; ArgTuple& argData_; @@ -368,29 +448,35 @@ namespace typelist{ public: /** type of the product created by this template. - * Will be a subclass of BASE */ - typedef _X_ Accessor; + * Will be a subclass of TUP */ + typedef _X_< Head // the type to use for this accessor + , NextAccessor // the base type to inherit from + , TUP // the tuple type we build upon + , i // current element index + > Accessor; + BuildTupleAccessor (ArgTuple& tup) : argData_(tup) { } + /** used to get the product of this builder template... */ operator Accessor() { return Accessor(argData_); } }; - + + template - < class BASE - , template class _X_ + < template class _X_ + , class TUP , uint i > - class BuildTupleAccessor, _X_, BASE, i> + class BuildTupleAccessor, _X_, TUP, i> { typedef Tuple > ArgTuple; -// typedef NullType BASE::*getElm(); public: - typedef _X_ Accessor; + typedef _X_ Accessor; }; diff --git a/src/lib/meta/typelistutil.hpp b/src/lib/meta/typelistutil.hpp index ebc39dc3f..1b89b26bc 100644 --- a/src/lib/meta/typelistutil.hpp +++ b/src/lib/meta/typelistutil.hpp @@ -29,7 +29,7 @@ #include "lib/meta/typelist.hpp" namespace lumiera { - namespace typelist { +namespace typelist { /** @@ -131,6 +131,27 @@ namespace lumiera { + + /** access the last list element */ + template + struct SplitLast; + + template<> + struct SplitLast { typedef NullType Type; + typedef NullType List; }; + template + struct SplitLast > { typedef TY Type; + typedef NullType List; }; + + template + struct SplitLast > { typedef typename SplitLast::Type Type; + typedef typename Append< TY, + typename SplitLast::List + >::List + List; }; + + + /** * prefix each of the elements, * yielding a list-of lists-of-types @@ -207,7 +228,5 @@ namespace lumiera { - } // namespace typelist - -} // namespace lumiera +}} // namespace lumiera::typelist #endif diff --git a/tests/components/proc/control/command-basic-test.cpp b/tests/components/proc/control/command-basic-test.cpp index 7d74708a6..915aa59ff 100644 --- a/tests/components/proc/control/command-basic-test.cpp +++ b/tests/components/proc/control/command-basic-test.cpp @@ -40,6 +40,9 @@ #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 //#include @@ -111,7 +114,7 @@ namespace test { typedef typename ARG::List Args; typedef typename SplitLast::Type Memento; - typedef typename SplitLast::Prefix OperationArglist; + typedef typename SplitLast::List OperationArglist; typedef typename Tuple::Type OperationArgs; typedef typename FunctionTypedef::Sig OperateSig; @@ -138,33 +141,42 @@ namespace test { }; - template + template + < typename TY + , class BASE + , class TUP + , uint idx + > struct ParamAccessor : BASE { - template ParamAccessor(TUP& tuple) : BASE(tuple) { cout << showSizeof(tuple.template getAt()) << endl; } + + ////////////////////TODO the real access operations (e.g. for serialising) go here }; - template - struct ParamAccessor - : BASE + + template + struct ParamAccessor + : TUP { - template ParamAccessor(TUP& tuple) - : BASE(tuple) + : TUP(tuple) { } + + ////////////////////TODO the recursion-end of the access operations goes here }; + + template class Closure : public CmdClosure { typedef typename FunctionSignature< function >::Args Args; -// typedef typename FunctionSignature< function >::Ret Ret; typedef Tuple ArgTuple;