/* TUPLE.hpp - metaprogramming utilities for type tuples and data tuples 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 tuple.hpp ** Metaprogramming with tuples-of-types and a very simple Tuple datatype. ** The metaprogramming part of this header complements typelist.hpp and allows ** to re-build a new tuple-of-types from an existing typelist. Such a finite ** tuple of types can at times be more handy than a typelist, especially when ** capturing specific types to use as template parameter. ** ** Additionally, this header augments the Tuple template into a very simple Tuple ** (run time) datatype. This isn't meant as competing with std::tr1::tuple, which is ** much more capable, but also has the downside of pulling in a lot of other headers. ** But when all we need is to define a generic typed record of N data elements and ** later re-accessing them (but no further advanced processing), the Tuple template ** might come in handy. ** ** @see control::CommandDef usage example ** @see typelist.hpp ** @see function.hpp ** @see generator.hpp ** */ #ifndef LUMIERA_META_TUPLE_H #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 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) */ 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; }; }} // namespace lumiera::typelist #endif