finish and tidy the extracted headers
This commit is contained in:
parent
9d04f48c51
commit
d1b425aba9
5 changed files with 766 additions and 955 deletions
|
|
@ -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 <tr1/functional>
|
||||
|
||||
|
|
@ -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<RET(void)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<> Args;
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1> Args;
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2> Args;
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2,A3)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2,A3> Args;
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2,A3,A4)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2,A3,A4> Args;
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
, typename A5
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2,A3,A4,A5)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2,A3,A4,A5> Args;
|
||||
};
|
||||
|
||||
|
||||
template<typename RET, typename LI>
|
||||
struct FunctionTypedef;
|
||||
|
||||
template< typename RET>
|
||||
struct FunctionTypedef<RET, Types<> >
|
||||
{
|
||||
typedef function<RET(void)> Func;
|
||||
typedef RET Sig();
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1> >
|
||||
{
|
||||
typedef function<RET(A1)> Func;
|
||||
typedef RET Sig(A1);
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2> >
|
||||
{
|
||||
typedef function<RET(A1,A2)> Func;
|
||||
typedef RET Sig(A1,A2);
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3> >
|
||||
{
|
||||
typedef function<RET(A1,A2,A3)> Func;
|
||||
typedef RET Sig(A1,A2,A3);
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4> >
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4)> Func;
|
||||
typedef RET Sig(A1,A2,A3,A4);
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
, typename A5
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5> >
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4,A5)> 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<uint n>
|
||||
struct Apply;
|
||||
|
||||
|
||||
template<> //_________________________________
|
||||
struct Apply<1> ///< Apply function with 1 Argument
|
||||
{
|
||||
template<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
invoke (FUN f, TUP & arg)
|
||||
{
|
||||
return f (element<1>(arg));
|
||||
}
|
||||
|
||||
template<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
invoke (FUN f, TUP & arg)
|
||||
{
|
||||
return f ( element<1>(arg)
|
||||
, element<2>(arg)
|
||||
);
|
||||
}
|
||||
|
||||
template<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
invoke (FUN f, TUP & arg)
|
||||
{
|
||||
return f ( element<1>(arg)
|
||||
, element<2>(arg)
|
||||
, element<3>(arg)
|
||||
);
|
||||
}
|
||||
|
||||
template<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
invoke (FUN f, TUP & arg)
|
||||
{
|
||||
return f ( element<1>(arg)
|
||||
, element<2>(arg)
|
||||
, element<3>(arg)
|
||||
, element<4>(arg)
|
||||
);
|
||||
}
|
||||
|
||||
template<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
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<class FUN, typename RET, class TUP>
|
||||
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<class T, class TYPES>
|
||||
struct Prepend;
|
||||
|
||||
template< typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
, typename A5
|
||||
, typename IGN
|
||||
>
|
||||
struct Prepend<A1, Types<A2,A3,A4,A5,IGN> >
|
||||
{
|
||||
typedef Types<A1,A2,A3,A4,A5> Tuple;
|
||||
};
|
||||
|
||||
template<class TYPES>
|
||||
struct Tuple;
|
||||
|
||||
template<>
|
||||
struct Tuple<NullType>
|
||||
{
|
||||
typedef NullType HeadType;
|
||||
typedef Types<> TailType;
|
||||
typedef Types<> Type;
|
||||
|
||||
typedef NullType ArgList_;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<NullType> Tail;
|
||||
enum { SIZE = 0 };
|
||||
|
||||
NullType getHead() { return NullType(); }
|
||||
Tail& getTail() { return *this; }
|
||||
|
||||
Tuple (HeadType const&, Tail const&) { }
|
||||
Tuple () { }
|
||||
};
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct Tuple<Node<TY,TYPES> >
|
||||
: Tuple<TYPES>
|
||||
{
|
||||
typedef TY HeadType;
|
||||
typedef typename Tuple<TYPES>::Type TailType;
|
||||
typedef typename Prepend<TY,TailType>::Tuple Type;
|
||||
|
||||
typedef Node<TY,TYPES> ArgList_;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<TYPES> Tail;
|
||||
enum { SIZE = count<ArgList_>::value };
|
||||
|
||||
Tuple ( TY a1 =TY()
|
||||
, Tail tail =Tail()
|
||||
)
|
||||
: Tuple<TYPES> (tail.getHead(), tail.getTail()),
|
||||
val_(a1)
|
||||
{ }
|
||||
|
||||
TY & getHead() { return val_; }
|
||||
Tail& getTail() { return static_cast<Tail&> (*this); }
|
||||
|
||||
private:
|
||||
TY val_;
|
||||
};
|
||||
|
||||
////TODO move in sub-scope
|
||||
template<class TUP,uint i>
|
||||
struct Shifted
|
||||
{
|
||||
typedef typename TUP::Tail Tail;
|
||||
typedef typename Shifted<Tail,i-1>::TupleType TupleType;
|
||||
};
|
||||
template<class TUP>
|
||||
struct Shifted<TUP,0>
|
||||
{
|
||||
typedef Tuple<typename TUP::ArgList_> TupleType;
|
||||
};
|
||||
|
||||
|
||||
template< typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
, typename T4
|
||||
, typename T5
|
||||
>
|
||||
struct Tuple<Types<T1,T2,T3,T4,T5> >
|
||||
: Tuple<typename Types<T1,T2,T3,T4,T5>::List>
|
||||
{
|
||||
typedef T1 HeadType;
|
||||
typedef Types<T2,T3,T4,T5,NullType> TailType;
|
||||
typedef Types<T1,T2,T3,T4,T5> Type;
|
||||
|
||||
typedef typename Type::List ArgList_;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<TailType> Tail;
|
||||
enum { SIZE = count<ArgList_>::value };
|
||||
|
||||
Tuple ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
, T3 a3 =T3()
|
||||
, T4 a4 =T4()
|
||||
, T5 a5 =T5()
|
||||
)
|
||||
: Tuple<ArgList_>(a1, Tuple<TailType>(a2,a3,a4,a5))
|
||||
{ }
|
||||
|
||||
using Tuple<ArgList_>::getHead;
|
||||
using Tuple<ArgList_>::getTail;
|
||||
|
||||
template<uint i>
|
||||
typename Shifted<ThisTuple,i>::TupleType&
|
||||
getShifted ()
|
||||
{
|
||||
typedef typename Shifted<ThisTuple,i>::TupleType Tail_I;
|
||||
return static_cast<Tail_I&> (*this);
|
||||
}
|
||||
|
||||
template<uint i>
|
||||
typename Shifted<ThisTuple,i>::TupleType::HeadType&
|
||||
getAt ()
|
||||
{
|
||||
return getShifted<i>().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<TYPES> ). 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,class,uint> class _X_
|
||||
, class BASE =Tuple<TYPES>
|
||||
, uint i = 0
|
||||
>
|
||||
class BuildTupleAccessor
|
||||
{
|
||||
typedef Tuple<TYPES> ArgTuple;
|
||||
typedef typename ArgTuple::HeadType Head;
|
||||
typedef typename ArgTuple::TailType Tail;
|
||||
// typedef Head ArgTuple::*getElm();
|
||||
typedef BuildTupleAccessor<Tail,_X_,BASE, i+1> 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_<Head, NextAccessor, i> Accessor;
|
||||
|
||||
BuildTupleAccessor (ArgTuple& tup)
|
||||
: argData_(tup)
|
||||
{ }
|
||||
|
||||
operator Accessor() { return Accessor(argData_); }
|
||||
|
||||
};
|
||||
|
||||
template
|
||||
< class BASE
|
||||
, template<class,class,uint> class _X_
|
||||
, uint i
|
||||
>
|
||||
class BuildTupleAccessor<Types<>, _X_, BASE, i>
|
||||
{
|
||||
typedef Tuple<Types<> > ArgTuple;
|
||||
// typedef NullType BASE::*getElm();
|
||||
|
||||
public:
|
||||
typedef _X_<NullType, BASE, 0> Accessor;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////// creating functional closures
|
||||
|
||||
namespace tuple {
|
||||
template<uint n>
|
||||
struct Apply;
|
||||
|
||||
template<>
|
||||
struct Apply<1>
|
||||
{
|
||||
template<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
invoke (FUN f, TUP & arg)
|
||||
{
|
||||
return f (arg.template getAt<1>());
|
||||
}
|
||||
|
||||
template<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
bind (FUN f, TUP & arg)
|
||||
{
|
||||
return std::tr1::bind (f, arg.template getAt<1>());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Apply<2>
|
||||
{
|
||||
template<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
invoke (FUN f, TUP & arg)
|
||||
{
|
||||
return f ( arg.template getAt<1>()
|
||||
, arg.template getAt<2>()
|
||||
);
|
||||
}
|
||||
|
||||
template<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
bind (FUN f, TUP & arg)
|
||||
{
|
||||
return std::tr1::bind (f, arg.template getAt<1>()
|
||||
, arg.template getAt<2>()
|
||||
);
|
||||
}
|
||||
};
|
||||
} // (END) sub-namespace
|
||||
|
||||
template<typename SIG>
|
||||
class TupleApplicator
|
||||
{
|
||||
|
|
@ -449,11 +351,11 @@ namespace typelist{
|
|||
: params_(args)
|
||||
{ }
|
||||
|
||||
function<SIG> bind (SIG& f) { return tuple::Apply<ARG_CNT>::bind (f, params_); }
|
||||
function<SIG> bind (function<SIG> const& f) { return tuple::Apply<ARG_CNT>::bind (f, params_); }
|
||||
function<SIG> bind (SIG& f) { return func::Apply<ARG_CNT>::bind (f, params_); }
|
||||
function<SIG> bind (function<SIG> const& f) { return func::Apply<ARG_CNT>::bind (f, params_); }
|
||||
|
||||
Ret operator() (SIG& f) { return tuple::Apply<ARG_CNT>::invoke (f, params_); }
|
||||
Ret operator() (function<SIG> const& f) { return tuple::Apply<ARG_CNT>::invoke (f, params_); }
|
||||
Ret operator() (SIG& f) { return func::Apply<ARG_CNT>::invoke (f, params_); }
|
||||
Ret operator() (function<SIG> const& f) { return func::Apply<ARG_CNT>::invoke (f, params_); }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -484,41 +386,6 @@ namespace typelist{
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
template<typename TYPES>
|
||||
struct BuildClosure
|
||||
: InstantiateWithIndex<TYPES, Accessor, I>
|
||||
{
|
||||
|
||||
};
|
||||
*/
|
||||
|
||||
///////////////////////// additional typelist manipulators
|
||||
|
||||
template<class TYPES>
|
||||
struct SplitLast;
|
||||
|
||||
template<>
|
||||
struct SplitLast<NullType>
|
||||
{
|
||||
typedef NullType Type;
|
||||
typedef NullType Prefix;
|
||||
};
|
||||
|
||||
template<class TY>
|
||||
struct SplitLast<Node<TY,NullType> >
|
||||
{
|
||||
typedef TY Type;
|
||||
typedef NullType Prefix;
|
||||
};
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct SplitLast<Node<TY,TYPES> >
|
||||
{
|
||||
typedef typename SplitLast<TYPES>::Type Type;
|
||||
typedef typename Append<TY, typename SplitLast<TYPES>::Prefix>::List Prefix;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}} // namespace lumiera::typelist
|
||||
|
|
|
|||
|
|
@ -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 <tr1/functional>
|
||||
|
||||
|
|
@ -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<RET(void)> >
|
||||
{
|
||||
|
|
@ -73,6 +80,7 @@ namespace typelist{
|
|||
typedef Types<> Args;
|
||||
};
|
||||
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
>
|
||||
|
|
@ -82,6 +90,7 @@ namespace typelist{
|
|||
typedef Types<A1> Args;
|
||||
};
|
||||
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
|
|
@ -92,6 +101,7 @@ namespace typelist{
|
|||
typedef Types<A1,A2> Args;
|
||||
};
|
||||
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
|
|
@ -103,6 +113,7 @@ namespace typelist{
|
|||
typedef Types<A1,A2,A3> Args;
|
||||
};
|
||||
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
|
|
@ -115,6 +126,7 @@ namespace typelist{
|
|||
typedef Types<A1,A2,A3,A4> Args;
|
||||
};
|
||||
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
|
|
@ -129,9 +141,85 @@ namespace typelist{
|
|||
};
|
||||
|
||||
|
||||
template<typename RET, typename LI>
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
, typename A5
|
||||
, typename A6
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2,A3,A4,A5,A6)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2,A3,A4,A5,A6> Args;
|
||||
};
|
||||
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
, typename A5
|
||||
, typename A6
|
||||
, typename A7
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2,A3,A4,A5,A6,A7)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2,A3,A4,A5,A6,A7> Args;
|
||||
};
|
||||
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
, typename A5
|
||||
, typename A6
|
||||
, typename A7
|
||||
, typename A8
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2,A3,A4,A5,A6,A7,A8)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2,A3,A4,A5,A6,A7,A8> 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<RET(A1,A2,A3,A4,A5,A6,A7,A8,A9)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2,A3,A4,A5,A6,A7,A8,A9> 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<typename RET, typename ARGS>
|
||||
struct FunctionTypedef;
|
||||
|
||||
|
||||
template< typename RET>
|
||||
struct FunctionTypedef<RET, Types<> >
|
||||
{
|
||||
|
|
@ -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<class T, class TYPES>
|
||||
struct Prepend;
|
||||
|
||||
template< typename A1
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
, typename A5
|
||||
, typename IGN
|
||||
, typename A6
|
||||
>
|
||||
struct Prepend<A1, Types<A2,A3,A4,A5,IGN> >
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6> >
|
||||
{
|
||||
typedef Types<A1,A2,A3,A4,A5> Tuple;
|
||||
typedef function<RET(A1,A2,A3,A4,A5,A6)> Func;
|
||||
typedef RET Sig(A1,A2,A3,A4,A5,A6);
|
||||
};
|
||||
|
||||
template<class TYPES>
|
||||
struct Tuple;
|
||||
|
||||
template<>
|
||||
struct Tuple<NullType>
|
||||
{
|
||||
typedef NullType HeadType;
|
||||
typedef Types<> TailType;
|
||||
typedef Types<> Type;
|
||||
|
||||
typedef NullType ArgList_;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<NullType> Tail;
|
||||
enum { SIZE = 0 };
|
||||
|
||||
NullType getHead() { return NullType(); }
|
||||
Tail& getTail() { return *this; }
|
||||
|
||||
Tuple (HeadType const&, Tail const&) { }
|
||||
Tuple () { }
|
||||
};
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct Tuple<Node<TY,TYPES> >
|
||||
: Tuple<TYPES>
|
||||
{
|
||||
typedef TY HeadType;
|
||||
typedef typename Tuple<TYPES>::Type TailType;
|
||||
typedef typename Prepend<TY,TailType>::Tuple Type;
|
||||
|
||||
typedef Node<TY,TYPES> ArgList_;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<TYPES> Tail;
|
||||
enum { SIZE = count<ArgList_>::value };
|
||||
|
||||
Tuple ( TY a1 =TY()
|
||||
, Tail tail =Tail()
|
||||
)
|
||||
: Tuple<TYPES> (tail.getHead(), tail.getTail()),
|
||||
val_(a1)
|
||||
{ }
|
||||
|
||||
TY & getHead() { return val_; }
|
||||
Tail& getTail() { return static_cast<Tail&> (*this); }
|
||||
|
||||
private:
|
||||
TY val_;
|
||||
};
|
||||
|
||||
////TODO move in sub-scope
|
||||
template<class TUP,uint i>
|
||||
struct Shifted
|
||||
{
|
||||
typedef typename TUP::Tail Tail;
|
||||
typedef typename Shifted<Tail,i-1>::TupleType TupleType;
|
||||
};
|
||||
template<class TUP>
|
||||
struct Shifted<TUP,0>
|
||||
{
|
||||
typedef Tuple<typename TUP::ArgList_> 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<Types<T1,T2,T3,T4,T5> >
|
||||
: Tuple<typename Types<T1,T2,T3,T4,T5>::List>
|
||||
{
|
||||
typedef T1 HeadType;
|
||||
typedef Types<T2,T3,T4,T5,NullType> TailType;
|
||||
typedef Types<T1,T2,T3,T4,T5> Type;
|
||||
|
||||
typedef typename Type::List ArgList_;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<TailType> Tail;
|
||||
enum { SIZE = count<ArgList_>::value };
|
||||
|
||||
Tuple ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
, T3 a3 =T3()
|
||||
, T4 a4 =T4()
|
||||
, T5 a5 =T5()
|
||||
)
|
||||
: Tuple<ArgList_>(a1, Tuple<TailType>(a2,a3,a4,a5))
|
||||
{ }
|
||||
|
||||
using Tuple<ArgList_>::getHead;
|
||||
using Tuple<ArgList_>::getTail;
|
||||
|
||||
template<uint i>
|
||||
typename Shifted<ThisTuple,i>::TupleType&
|
||||
getShifted ()
|
||||
{
|
||||
typedef typename Shifted<ThisTuple,i>::TupleType Tail_I;
|
||||
return static_cast<Tail_I&> (*this);
|
||||
}
|
||||
|
||||
template<uint i>
|
||||
typename Shifted<ThisTuple,i>::TupleType::HeadType&
|
||||
getAt ()
|
||||
{
|
||||
return getShifted<i>().getHead();
|
||||
}
|
||||
|
||||
NullType&
|
||||
getNull()
|
||||
{
|
||||
static NullType nix;
|
||||
return nix;
|
||||
}
|
||||
};
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6,A7> >
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4,A5,A6,A7)> 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<TYPES> ). 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,class,uint> class _X_
|
||||
, class BASE =Tuple<TYPES>
|
||||
, uint i = 0
|
||||
>
|
||||
class BuildTupleAccessor
|
||||
{
|
||||
typedef Tuple<TYPES> ArgTuple;
|
||||
typedef typename ArgTuple::HeadType Head;
|
||||
typedef typename ArgTuple::TailType Tail;
|
||||
// typedef Head ArgTuple::*getElm();
|
||||
typedef BuildTupleAccessor<Tail,_X_,BASE, i+1> 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_<Head, NextAccessor, i> Accessor;
|
||||
|
||||
BuildTupleAccessor (ArgTuple& tup)
|
||||
: argData_(tup)
|
||||
{ }
|
||||
|
||||
operator Accessor() { return Accessor(argData_); }
|
||||
|
||||
};
|
||||
|
||||
template
|
||||
< class BASE
|
||||
, template<class,class,uint> class _X_
|
||||
, uint i
|
||||
>
|
||||
class BuildTupleAccessor<Types<>, _X_, BASE, i>
|
||||
{
|
||||
typedef Tuple<Types<> > ArgTuple;
|
||||
// typedef NullType BASE::*getElm();
|
||||
|
||||
public:
|
||||
typedef _X_<NullType, BASE, 0> Accessor;
|
||||
};
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
, typename A5
|
||||
, typename A6
|
||||
, typename A7
|
||||
, typename A8
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8> >
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4,A5,A6,A7,A8)> Func;
|
||||
typedef RET Sig(A1,A2,A3,A4,A5,A6,A7,A8);
|
||||
};
|
||||
|
||||
|
||||
///////////////////////// creating functional closures
|
||||
|
||||
namespace tuple {
|
||||
template<uint n>
|
||||
struct Apply;
|
||||
|
||||
template<>
|
||||
struct Apply<1>
|
||||
{
|
||||
template<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
invoke (FUN f, TUP & arg)
|
||||
{
|
||||
return f (arg.template getAt<1>());
|
||||
}
|
||||
|
||||
template<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
bind (FUN f, TUP & arg)
|
||||
{
|
||||
return std::tr1::bind (f, arg.template getAt<1>());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Apply<2>
|
||||
{
|
||||
template<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
invoke (FUN f, TUP & arg)
|
||||
{
|
||||
return f ( arg.template getAt<1>()
|
||||
, arg.template getAt<2>()
|
||||
);
|
||||
}
|
||||
|
||||
template<class FUN, typename RET, class TUP>
|
||||
static RET
|
||||
bind (FUN f, TUP & arg)
|
||||
{
|
||||
return std::tr1::bind (f, arg.template getAt<1>()
|
||||
, arg.template getAt<2>()
|
||||
);
|
||||
}
|
||||
};
|
||||
} // (END) sub-namespace
|
||||
|
||||
template<typename SIG>
|
||||
class TupleApplicator
|
||||
{
|
||||
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
||||
typedef typename FunctionSignature< function<SIG> >::Ret Ret;
|
||||
|
||||
enum { ARG_CNT = count<typename Args::List>::value };
|
||||
|
||||
|
||||
/** storing a ref to the parameter tuple */
|
||||
Tuple<Args>& params_;
|
||||
|
||||
public:
|
||||
TupleApplicator (Tuple<Args>& args)
|
||||
: params_(args)
|
||||
{ }
|
||||
|
||||
function<SIG> bind (SIG& f) { return tuple::Apply<ARG_CNT>::bind (f, params_); }
|
||||
function<SIG> bind (function<SIG> const& f) { return tuple::Apply<ARG_CNT>::bind (f, params_); }
|
||||
|
||||
Ret operator() (SIG& f) { return tuple::Apply<ARG_CNT>::invoke (f, params_); }
|
||||
Ret operator() (function<SIG> const& f) { return tuple::Apply<ARG_CNT>::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<RET, Types<A1,A2,A3,A4,A5,A6,A7,A8,A9> >
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4,A5,A6,A7,A8,A9)> 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<typename SIG>
|
||||
class FunctionClosure
|
||||
{
|
||||
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
||||
typedef typename FunctionSignature< function<SIG> >::Ret Ret;
|
||||
|
||||
function<Ret(void)> closure_;
|
||||
|
||||
public:
|
||||
FunctionClosure (SIG& f, Tuple<Args>& arg)
|
||||
: closure_(TupleApplicator<SIG>(arg).bind(f))
|
||||
{ }
|
||||
FunctionClosure (function<SIG> const& f, Tuple<Args>& arg)
|
||||
: closure_(TupleApplicator<SIG>(arg).bind(f))
|
||||
{ }
|
||||
|
||||
Ret operator() () { return closure_(); }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
template<typename TYPES>
|
||||
struct BuildClosure
|
||||
: InstantiateWithIndex<TYPES, Accessor, I>
|
||||
{
|
||||
|
||||
};
|
||||
*/
|
||||
|
||||
///////////////////////// additional typelist manipulators
|
||||
|
||||
template<class TYPES>
|
||||
struct SplitLast;
|
||||
|
||||
template<>
|
||||
struct SplitLast<NullType>
|
||||
{
|
||||
typedef NullType Type;
|
||||
typedef NullType Prefix;
|
||||
};
|
||||
|
||||
template<class TY>
|
||||
struct SplitLast<Node<TY,NullType> >
|
||||
{
|
||||
typedef TY Type;
|
||||
typedef NullType Prefix;
|
||||
};
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct SplitLast<Node<TY,TYPES> >
|
||||
{
|
||||
typedef typename SplitLast<TYPES>::Type Type;
|
||||
typedef typename Append<TY, typename SplitLast<TYPES>::Prefix>::List Prefix;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}} // namespace lumiera::typelist
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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 <tr1/functional>
|
||||
|
||||
|
||||
|
||||
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<RET(void)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<> Args;
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1> Args;
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2> Args;
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2,A3)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2,A3> Args;
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2,A3,A4)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2,A3,A4> Args;
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
, typename A5
|
||||
>
|
||||
struct FunctionSignature< function<RET(A1,A2,A3,A4,A5)> >
|
||||
{
|
||||
typedef RET Ret;
|
||||
typedef Types<A1,A2,A3,A4,A5> Args;
|
||||
};
|
||||
|
||||
|
||||
template<typename RET, typename LI>
|
||||
struct FunctionTypedef;
|
||||
|
||||
template< typename RET>
|
||||
struct FunctionTypedef<RET, Types<> >
|
||||
{
|
||||
typedef function<RET(void)> Func;
|
||||
typedef RET Sig();
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1> >
|
||||
{
|
||||
typedef function<RET(A1)> Func;
|
||||
typedef RET Sig(A1);
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2> >
|
||||
{
|
||||
typedef function<RET(A1,A2)> Func;
|
||||
typedef RET Sig(A1,A2);
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3> >
|
||||
{
|
||||
typedef function<RET(A1,A2,A3)> Func;
|
||||
typedef RET Sig(A1,A2,A3);
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4> >
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4)> Func;
|
||||
typedef RET Sig(A1,A2,A3,A4);
|
||||
};
|
||||
|
||||
template< typename RET
|
||||
, typename A1
|
||||
, typename A2
|
||||
, typename A3
|
||||
, typename A4
|
||||
, typename A5
|
||||
>
|
||||
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5> >
|
||||
{
|
||||
typedef function<RET(A1,A2,A3,A4,A5)> 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<class T, class TYPES>
|
||||
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<A1, Types<A2,A3,A4,A5,IGN> >
|
||||
struct Prepend<T01, Types< T02,T03,T04,T05
|
||||
, T06,T07,T08,T09,T10
|
||||
, T11,T12,T13,T14,T15
|
||||
, T16,T17,T18,T19,T20
|
||||
, IGN
|
||||
> >
|
||||
{
|
||||
typedef Types<A1,A2,A3,A4,A5> 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<class TYPES>
|
||||
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<Types< T01,T02,T03,T04,T05
|
||||
, T06,T07,T08,T09,T10
|
||||
, T11,T12,T13,T14,T15
|
||||
, T16,T17,T18,T19,T20
|
||||
> >
|
||||
{
|
||||
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 TYPES, uint i=1>
|
||||
class Shifted
|
||||
{
|
||||
typedef typename Split<TYPES>::Tail Tail;
|
||||
public:
|
||||
typedef typename Shifted<Tail,i-1>::Types Types;
|
||||
typedef typename Split<Types>::Head Head;
|
||||
};
|
||||
|
||||
template<class TYPES>
|
||||
struct Shifted<TYPES,0>
|
||||
{
|
||||
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<class TYPES>
|
||||
struct Tuple;
|
||||
|
||||
|
||||
|
||||
template<>
|
||||
struct Tuple<NullType>
|
||||
{
|
||||
|
|
@ -223,10 +188,10 @@ namespace typelist{
|
|||
typedef Types<> TailType;
|
||||
typedef Types<> Type;
|
||||
|
||||
typedef NullType ArgList_;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef NullType ArgList;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<NullType> Tail;
|
||||
enum { SIZE = 0 };
|
||||
enum { SIZE = 0 };
|
||||
|
||||
NullType getHead() { return NullType(); }
|
||||
Tail& getTail() { return *this; }
|
||||
|
|
@ -235,6 +200,7 @@ namespace typelist{
|
|||
Tuple () { }
|
||||
};
|
||||
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct Tuple<Node<TY,TYPES> >
|
||||
: Tuple<TYPES>
|
||||
|
|
@ -243,12 +209,12 @@ namespace typelist{
|
|||
typedef typename Tuple<TYPES>::Type TailType;
|
||||
typedef typename Prepend<TY,TailType>::Tuple Type;
|
||||
|
||||
typedef Node<TY,TYPES> ArgList_;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<TYPES> Tail;
|
||||
enum { SIZE = count<ArgList_>::value };
|
||||
typedef Node<TY,TYPES> ArgList;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<TYPES> Tail;
|
||||
enum { SIZE = count<ArgList>::value };
|
||||
|
||||
Tuple ( TY a1 =TY()
|
||||
Tuple ( TY a1 =TY()
|
||||
, Tail tail =Tail()
|
||||
)
|
||||
: Tuple<TYPES> (tail.getHead(), tail.getTail()),
|
||||
|
|
@ -262,74 +228,189 @@ namespace typelist{
|
|||
TY val_;
|
||||
};
|
||||
|
||||
////TODO move in sub-scope
|
||||
template<class TUP,uint i>
|
||||
struct Shifted
|
||||
{
|
||||
typedef typename TUP::Tail Tail;
|
||||
typedef typename Shifted<Tail,i-1>::TupleType TupleType;
|
||||
};
|
||||
template<class TUP>
|
||||
struct Shifted<TUP,0>
|
||||
{
|
||||
typedef Tuple<typename TUP::ArgList_> TupleType;
|
||||
};
|
||||
|
||||
|
||||
template< typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
, typename T4
|
||||
, typename T5
|
||||
, typename T6
|
||||
, typename T7
|
||||
, typename T8
|
||||
, typename T9
|
||||
>
|
||||
struct Tuple<Types<T1,T2,T3,T4,T5> >
|
||||
: Tuple<typename Types<T1,T2,T3,T4,T5>::List>
|
||||
struct Tuple<Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> >
|
||||
: Tuple<typename Types<T1,T2,T3,T4,T5,T6,T7,T8,T9>::List>
|
||||
{
|
||||
typedef T1 HeadType;
|
||||
typedef Types<T2,T3,T4,T5,NullType> TailType;
|
||||
typedef Types<T1,T2,T3,T4,T5> Type;
|
||||
typedef T1 HeadType;
|
||||
typedef Types<T2,T3,T4,T5,T6,T7,T8,T9,NullType> TailType;
|
||||
typedef Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> Type;
|
||||
|
||||
typedef typename Type::List ArgList_;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<TailType> Tail;
|
||||
enum { SIZE = count<ArgList_>::value };
|
||||
typedef typename Type::List ArgList;
|
||||
typedef Tuple<Type> ThisTuple;
|
||||
typedef Tuple<TailType> Tail;
|
||||
enum { SIZE = count<ArgList>::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<ArgList_>(a1, Tuple<TailType>(a2,a3,a4,a5))
|
||||
: Tuple<ArgList>(a1, Tuple<TailType>(a2,a3,a4,a5,a6,a7,a8,a9))
|
||||
{ }
|
||||
|
||||
using Tuple<ArgList_>::getHead;
|
||||
using Tuple<ArgList_>::getTail;
|
||||
using Tuple<ArgList>::getHead;
|
||||
using Tuple<ArgList>::getTail;
|
||||
|
||||
template<uint i>
|
||||
typename Shifted<ThisTuple,i>::TupleType&
|
||||
class ShiftedTuple
|
||||
{
|
||||
typedef typename Tuple::Type OurType_;
|
||||
typedef typename Shifted<OurType_,i>::Types ShiftedTypes_;
|
||||
public:
|
||||
typedef Tuple<typename ShiftedTypes_::List> Type;
|
||||
};
|
||||
|
||||
template<uint i>
|
||||
typename ShiftedTuple<i>::Type&
|
||||
getShifted ()
|
||||
{
|
||||
typedef typename Shifted<ThisTuple,i>::TupleType Tail_I;
|
||||
typedef typename ShiftedTuple<i>::Type Tail_I;
|
||||
return static_cast<Tail_I&> (*this);
|
||||
}
|
||||
|
||||
template<uint i>
|
||||
typename Shifted<ThisTuple,i>::TupleType::HeadType&
|
||||
typename Shifted<Type,i>::Head&
|
||||
getAt ()
|
||||
{
|
||||
return getShifted<i>().getHead();
|
||||
}
|
||||
|
||||
NullType&
|
||||
getNull()
|
||||
{
|
||||
static NullType nix;
|
||||
return nix;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace tuple { // some convenience access functions
|
||||
|
||||
template<uint n, class TUP>
|
||||
typename TUP::template ShiftedTuple<n>::Type::Head&
|
||||
element (TUP& tup)
|
||||
{
|
||||
return tup.template getAt<n>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Tuple<Types<> >
|
||||
makeNullTuple ()
|
||||
{
|
||||
return Tuple<Types<> > ();
|
||||
}
|
||||
|
||||
|
||||
template< typename T1
|
||||
>
|
||||
Tuple<Types<T1> >
|
||||
make ( T1 a1 =T1()
|
||||
)
|
||||
{
|
||||
return Tuple<Types<T1> > (a1);
|
||||
}
|
||||
|
||||
|
||||
template< typename T1
|
||||
, typename T2
|
||||
>
|
||||
Tuple<Types<T1,T2> >
|
||||
make ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
)
|
||||
{
|
||||
return Tuple<Types<T1,T2> > (a1,a2);
|
||||
}
|
||||
|
||||
|
||||
template< typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
>
|
||||
Tuple<Types<T1,T2,T3> >
|
||||
make ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
, T3 a3 =T3()
|
||||
)
|
||||
{
|
||||
return Tuple<Types<T1,T2,T3> > (a1,a2,a3);
|
||||
}
|
||||
|
||||
|
||||
template< typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
, typename T4
|
||||
>
|
||||
Tuple<Types<T1,T2,T3,T4> >
|
||||
make ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
, T3 a3 =T3()
|
||||
, T4 a4 =T4()
|
||||
)
|
||||
{
|
||||
return Tuple<Types<T1,T2,T3,T4> > (a1,a2,a3,a4);
|
||||
}
|
||||
|
||||
|
||||
template< typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
, typename T4
|
||||
, typename T5
|
||||
>
|
||||
Tuple<Types<T1,T2,T3,T4,T5> >
|
||||
make ( T1 a1 =T1()
|
||||
, T2 a2 =T2()
|
||||
, T3 a3 =T3()
|
||||
, T4 a4 =T4()
|
||||
, T5 a5 =T5()
|
||||
)
|
||||
{
|
||||
return Tuple<Types<T1,T2,T3,T4,T5> > (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<Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> >
|
||||
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<Types<T1,T2,T3,T4,T5,T6,T7,T8,T9> > (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,class,uint> class _X_
|
||||
, class BASE =Tuple<TYPES>
|
||||
, uint i = 0
|
||||
< typename TYPES ///< Type sequence to use within the Accessor (usually the Tuple Types)
|
||||
, template<class,class,class, uint> class _X_ ///< user provided template<Type, Base, TupleType, arg-No>
|
||||
, class TUP =Tuple<TYPES> ///< the tuple type to build on
|
||||
, uint i = 0 ///< tuple element index counter
|
||||
>
|
||||
class BuildTupleAccessor
|
||||
{
|
||||
typedef Tuple<TYPES> ArgTuple;
|
||||
typedef typename ArgTuple::HeadType Head;
|
||||
typedef typename ArgTuple::TailType Tail;
|
||||
// typedef Head ArgTuple::*getElm();
|
||||
typedef BuildTupleAccessor<Tail,_X_,BASE, i+1> NextBuilder;
|
||||
typedef BuildTupleAccessor<Tail,_X_,TUP, i+1> 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_<Head, NextAccessor, i> 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,class,uint> class _X_
|
||||
< template<class,class,class, uint> class _X_
|
||||
, class TUP
|
||||
, uint i
|
||||
>
|
||||
class BuildTupleAccessor<Types<>, _X_, BASE, i>
|
||||
class BuildTupleAccessor<Types<>, _X_, TUP, i>
|
||||
{
|
||||
typedef Tuple<Types<> > ArgTuple;
|
||||
// typedef NullType BASE::*getElm();
|
||||
|
||||
public:
|
||||
typedef _X_<NullType, BASE, 0> Accessor;
|
||||
typedef _X_<NullType, TUP, TUP, 0> Accessor;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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<class TYPES>
|
||||
struct SplitLast;
|
||||
|
||||
template<>
|
||||
struct SplitLast<NullType> { typedef NullType Type;
|
||||
typedef NullType List; };
|
||||
template<class TY>
|
||||
struct SplitLast<Node<TY,NullType> > { typedef TY Type;
|
||||
typedef NullType List; };
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct SplitLast<Node<TY,TYPES> > { typedef typename SplitLast<TYPES>::Type Type;
|
||||
typedef typename Append< TY,
|
||||
typename SplitLast<TYPES>::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
|
||||
|
|
|
|||
|
|
@ -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 <tr1/functional>
|
||||
//#include <boost/format.hpp>
|
||||
|
|
@ -111,7 +114,7 @@ namespace test {
|
|||
typedef typename ARG::List Args;
|
||||
|
||||
typedef typename SplitLast<Args>::Type Memento;
|
||||
typedef typename SplitLast<Args>::Prefix OperationArglist;
|
||||
typedef typename SplitLast<Args>::List OperationArglist;
|
||||
typedef typename Tuple<OperationArglist>::Type OperationArgs;
|
||||
|
||||
typedef typename FunctionTypedef<void, OperationArgs>::Sig OperateSig;
|
||||
|
|
@ -138,33 +141,42 @@ namespace test {
|
|||
};
|
||||
|
||||
|
||||
template<typename TY, class BASE, uint idx>
|
||||
template
|
||||
< typename TY
|
||||
, class BASE
|
||||
, class TUP
|
||||
, uint idx
|
||||
>
|
||||
struct ParamAccessor
|
||||
: BASE
|
||||
{
|
||||
template<class TUP>
|
||||
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 BASE>
|
||||
struct ParamAccessor<NullType, BASE, 0>
|
||||
: BASE
|
||||
|
||||
template<class TUP>
|
||||
struct ParamAccessor<NullType, TUP, TUP, 0>
|
||||
: TUP
|
||||
{
|
||||
template<class TUP>
|
||||
ParamAccessor(TUP& tuple)
|
||||
: BASE(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 typename FunctionSignature< function<SIG> >::Ret Ret;
|
||||
|
||||
typedef Tuple<Args> ArgTuple;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue