From 057f32e15b67951dd7f41374af3e1b1a771857a9 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 25 Sep 2011 15:40:16 +0200 Subject: [PATCH] rename the typelist-manipulation header --- src/lib/meta/generator-combinations.hpp | 2 +- src/lib/meta/tuple.hpp | 2 +- src/lib/meta/typelist-manip.hpp | 366 +++++++++++++++++++++++ src/lib/meta/typeseq-util.hpp | 2 +- src/lib/variant.hpp | 2 +- src/proc/control/command-def.hpp | 2 +- src/proc/control/command-signature.hpp | 5 +- src/proc/engine/nodewiring.cpp | 2 +- src/proc/mobject/output-designation.hpp | 2 +- tests/lib/meta/config-flags-test.cpp | 2 +- tests/lib/meta/function-closure-test.cpp | 2 +- tests/lib/meta/typelist-manip-test.cpp | 2 +- tests/lib/meta/typeseq-manip-test.cpp | 2 +- 13 files changed, 378 insertions(+), 15 deletions(-) create mode 100644 src/lib/meta/typelist-manip.hpp diff --git a/src/lib/meta/generator-combinations.hpp b/src/lib/meta/generator-combinations.hpp index 28790ec01..3cc3a0946 100644 --- a/src/lib/meta/generator-combinations.hpp +++ b/src/lib/meta/generator-combinations.hpp @@ -37,7 +37,7 @@ #define LUMIERA_META_GENERATOR_COMBINATIONS_H #include "lib/meta/typelist.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" #include "lib/meta/generator.hpp" diff --git a/src/lib/meta/tuple.hpp b/src/lib/meta/tuple.hpp index 38d5def29..84559216a 100644 --- a/src/lib/meta/tuple.hpp +++ b/src/lib/meta/tuple.hpp @@ -48,7 +48,7 @@ #define LUMIERA_META_TUPLE_H #include "lib/meta/typelist.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" #include "lib/meta/typeseq-util.hpp" #include "lib/meta/util.hpp" diff --git a/src/lib/meta/typelist-manip.hpp b/src/lib/meta/typelist-manip.hpp new file mode 100644 index 000000000..428c23f97 --- /dev/null +++ b/src/lib/meta/typelist-manip.hpp @@ -0,0 +1,366 @@ +/* + TYPELIST-UTIL.hpp - Utils for working with lists-of-types + + Copyright (C) Lumiera.org + 2008, 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 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. + ** + ** 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. + ** + ** @see generator.hpp + ** @see typelist-manip-test.cpp + ** @see TimeControl_test usage example + ** @see typelist.hpp + ** + */ + + +#ifndef LUMIERA_META_TYPELIST_UTIL_H +#define LUMIERA_META_TYPELIST_UTIL_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 + struct count; + template<> + struct count + { + enum{ value = 0 }; + }; + template + struct count > + { + enum{ value = 1 + count::value }; + }; + + /** + * Metafunction " max( sizeof(T) ) for T in TYPES " + */ + template + struct maxSize; + template<> + struct maxSize + { + enum{ value = 0 }; + }; + template + struct maxSize > + { + enum{ thisval = sizeof(TY) + , nextval = maxSize::value + , value = nextval > thisval? nextval:thisval + }; + }; + + + /** pick the n-th element from a typelist */ + template + struct Pick + { + typedef NullType Type; + }; + template + struct Pick, 0> + { + typedef TY Type; + }; + template + struct Pick, i> + { + typedef typename Pick::Type Type; + }; + + + + + /** apply a transformation (template) to each type in the list */ + template class _TRANS_> + struct Apply { typedef TY List; }; + + template< class TY, class TYPES + , template class _TRANS_ + > + struct Apply, _TRANS_ > { typedef Node< typename _TRANS_::Type + , typename Apply::List + > List; }; + + + /** conditional node: skip an element based on evaluating a predicate */ + template + struct CondNode { typedef TAIL Next; }; + + template + struct CondNode { typedef Node Next; }; + + /** filter away those types which don't fulfil a predicate metafunction */ + template< class TYPES + , template class _P_ ///< a template providing a boolean member \c ::value + > + struct Filter; + + template class _P_> + struct Filter { typedef NullType List; }; + + template< class TY, class TYPES + , template class _P_ + > + struct Filter,_P_> { typedef typename CondNode< _P_::value + , TY + , typename Filter::List + >::Next + List; }; + + + /** append lists-of-types */ + template + struct Append { typedef Node::List> List; }; + + template< class TY, class TYPES + , class TAIL + > + struct Append, TAIL> { typedef Node::List> List; }; + + template + struct Append > { typedef Node List; }; + + template + struct Append, NullType> { typedef Node List; }; + + template + struct Append { typedef Node List; }; + + template + struct Append { typedef Node List; }; + + template<> + struct Append { typedef NullType List; }; + + + + + /** 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; }; + + + + /** + * 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 + struct Splice; + + template + struct Splice, OVERLAY, i> { typedef Node::List> List; + typedef Node::Front> Front; + typedef typename Splice::Back Back; }; + + template + struct Splice,Node,0> { typedef Node::List> List; + typedef NullType Front; + typedef typename Splice::Back Back; }; + + template + struct Splice, NullType, 0> { typedef Node List; + typedef NullType Front; + typedef Node Back; }; + + template + struct Splice { typedef NullType List; + typedef NullType Front; + typedef NullType Back; }; + + + + + /** + * Allows to access various parts of a given typelist: + * Start and End, Prefix and Tail.. + */ + template + struct Dissect; + + template + struct Dissect > + { + typedef Node List; ///< the complete list + typedef T Head; ///< first element + typedef Node First; ///< a list containing the first element + typedef TYPES Tail; ///< remainder of the list starting with the second elm. + typedef typename SplitLast::List Prefix;///< all of the list, up to but excluding the last element + typedef typename SplitLast::Type End; ///< the last element + typedef Node Last; ///< a list containing the last element + }; + + template<> + struct Dissect + { + typedef NullType List; + typedef NullType Head; + typedef NullType First; + typedef NullType Tail; + typedef NullType Prefix; + typedef NullType End; + typedef NullType Last; + }; + + + + + /** + * prefix each of the elements, + * yielding a list-of lists-of-types + */ + template + struct PrefixAll { typedef Node< typename Append::List, NullType> List; }; + + template + struct PrefixAll { typedef NullType List; }; + + template + struct PrefixAll { typedef Node< typename Append::List, NullType> List; }; + + template< class T + , class TY, class TYPES + > + struct PrefixAll > { typedef Node< typename Append::List + , typename PrefixAll::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 + struct Distribute { typedef typename PrefixAll::List List; }; + + template + struct Distribute { typedef NullType List; }; + + template< class TY, class TYPES + , class TAIL + > + struct Distribute,TAIL> { typedef typename Append< typename PrefixAll::List + , typename Distribute::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 _ENUM_> + struct Combine { typedef typename Distribute< typename _ENUM_::List + , Node + >::List List; }; + template< template class _ENUM_> + struct Combine { typedef NodeNull List; }; + + template< class TY, class TYPES + , template class _ENUM_> + struct Combine,_ENUM_> { typedef typename Distribute< typename _ENUM_::List + , typename Combine::List + >::List List; }; + + /** enumeration generator for the Combine metafunction, + * yielding an "on" and "off" case + */ + template + struct FlagOnOff + { + typedef Node > List; + }; + + + /** generate all possible on-off combinations of the given flags */ + template + struct CombineFlags + { + typedef typename Combine::List List; + }; + + + + +}} // namespace lumiera::typelist +#endif diff --git a/src/lib/meta/typeseq-util.hpp b/src/lib/meta/typeseq-util.hpp index 398d09d53..07ecbffa6 100644 --- a/src/lib/meta/typeseq-util.hpp +++ b/src/lib/meta/typeseq-util.hpp @@ -45,7 +45,7 @@ #define LUMIERA_META_TYPESEQ_UTIL_H #include "lib/meta/typelist.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" #include "lib/meta/util.hpp" diff --git a/src/lib/variant.hpp b/src/lib/variant.hpp index b4eef9b76..7b30ba63c 100644 --- a/src/lib/variant.hpp +++ b/src/lib/variant.hpp @@ -45,7 +45,7 @@ #define LIB_VARIANT_H -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" #include "lib/meta/generator.hpp" #include diff --git a/src/proc/control/command-def.hpp b/src/proc/control/command-def.hpp index b3e777c4c..07490ce0b 100644 --- a/src/proc/control/command-def.hpp +++ b/src/proc/control/command-def.hpp @@ -67,7 +67,7 @@ #include "lib/bool-checkable.hpp" #include "lib/meta/function.hpp" #include "lib/meta/typelist.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" #include "lib/meta/tuple.hpp" #include "lib/util.hpp" diff --git a/src/proc/control/command-signature.hpp b/src/proc/control/command-signature.hpp index 3c9df666f..52e4dcf19 100644 --- a/src/proc/control/command-signature.hpp +++ b/src/proc/control/command-signature.hpp @@ -47,14 +47,11 @@ #define CONTROL_COMMAND_SIGNATURE_H //#include "pre.hpp" -//#include "lib/symbol.hpp" #include "lib/meta/function.hpp" #include "lib/meta/typelist.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" #include "lib/meta/typeseq-util.hpp" -//#include "lib/meta/tuple.hpp" -//#include #include diff --git a/src/proc/engine/nodewiring.cpp b/src/proc/engine/nodewiring.cpp index f1e989816..9be5dd541 100644 --- a/src/proc/engine/nodewiring.cpp +++ b/src/proc/engine/nodewiring.cpp @@ -26,7 +26,7 @@ #include "proc/engine/nodeoperation.hpp" #include "proc/engine/nodewiring-config.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" namespace engine { diff --git a/src/proc/mobject/output-designation.hpp b/src/proc/mobject/output-designation.hpp index 93f98f518..bfd47b8a5 100644 --- a/src/proc/mobject/output-designation.hpp +++ b/src/proc/mobject/output-designation.hpp @@ -26,7 +26,7 @@ #include "proc/asset/pipe.hpp" #include "lib/opaque-holder.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" extern "C" { #include "lib/luid.h" diff --git a/tests/lib/meta/config-flags-test.cpp b/tests/lib/meta/config-flags-test.cpp index 57a5621d1..757f84d39 100644 --- a/tests/lib/meta/config-flags-test.cpp +++ b/tests/lib/meta/config-flags-test.cpp @@ -40,7 +40,7 @@ #include "lib/test/run.hpp" #include "lib/meta/util.hpp" #include "lib/meta/generator.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" #include "lib/meta/configflags.hpp" #include "meta/typelist-diagnostics.hpp" #include "proc/engine/nodewiring-config.hpp" diff --git a/tests/lib/meta/function-closure-test.cpp b/tests/lib/meta/function-closure-test.cpp index e024ff808..4d2eb2a06 100644 --- a/tests/lib/meta/function-closure-test.cpp +++ b/tests/lib/meta/function-closure-test.cpp @@ -38,7 +38,7 @@ #include "lib/test/run.hpp" #include "lib/test/test-helper.hpp" #include "lib/meta/typelist.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" #include "lib/meta/function.hpp" #include "lib/meta/function-closure.hpp" #include "meta/typelist-diagnostics.hpp" diff --git a/tests/lib/meta/typelist-manip-test.cpp b/tests/lib/meta/typelist-manip-test.cpp index a14daef90..57f88d1dd 100644 --- a/tests/lib/meta/typelist-manip-test.cpp +++ b/tests/lib/meta/typelist-manip-test.cpp @@ -40,7 +40,7 @@ #include "lib/test/run.hpp" #include "lib/meta/generator.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" #include "meta/typelist-diagnostics.hpp" #include diff --git a/tests/lib/meta/typeseq-manip-test.cpp b/tests/lib/meta/typeseq-manip-test.cpp index 6efffd272..3445d2217 100644 --- a/tests/lib/meta/typeseq-manip-test.cpp +++ b/tests/lib/meta/typeseq-manip-test.cpp @@ -39,7 +39,7 @@ #include "lib/test/run.hpp" #include "lib/meta/typeseq-util.hpp" -#include "lib/meta/typelist-util.hpp" +#include "lib/meta/typelist-manip.hpp" #include "meta/typelist-diagnostics.hpp" #include