split off and test-cover simple typelist utils
these simple utils (length of typelist, maximum size containment test) are mostly not used in conjunction with the more elaborate typelist manipulatino utils. Moreover, we lacked a dedicated unit test
This commit is contained in:
parent
057f32e15b
commit
5350ef6dbe
9 changed files with 166 additions and 360 deletions
|
|
@ -48,7 +48,7 @@
|
|||
#define LUMIERA_META_TUPLE_H
|
||||
|
||||
#include "lib/meta/typelist.hpp"
|
||||
#include "lib/meta/typelist-manip.hpp"
|
||||
#include "lib/meta/typelist-util.hpp"
|
||||
#include "lib/meta/typeseq-util.hpp"
|
||||
#include "lib/meta/util.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
TYPELIST-UTIL.hpp - Utils for working with lists-of-types
|
||||
TYPELIST-MANIP.hpp - Utils for working with lists-of-types
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
|
@ -21,8 +21,8 @@
|
|||
*/
|
||||
|
||||
|
||||
/** @file typelist-util.hpp
|
||||
** Metaprogramming: Helpers for manipulating lists-of-types.
|
||||
/** @file typelist-manip.hpp
|
||||
** Metaprogramming: Helpers for manipulating lists-of-types.
|
||||
** Sometimes, we use metaprogramming to generate a variation of concrete
|
||||
** implementations by combining some basic building blocks. Typically, there
|
||||
** is a number of similar, but not suitably related types involved. We want to
|
||||
|
|
@ -49,54 +49,17 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifndef LUMIERA_META_TYPELIST_UTIL_H
|
||||
#define LUMIERA_META_TYPELIST_UTIL_H
|
||||
#ifndef LUMIERA_META_TYPELIST_MANIP_H
|
||||
#define LUMIERA_META_TYPELIST_MANIP_H
|
||||
|
||||
|
||||
|
||||
|
||||
#include "lib/meta/typelist.hpp"
|
||||
|
||||
namespace lumiera {
|
||||
namespace typelist{
|
||||
|
||||
|
||||
/**
|
||||
* Metafunction counting the number of Types in the collection
|
||||
* @return an embedded constant \c value holding the result
|
||||
*/
|
||||
template<class TYPES>
|
||||
struct count;
|
||||
template<>
|
||||
struct count<NullType>
|
||||
{
|
||||
enum{ value = 0 };
|
||||
};
|
||||
template<class TY, class TYPES>
|
||||
struct count<Node<TY,TYPES> >
|
||||
{
|
||||
enum{ value = 1 + count<TYPES>::value };
|
||||
};
|
||||
|
||||
/**
|
||||
* Metafunction " max( sizeof(T) ) for T in TYPES "
|
||||
*/
|
||||
template<class TYPES>
|
||||
struct maxSize;
|
||||
template<>
|
||||
struct maxSize<NullType>
|
||||
{
|
||||
enum{ value = 0 };
|
||||
};
|
||||
template<class TY, class TYPES>
|
||||
struct maxSize<Node<TY,TYPES> >
|
||||
{
|
||||
enum{ thisval = sizeof(TY)
|
||||
, nextval = maxSize<TYPES>::value
|
||||
, value = nextval > thisval? nextval:thisval
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/** pick the n-th element from a typelist */
|
||||
template<class TYPES, uint i>
|
||||
struct Pick
|
||||
|
|
@ -111,7 +74,7 @@ namespace typelist{
|
|||
template<class TY, class TYPES, uint i>
|
||||
struct Pick<Node<TY,TYPES>, i>
|
||||
{
|
||||
typedef typename Pick<TYPES, i-1>::Type Type;
|
||||
typedef typename Pick<TYPES, i-1>::Type Type;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -240,7 +203,7 @@ namespace typelist{
|
|||
|
||||
/**
|
||||
* Allows to access various parts of a given typelist:
|
||||
* Start and End, Prefix and Tail..
|
||||
* Start and End, Prefix and Tail...
|
||||
*/
|
||||
template<class TYPES>
|
||||
struct Dissect;
|
||||
|
|
@ -356,7 +319,7 @@ namespace typelist{
|
|||
template<class FLAGS>
|
||||
struct CombineFlags
|
||||
{
|
||||
typedef typename Combine<FLAGS, FlagOnOff>::List List;
|
||||
typedef typename Combine<FLAGS, FlagOnOff>::List List;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
TYPELIST-UTIL.hpp - Utils for working with lists-of-types
|
||||
TYPELIST-UTIL.hpp - simple helpers for working with lists-of-types
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
|
@ -22,28 +22,21 @@
|
|||
|
||||
|
||||
/** @file typelist-util.hpp
|
||||
** Metaprogramming: Helpers for manipulating lists-of-types.
|
||||
** Sometimes, we use metaprogramming to generate a variation of concrete
|
||||
** implementations by combining some basic building blocks. Typically, there
|
||||
** is a number of similar, but not suitably related types involved. We want to
|
||||
** process those types using a common scheme, without being forced to squeeze
|
||||
** all those types into a artificial inheritance relationship. Now, generating
|
||||
** some kind of common factory or adapter, while mixing in pieces of code tailored
|
||||
** specifically to the individual types, allows still to build a common processing
|
||||
** in such situations.
|
||||
** Metaprogramming: simple helpers for working with lists-of-types.
|
||||
** This header provides some very basic "meta functions" for extracting
|
||||
** some informations from a list-of-types. In Lumiera, we use template
|
||||
** metaprogramming and especially such lists-of-types, whenever we build
|
||||
** some common implementation backbone, without being able to subsume all
|
||||
** participating types (classes) into a single inheritance hierarchy.
|
||||
**
|
||||
** The facilities in this header provide the basics of simple functional list
|
||||
** processing (mostly with tail recursion). Usually, there is one template parameter
|
||||
** TYPES, which accepts a \em Type-list. The result of the processing step is then
|
||||
** accessible as an embedded typedef named \c List . Here, all of the 'processing'
|
||||
** to calculate this result is performed by the compiler, as a side-effect of
|
||||
** figuring out the resulting concrete type. At run time, in the generated
|
||||
** code, typically the resulting classes are empty, maybe just
|
||||
** exposing a specifically built-up function.
|
||||
** The "meta functions" defined here are templates; to access the "result" of
|
||||
** such a meta function, we instantiate the template and then access one of the
|
||||
** embedded constant definitions (usually the enum constant named \c value)
|
||||
**
|
||||
** @see generator.hpp
|
||||
** @see typelist-manip-test.cpp
|
||||
** @see TimeControl_test usage example
|
||||
** @see TypelistUtil_test
|
||||
** @see lib::SimpleAllocator usage example (for isInList)
|
||||
** @see TypelistManip_test
|
||||
** @see typelist.hpp
|
||||
**
|
||||
*/
|
||||
|
|
@ -53,7 +46,7 @@
|
|||
#define LUMIERA_META_TYPELIST_UTIL_H
|
||||
|
||||
|
||||
|
||||
|
||||
#include "lib/meta/typelist.hpp"
|
||||
|
||||
namespace lumiera {
|
||||
|
|
@ -77,6 +70,7 @@ namespace typelist{
|
|||
enum{ value = 1 + count<TYPES>::value };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Metafunction " max( sizeof(T) ) for T in TYPES "
|
||||
*/
|
||||
|
|
@ -97,268 +91,35 @@ namespace typelist{
|
|||
};
|
||||
|
||||
|
||||
/** pick the n-th element from a typelist */
|
||||
template<class TYPES, uint i>
|
||||
struct Pick
|
||||
{
|
||||
typedef NullType Type;
|
||||
};
|
||||
template<class TY, class TYPES>
|
||||
struct Pick<Node<TY,TYPES>, 0>
|
||||
{
|
||||
typedef TY Type;
|
||||
};
|
||||
template<class TY, class TYPES, uint i>
|
||||
struct Pick<Node<TY,TYPES>, i>
|
||||
{
|
||||
typedef typename Pick<TYPES, i-1>::Type Type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** apply a transformation (template) to each type in the list */
|
||||
template<class TY, template<class> class _TRANS_>
|
||||
struct Apply { typedef TY List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, template<class> class _TRANS_
|
||||
>
|
||||
struct Apply<Node<TY,TYPES>, _TRANS_ > { typedef Node< typename _TRANS_<TY>::Type
|
||||
, typename Apply<TYPES,_TRANS_>::List
|
||||
> List; };
|
||||
|
||||
|
||||
/** conditional node: skip an element based on evaluating a predicate */
|
||||
template<bool, class T, class TAIL>
|
||||
struct CondNode { typedef TAIL Next; };
|
||||
|
||||
template<class T, class TAIL>
|
||||
struct CondNode<true, T, TAIL> { typedef Node<T,TAIL> Next; };
|
||||
|
||||
/** filter away those types which don't fulfil a predicate metafunction */
|
||||
template< class TYPES
|
||||
, template<class> class _P_ ///< a template providing a boolean member \c ::value
|
||||
>
|
||||
struct Filter;
|
||||
|
||||
template<template<class> class _P_>
|
||||
struct Filter<NullType,_P_> { typedef NullType List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, template<class> class _P_
|
||||
>
|
||||
struct Filter<Node<TY,TYPES>,_P_> { typedef typename CondNode< _P_<TY>::value
|
||||
, TY
|
||||
, typename Filter<TYPES,_P_>::List
|
||||
>::Next
|
||||
List; };
|
||||
|
||||
|
||||
/** append lists-of-types */
|
||||
template<class TY1, class TY2>
|
||||
struct Append { typedef Node<TY1, typename Append<TY2,NullType>::List> List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, class TAIL
|
||||
>
|
||||
struct Append<Node<TY,TYPES>, TAIL> { typedef Node<TY, typename Append<TYPES, TAIL>::List> List; };
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct Append<NullType, Node<TY,TYPES> > { typedef Node<TY,TYPES> List; };
|
||||
|
||||
template<class TY, class TYPES>
|
||||
struct Append<Node<TY,TYPES>, NullType> { typedef Node<TY,TYPES> List; };
|
||||
|
||||
template<class TY1>
|
||||
struct Append<TY1,NullType> { typedef Node<TY1,NullType> List; };
|
||||
|
||||
template<class TY2>
|
||||
struct Append<NullType,TY2> { typedef Node<TY2,NullType> List; };
|
||||
|
||||
template<>
|
||||
struct Append<NullType,NullType> { typedef NullType List; };
|
||||
|
||||
|
||||
|
||||
|
||||
/** 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; };
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* splice a typelist like an overlay
|
||||
* into an base typelist, starting at given index.
|
||||
* @return either the combined (spliced) List, or
|
||||
* the Front/Back part before or after the Overlay
|
||||
* @note using a NullType as OVERLAY allows to extract
|
||||
* an arbitrary Front/Back part of the list
|
||||
*/
|
||||
template<class BASE, class OVERLAY, uint i=0>
|
||||
struct Splice;
|
||||
|
||||
template<class B, class BS,
|
||||
class OVERLAY, uint i>
|
||||
struct Splice<Node<B,BS>, OVERLAY, i> { typedef Node<B, typename Splice<BS, OVERLAY, i-1>::List> List;
|
||||
typedef Node<B, typename Splice<BS, OVERLAY, i-1>::Front> Front;
|
||||
typedef typename Splice<BS, OVERLAY, i-1>::Back Back; };
|
||||
|
||||
template<class B, class BS,
|
||||
class O, class OS >
|
||||
struct Splice<Node<B,BS>,Node<O,OS>,0> { typedef Node<O, typename Splice<BS,OS, 0>::List> List;
|
||||
typedef NullType Front;
|
||||
typedef typename Splice<BS,OS, 0>::Back Back; };
|
||||
|
||||
template<class B, class BS>
|
||||
struct Splice<Node<B,BS>, NullType, 0> { typedef Node<B, BS> List;
|
||||
typedef NullType Front;
|
||||
typedef Node<B, BS> Back; };
|
||||
|
||||
template<class XX, uint i>
|
||||
struct Splice<NullType, XX, i> { typedef NullType List;
|
||||
typedef NullType Front;
|
||||
typedef NullType Back; };
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allows to access various parts of a given typelist:
|
||||
* Start and End, Prefix and Tail..
|
||||
* Metafunction to check if a specific type is contained
|
||||
* in a given typelist. Only exact match is detected.
|
||||
*/
|
||||
template<class TYPES>
|
||||
struct Dissect;
|
||||
|
||||
template<class T, class TYPES>
|
||||
struct Dissect<Node<T,TYPES> >
|
||||
template<typename TY, typename TYPES>
|
||||
struct IsInList
|
||||
{
|
||||
typedef Node<T,TYPES> List; ///< the complete list
|
||||
typedef T Head; ///< first element
|
||||
typedef Node<T,NullType> First; ///< a list containing the first element
|
||||
typedef TYPES Tail; ///< remainder of the list starting with the second elm.
|
||||
typedef typename SplitLast<List>::List Prefix;///< all of the list, up to but excluding the last element
|
||||
typedef typename SplitLast<List>::Type End; ///< the last element
|
||||
typedef Node<End,NullType> Last; ///< a list containing the last element
|
||||
enum{ value = false };
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Dissect<NullType>
|
||||
template<typename TY, typename TYPES>
|
||||
struct IsInList<TY, Node<TY,TYPES> >
|
||||
{
|
||||
typedef NullType List;
|
||||
typedef NullType Head;
|
||||
typedef NullType First;
|
||||
typedef NullType Tail;
|
||||
typedef NullType Prefix;
|
||||
typedef NullType End;
|
||||
typedef NullType Last;
|
||||
enum{ value = true };
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* prefix each of the elements,
|
||||
* yielding a list-of lists-of-types
|
||||
*/
|
||||
template<class T, class TY>
|
||||
struct PrefixAll { typedef Node< typename Append<T,TY>::List, NullType> List; };
|
||||
|
||||
template<class T>
|
||||
struct PrefixAll<T, NullType> { typedef NullType List; };
|
||||
|
||||
template<class T>
|
||||
struct PrefixAll<T, NodeNull> { typedef Node< typename Append<T,NodeNull>::List, NullType> List; };
|
||||
|
||||
template< class T
|
||||
, class TY, class TYPES
|
||||
>
|
||||
struct PrefixAll<T, Node<TY,TYPES> > { typedef Node< typename Append<T,TY>::List
|
||||
, typename PrefixAll<T,TYPES>::List
|
||||
> List; };
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* build a list-of lists, where each element of the first arg list
|
||||
* gets in turn prepended to all elements of the second arg list.
|
||||
* Can be used to build all possible combinations from two
|
||||
* sources, i.e. the Cartesian product.
|
||||
*/
|
||||
template<class TY1,class TY2>
|
||||
struct Distribute { typedef typename PrefixAll<TY1,TY2>::List List; };
|
||||
|
||||
template<class TY>
|
||||
struct Distribute<NullType,TY> { typedef NullType List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, class TAIL
|
||||
>
|
||||
struct Distribute<Node<TY,TYPES>,TAIL> { typedef typename Append< typename PrefixAll<TY,TAIL>::List
|
||||
, typename Distribute<TYPES,TAIL>::List
|
||||
>::List
|
||||
List; };
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* build all possible combinations, based on a enumeration of the basic cases.
|
||||
* For each of the types in the argument list, an "enumeration generator" template is invoked,
|
||||
* yielding a list of the possible base cases. These base cases are then combined with all the
|
||||
* combinations of the rest, yielding all ordered combinations of all cases. Here, "ordered"
|
||||
* means that the base cases of the n-th element will appear in the n-th position of the
|
||||
* resulting lists,
|
||||
*
|
||||
* For the typical example, the "base cases" are {flag(on), flag(off)}, so we get a
|
||||
* list-of-lists, featuring all possibilities to combine these distinct toggles.
|
||||
*/
|
||||
template< class X
|
||||
, template<class> class _ENUM_>
|
||||
struct Combine { typedef typename Distribute< typename _ENUM_<X>::List
|
||||
, Node<NullType,NullType>
|
||||
>::List List; };
|
||||
template< template<class> class _ENUM_>
|
||||
struct Combine<NullType, _ENUM_ > { typedef NodeNull List; };
|
||||
|
||||
template< class TY, class TYPES
|
||||
, template<class> class _ENUM_>
|
||||
struct Combine<Node<TY,TYPES>,_ENUM_> { typedef typename Distribute< typename _ENUM_<TY>::List
|
||||
, typename Combine<TYPES,_ENUM_>::List
|
||||
>::List List; };
|
||||
|
||||
/** enumeration generator for the Combine metafunction,
|
||||
* yielding an "on" and "off" case
|
||||
*/
|
||||
template<class F>
|
||||
struct FlagOnOff
|
||||
{
|
||||
typedef Node<F, Node<NullType,NullType> > List;
|
||||
};
|
||||
|
||||
|
||||
/** generate all possible on-off combinations of the given flags */
|
||||
template<class FLAGS>
|
||||
struct CombineFlags
|
||||
{
|
||||
typedef typename Combine<FLAGS, FlagOnOff>::List List;
|
||||
template<typename TY, typename XX, typename TYPES>
|
||||
struct IsInList<TY, Node<XX,TYPES> >
|
||||
{
|
||||
enum{ value = IsInList<TY,TYPES>::value };
|
||||
};
|
||||
|
||||
/** convenience shortcut: query function */
|
||||
template<typename TY, typename TYPES>
|
||||
bool
|
||||
isInList()
|
||||
{
|
||||
return IsInList<TY,TYPES>::value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,15 +40,25 @@ This code is heavily inspired by
|
|||
|
||||
/** @file typelist.hpp
|
||||
** A template metaprogramming technique for manipulating collections of types.
|
||||
** Effectively this is a taylored and simplified version of what can be found in the Loki library.
|
||||
** Effectively this is a tailored and simplified version of what can be found in the Loki library.
|
||||
** We use it in other generic library-style code to generate repetitive code. If you tend to find
|
||||
** template metaprogramming (or functional programming in general) offending, please ignore the
|
||||
** technical details and just consider the benefit of such an simplification for the user code.
|
||||
**
|
||||
** Interface for using this facility is the template Types(.....) for up to 20 Type parameters
|
||||
** technical details and just consider the benefit of such an simplification for the client code.
|
||||
**
|
||||
** Interface for using this facility is the template Types(.....) for up to 20 Type parameters.
|
||||
** To start typelist processing, other templates typically pick up the Types<...>::List type.
|
||||
** This allows for LISP-style list processing, with a pattern match on either Node<TY,TYPES>
|
||||
** or NullType to terminate recursion. In C++ template metaprogramming, "pattern match"
|
||||
** is done by partial template specialisations (the compiler will pick up and thus
|
||||
** match the template parameters). A typedef acts like a declaration in normal
|
||||
** programming. Because such a "declaration" can't be changed after the fact,
|
||||
** effectively this is a flavour of functional programming. Just the
|
||||
** "execution environment" is the compiler, during compilation.
|
||||
**
|
||||
** @see lumiera::visitor::Applicable usage example
|
||||
** @see typelisttest.cpp
|
||||
** @see control::CommandSignature more elaborate usage example (dissecting a functor signature)
|
||||
** @see TypeList_test
|
||||
** @see TypeListManip_test
|
||||
**
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
//#include "pre.hpp"
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/meta/generator.hpp"
|
||||
#include "lib/meta/typelist-util.hpp"
|
||||
#include "lib/format.hpp"
|
||||
//#include "lib/typed-counter.hpp"
|
||||
#include "include/logging.h"
|
||||
|
|
@ -63,31 +64,11 @@
|
|||
namespace lib {
|
||||
|
||||
// using std::tr1::shared_ptr;
|
||||
using lumiera::typelist::InstantiateForEach;
|
||||
using lumiera::typelist::Types;
|
||||
using lumiera::typelist::IsInList;
|
||||
using lumiera::typelist::InstantiateForEach;
|
||||
|
||||
namespace {
|
||||
using lumiera::typelist::Node;
|
||||
using lumiera::typelist::NullType;
|
||||
|
||||
template<typename TYPES, typename TY>
|
||||
struct IsInList
|
||||
{
|
||||
enum{ value = false };
|
||||
};
|
||||
|
||||
template<typename TY, typename TYPES>
|
||||
struct IsInList<Node<TY,TYPES>, TY>
|
||||
{
|
||||
enum{ value = true };
|
||||
};
|
||||
|
||||
template<typename XX, typename TYPES, typename TY>
|
||||
struct IsInList<Node<XX,TYPES>, TY>
|
||||
{
|
||||
enum{ value = IsInList<TYPES,TY>::value };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -141,9 +122,9 @@ namespace lib {
|
|||
___assertSupportedType()
|
||||
{
|
||||
typedef typename TYPES::List PreconfiguredTypes;
|
||||
typedef IsInList<PreconfiguredTypes,XX> IsPreconfiguredType;
|
||||
typedef IsInList<XX, PreconfiguredTypes> IsSupportedType;
|
||||
|
||||
BOOST_STATIC_ASSERT (IsPreconfiguredType::value);
|
||||
BOOST_STATIC_ASSERT (IsSupportedType::value);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
#define LIB_VARIANT_H
|
||||
|
||||
|
||||
#include "lib/meta/typelist-manip.hpp"
|
||||
#include "lib/meta/typelist-util.hpp"
|
||||
#include "lib/meta/generator.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
** we need to accept functor objects with a very specific and predetermined
|
||||
** signature, thus allowing for strict type checking by the compiler.
|
||||
**
|
||||
** \par Relation of function signatures
|
||||
** \par Relation of function signatures (MEM = type of the "memento" for Undo)
|
||||
** - operation: void(P1,..PN)
|
||||
** - captureUndo: MEM(P1,..PN)
|
||||
** - undoOperation void(P1,..PN,MEM)
|
||||
|
|
@ -59,24 +59,20 @@
|
|||
|
||||
namespace control {
|
||||
|
||||
// using lib::Symbol;
|
||||
// using std::tr1::shared_ptr;
|
||||
using std::tr1::function;
|
||||
|
||||
using lumiera::typelist::FunctionSignature;
|
||||
using lumiera::typelist::FunctionTypedef;
|
||||
using lumiera::typelist::Types;
|
||||
//using lumiera::typelist::NullType;
|
||||
//using lumiera::typelist::Tuple;
|
||||
using lumiera::typelist::Append;
|
||||
using lumiera::typelist::SplitLast;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Metaprogramming helper for building Command function signatures.
|
||||
* Metaprogramming helper for building Command function signatures.
|
||||
* The complete definition context of any command is templated to the signature
|
||||
* of the actual command operation and to the memento type. The typedefs embedded
|
||||
* within CommandSignature<SIG,MEM> allows accepting suitable typed functions
|
||||
* within CommandSignature<SIG,MEM> allows for accepting suitable typed functions
|
||||
* to implement the command in question.
|
||||
*/
|
||||
template<typename SIG, typename MEM>
|
||||
|
|
@ -90,7 +86,7 @@ namespace control {
|
|||
|
||||
public:
|
||||
typedef typename FunctionTypedef<void, Args>::Sig OperateSig;
|
||||
typedef typename FunctionTypedef<MEM, Args>::Sig CaptureSig;
|
||||
typedef typename FunctionTypedef<MEM, Args>::Sig CaptureSig;
|
||||
typedef typename FunctionTypedef<void, ExtendedArgs>::Sig UndoOp_Sig;
|
||||
typedef Args CmdArgs;
|
||||
typedef MEM Memento;
|
||||
|
|
@ -100,16 +96,23 @@ namespace control {
|
|||
|
||||
|
||||
/**
|
||||
* Type analysis helper template.
|
||||
* Type analysis helper template.
|
||||
* Used for dissecting a given type signature to derive
|
||||
* the related basic operation signature, the signature of a possible Undo-function
|
||||
* and the signature necessary for capturing undo information. The implementation
|
||||
* relies on re-binding an embedded type defining template, based on the actual
|
||||
* case, as identified by the structure of the given parameter signature.
|
||||
*
|
||||
* To use this template, it is instantiated with the signature of a functor object
|
||||
* in question. Depending on the actual situation, the compiler will then either
|
||||
* pick Case1 or Case2 -- thus allowing the client in any case to pick up the
|
||||
* correct signatures for Operation, Capture and Undo-function from the
|
||||
* public typedefs within \c UndoSignature
|
||||
*/
|
||||
template<typename SIG>
|
||||
class UndoSignature
|
||||
{
|
||||
// preparation: dissect the function signature into arguments and result
|
||||
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
||||
typedef typename FunctionSignature< function<SIG> >::Ret Ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -801,6 +801,11 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
TEST "simple typelist utils" TypeListUtil_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "TypeListGenerator_test" TypeListGenerator_test <<END
|
||||
out: ctor DoIt<Block<13> >
|
||||
out: ctor DoIt<Block< 8> >
|
||||
|
|
|
|||
83
tests/lib/meta/typelist-util-test.cpp
Normal file
83
tests/lib/meta/typelist-util-test.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
TypeListUtil(Test) - check the simple typelist metaprogramming helpers
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2011, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
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.
|
||||
|
||||
* *****************************************************/
|
||||
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/meta/typelist-util.hpp"
|
||||
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
namespace typelist{
|
||||
namespace test {
|
||||
|
||||
|
||||
|
||||
typedef Types< int
|
||||
, uint
|
||||
, int64_t
|
||||
, uint64_t
|
||||
>::List TheList;
|
||||
|
||||
typedef Types< >::List EmptyList;
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* @test verify the simple helpers for working with lists-of-types.
|
||||
* These are simple metafunctions to count the number of elements,
|
||||
* calculate the maximum size or check for inclusion.
|
||||
*
|
||||
* Because these metafunctions will be computed during compilation,
|
||||
* mostly the function is already verified when it passes compilation.
|
||||
* All we can do here, at runtime, is to verify some of the (expected)
|
||||
* constant results.
|
||||
*/
|
||||
class TypeListUtil_test : public Test
|
||||
{
|
||||
void
|
||||
run (Arg)
|
||||
{
|
||||
CHECK (4 == count<TheList>::value);
|
||||
CHECK (0 == count<EmptyList>::value);
|
||||
|
||||
CHECK (sizeof(int64_t) == maxSize<TheList>::value);
|
||||
CHECK (0 == maxSize<EmptyList>::value);
|
||||
|
||||
CHECK ( bool(IsInList<int , TheList>::value));
|
||||
CHECK ( bool(IsInList<uint , TheList>::value));
|
||||
CHECK ( bool(IsInList<int64_t , TheList>::value));
|
||||
CHECK ( bool(IsInList<uint64_t, TheList>::value));
|
||||
|
||||
CHECK (!bool(IsInList<double , TheList>::value));
|
||||
CHECK (!bool(IsInList<int , EmptyList>::value));
|
||||
CHECK (!bool(IsInList<int , int>::value)); // Note: not-a-typelist yields false too
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (TypeListUtil_test, "unit common");
|
||||
|
||||
|
||||
|
||||
}}} // namespace lumiera::typelist::test
|
||||
Loading…
Reference in a new issue