diff options
| author | Sebastien Braun | 2010-10-07 22:54:10 +0200 |
|---|---|---|
| committer | Sebastien Braun | 2010-10-07 22:54:10 +0200 |
| commit | e61097b8881bc7e72a5499816cb1199ea274a3ca (patch) | |
| tree | bcfa9f3fe3f43af02845bc21367de395b248600c /src/input/detail | |
| parent | Make behaviour on lookup failures configurable (diff) | |
| download | pvs-e61097b8881bc7e72a5499816cb1199ea274a3ca.tar.gz pvs-e61097b8881bc7e72a5499816cb1199ea274a3ca.tar.xz pvs-e61097b8881bc7e72a5499816cb1199ea274a3ca.zip | |
Rework template meta-magic
- No more implicit dependency on Boost.MPL
- Better documentation for template magic
- Move input handler policies to handler definitions where they belong
- Separate out event descriptions from handlers
Diffstat (limited to 'src/input/detail')
| -rw-r--r-- | src/input/detail/Makefile.autogen | 8 | ||||
| -rw-r--r-- | src/input/detail/gen/gen_policyChain.cpp | 68 | ||||
| -rw-r--r-- | src/input/detail/gen/gen_typeList.cpp | 115 | ||||
| -rw-r--r-- | src/input/detail/policyChain.h | 78 | ||||
| -rw-r--r-- | src/input/detail/policyChain_autogen.h | 8 | ||||
| -rw-r--r-- | src/input/detail/systemTraits.h | 94 | ||||
| -rw-r--r-- | src/input/detail/typeList.h | 76 | ||||
| -rw-r--r-- | src/input/detail/typeList_autogen.h | 60 |
8 files changed, 507 insertions, 0 deletions
diff --git a/src/input/detail/Makefile.autogen b/src/input/detail/Makefile.autogen new file mode 100644 index 0000000..6d0bfb3 --- /dev/null +++ b/src/input/detail/Makefile.autogen @@ -0,0 +1,8 @@ +all : policyChain_autogen.h typeList_autogen.h +.PHONY : all + +policyChain_autogen.h : gen/gen_policyChain + gen/gen_policyChain > policyChain_autogen.h + +typeList_autogen.h : gen/gen_typeList + gen/gen_typeList > typeList_autogen.h diff --git a/src/input/detail/gen/gen_policyChain.cpp b/src/input/detail/gen/gen_policyChain.cpp new file mode 100644 index 0000000..3e375ec --- /dev/null +++ b/src/input/detail/gen/gen_policyChain.cpp @@ -0,0 +1,68 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # detail/gen/gen_policyChain.cpp: + # - generate the input_policy::detail::PolicyChain class + # -------------------------------------------------------------------------- + */ + +#include <iostream> + +using namespace std; + +#define NUM_POLICIES 8 + +int main(int, char**) +{ + int i; + + cout << "template<typename BaseCase"; + for(i = 0; i < NUM_POLICIES; i++) + { + cout << ", typename P" << i; + } + cout << ">\nstruct PolicyChain :\npublic P0::template apply_<PolicyChain<BaseCase"; + for(i = 1; i < NUM_POLICIES; i++) + { + cout << ", P" << i; + } + cout << ", void> >\n"; + cout << "{};\n"; + + // Base case: + cout << "template<typename BaseCase>\n"; + cout << "struct PolicyChain<BaseCase"; + for(i = 0; i < NUM_POLICIES; i++) + { + cout << ", void"; + } + cout << "> : public BaseCase {};\n"; + + // We need the following in macros: + cout << "#define _autogen_POLICY_TEMPLATE_PARAMS "; + for(i = 0; i < NUM_POLICIES; i++) + { + if(i) + cout << ", "; + cout << "typename P" << i; + } + + cout << "\n#define _autogen_POLICY_TEMPLATE_ARGS "; + for(i = 0; i < NUM_POLICIES; i++) + { + if(i) + cout << ", "; + cout << "P" << i; + } + cout << "\n"; + + return 0; +} diff --git a/src/input/detail/gen/gen_typeList.cpp b/src/input/detail/gen/gen_typeList.cpp new file mode 100644 index 0000000..e092b80 --- /dev/null +++ b/src/input/detail/gen/gen_typeList.cpp @@ -0,0 +1,115 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # detail/gen/gen_policyChain.cpp: + # - generate the input_policy::detail::TypeList class + # -------------------------------------------------------------------------- + */ + +#include <iostream> + +using namespace std; + +#define NUM_MAX_ENTRIES 16 + +int main(int, char**) +{ + int i; + + cout << "template<"; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "typename T" << i << " = void"; + } + cout << ">\nstruct TypeList {\n"; + cout << "typedef T0 head;\n"; + cout << "typedef TypeList<"; + for(i = 1; i < NUM_MAX_ENTRIES; i++) + { + if(i > 1) + cout << ", "; + cout << "T" << i; + } + cout << ", void > tail;\n"; + cout << "};\n"; + + // Contains: + cout << "template<typename Needle, typename Haystack>\n" + "struct Contains { static const int index = -1; static const bool value = false; };\n"; + + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + int j; + + cout << "template<typename Needle"; + for(j = 0; j < NUM_MAX_ENTRIES; j++) + { + if(j == i) + continue; + cout << ", typename T" << j; + } + cout << ">\nstruct Contains<Needle, TypeList<"; + for(j = 0; j < NUM_MAX_ENTRIES; j++) + { + if(j) + cout << ", "; + if(j == i) + cout << "Needle"; + else + cout << "T" << j; + } + cout << "> >\n{ static const int index = " << i << "; static const bool value = true; };\n"; + } + + // Empty List: + cout << "typedef TypeList<"; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "void"; + } + cout << " > EmptyList;\n"; + + // Macros: + cout << "#define IMPLICIT_TYPE_LIST_PARAMS(prefix) "; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "typename prefix##" << i << " = void"; + } + cout << "\n"; + + cout << "#define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) "; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "typename prefix##" << i; + } + cout << "\n"; + + cout << "#define IMPLICIT_TYPE_LIST_ARGS(prefix) "; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "prefix##" << i; + } + cout << "\n"; + + cout << "#define IMPLICIT_TYPE_LIST(prefix) ::input_policy::detail::TypeList<IMPLICIT_TYPE_LIST_ARGS(prefix) >\n"; + + return 0; +} diff --git a/src/input/detail/policyChain.h b/src/input/detail/policyChain.h new file mode 100644 index 0000000..ae01ff2 --- /dev/null +++ b/src/input/detail/policyChain.h @@ -0,0 +1,78 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # detail/policyChain.h: + # - Tie together the different bits of policy information a handler may + # give us + # -------------------------------------------------------------------------- + */ + +#ifndef POLICYCHAIN_H_ +#define POLICYCHAIN_H_ + +#include "typeList.h" + +namespace input_policy +{ +namespace detail +{ + +template<typename BaseCase, typename PolicyList> +struct PolicyChain : public PolicyList::head::template apply_<PolicyChain<BaseCase, typename PolicyList::tail> > +{ +}; + +template<typename BaseCase> +struct PolicyChain<BaseCase, EmptyList> : public BaseCase +{ +private: + struct This_Should_Not_Work; +public: + static const int test_value = sizeof(This_Should_Not_Work); +}; + +} +} + +///////////////////////////////////////////////////////////////////////// +// Macros that enable specification of policies: +// A policy is declared like this: +// template< PARAM1, PARAM2, ... > +// BEGIN_POLICY_CLASS(MyPolicy) { +// static const int field1 = 2; +// ... +// } END_POLICY_CLASS(MyPolicy); +///////////////////////////////////////////////////////////////////////// +#define BEGIN_POLICY_CLASS(policyName) \ + struct policyName { \ + template<typename NextPolicy> \ + struct apply_ : public NextPolicy +#define END_POLICY_CLASS \ + ; }; + +///////////////////////////////////////////////////////////////////////// +// A macro that enables us to use a template parameter list +// in a class using a policy, like this: +// +// template<POLICY_PARAMS> +// struct MyPolicyBasedClass +// { +// typedef USE_POLICY(baseCase) policy_type; +// }; +// +// now, the following type is valid: +// MyPolicyBasedClass<Policy1, Policy2> +///////////////////////////////////////////////////////////////////////// +#define POLICY_PARAMS IMPLICIT_TYPE_LIST_PARAMS(Policy) +#define POLICY_PARAMS_LIST IMPLICIT_TYPE_LIST(Policy) +#define USE_POLICY(baseCase) ::input_policy::detail::PolicyChain<baseCase, POLICY_PARAMS_LIST> + +#endif /* POLICYCHAIN_H_ */ diff --git a/src/input/detail/policyChain_autogen.h b/src/input/detail/policyChain_autogen.h new file mode 100644 index 0000000..d9503b8 --- /dev/null +++ b/src/input/detail/policyChain_autogen.h @@ -0,0 +1,8 @@ +template<typename BaseCase, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7> +struct PolicyChain : +public P0::template apply_<PolicyChain<BaseCase, P1, P2, P3, P4, P5, P6, P7, void> > +{}; +template<typename BaseCase> +struct PolicyChain<BaseCase, void, void, void, void, void, void, void, void> : public BaseCase {}; +#define _autogen_POLICY_TEMPLATE_PARAMS typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7 +#define _autogen_POLICY_TEMPLATE_ARGS P0, P1, P2, P3, P4, P5, P6, P7 diff --git a/src/input/detail/systemTraits.h b/src/input/detail/systemTraits.h new file mode 100644 index 0000000..7f5582f --- /dev/null +++ b/src/input/detail/systemTraits.h @@ -0,0 +1,94 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # detail/systemTraits.h: + # - Define system traits and provide a way to match against them + # -------------------------------------------------------------------------- + */ + +#ifndef SYSTEMTRAITS_H_ +#define SYSTEMTRAITS_H_ + +#include "typeList.h" + +#define DEFINE_SYSTEM_TRAIT(name) struct name; +#define BEGIN_SYSTEM_TRAITS typedef TypeList< +#define END_SYSTEM_TRAITS > SystemTraits; + +namespace input_policy +{ + +// Trait names are externally visible. +DEFINE_SYSTEM_TRAIT(UnixLike) +DEFINE_SYSTEM_TRAIT(LinuxSystem) +DEFINE_SYSTEM_TRAIT(X11GUI) +DEFINE_SYSTEM_TRAIT(ConsoleKitSupported) + +namespace detail +{ +BEGIN_SYSTEM_TRAITS +#ifdef __linux +UnixLike, +LinuxSystem, +X11GUI, +ConsoleKitSupported +#endif +END_SYSTEM_TRAITS +} + +///////////////////////////////////////////////////////////////////////// +// Boolean logic as applied to system traits +///////////////////////////////////////////////////////////////////////// +template<IMPLICIT_TYPE_LIST_PARAMS(T)> +struct AllOf; + +template<IMPLICIT_TYPE_LIST_PARAMS(T)> +struct AnyOf; + +namespace detail +{ +///////////////////////////////////////////////////////////////////////// +// Does the list of system traits match what we have given? +///////////////////////////////////////////////////////////////////////// +template<typename Needles, typename Haystack> +struct Matches +{ + // if Needles is neither AnyOf<...> nor AllOf<...> + // then we need to know if the Haystack contains it: + static const bool value = Contains<Needles, Haystack>::value; +}; + +template<typename Haystack> +struct MatchesPredicate +{ + template<typename Needle> + struct apply + { + static const bool value = Matches<Needle, Haystack>::value; + }; +}; + +template<IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(T), typename Haystack> +struct Matches<AnyOf<IMPLICIT_TYPE_LIST_ARGS(T)>, Haystack> +{ + static const bool value = ForAnyInTypeList<MatchesPredicate<Haystack>, IMPLICIT_TYPE_LIST(T)>::value; +}; + +template<IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(T), typename Haystack> +struct Matches<AllOf<IMPLICIT_TYPE_LIST_ARGS(T)>, Haystack> +{ + static const bool value = ForAllInTypeList<MatchesPredicate<Haystack>, IMPLICIT_TYPE_LIST(T)>::value; +}; +} + +} + +#endif /* SYSTEMTRAITS_H_ */ diff --git a/src/input/detail/typeList.h b/src/input/detail/typeList.h new file mode 100644 index 0000000..5b915a9 --- /dev/null +++ b/src/input/detail/typeList.h @@ -0,0 +1,76 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # detail/typeList.h: + # - Compile-time metaprogramming facilities: Type Lists and Member Check + # -------------------------------------------------------------------------- + */ + +#ifndef TYPELIST_H_ +#define TYPELIST_H_ + +namespace input_policy +{ +namespace detail +{ + +///////////////////////////////////////////////////////////////////////// +// TypeList, Contains, EmptyList: +// This class is autogenerated by gen/gen_typeList.cpp +///////////////////////////////////////////////////////////////////////// +#include "typeList_autogen.h" + +///////////////////////////////////////////////////////////////////////// +// Type-level functions that do not need to be autogenerated as they +// do not depend on the maximum number of entries: +// +// ForAnyInTypeList<Predicate, List>::value == true +// if there is any entry E in List for which +// Predicate::apply<E>::value == true +///////////////////////////////////////////////////////////////////////// +template<typename Predicate, typename List> +struct ForAnyInTypeList +{ + static const bool value = + Predicate::template apply<typename List::head>::value || + ForAnyInTypeList<Predicate, typename List::tail>::value; +}; + +template<typename Predicate> +struct ForAnyInTypeList<Predicate, EmptyList> +{ + static const bool value = false; +}; + +///////////////////////////////////////////////////////////////////////// +// ForAllInTypeList<Predicate, List>::value == true +// if there is not any entry E in List for which +// Predicate::apply<E>::value == false +///////////////////////////////////////////////////////////////////////// +template<typename Predicate, typename List> +struct ForAllInTypeList +{ + static const bool value = + Predicate::template apply<typename List::head>::value && + ForAllInTypeList<Predicate, typename List::tail>::value; +}; + +template<typename Predicate> +struct ForAllInTypeList<Predicate, EmptyList> +{ + static const bool value = true; +}; + +} + +} + +#endif /* TYPELIST_H_ */ diff --git a/src/input/detail/typeList_autogen.h b/src/input/detail/typeList_autogen.h new file mode 100644 index 0000000..0f8fdd4 --- /dev/null +++ b/src/input/detail/typeList_autogen.h @@ -0,0 +1,60 @@ +template<typename T0 = void, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void, typename T13 = void, typename T14 = void, typename T15 = void> +struct TypeList { +typedef T0 head; +typedef TypeList<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void > tail; +}; +template<typename Needle, typename Haystack> +struct Contains { static const int index = -1; static const bool value = false; }; +template<typename Needle, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<Needle, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> > +{ static const int index = 0; static const bool value = true; }; +template<typename Needle, typename T0, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, Needle, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> > +{ static const int index = 1; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, Needle, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> > +{ static const int index = 2; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, Needle, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> > +{ static const int index = 3; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, Needle, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> > +{ static const int index = 4; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, Needle, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> > +{ static const int index = 5; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, Needle, T7, T8, T9, T10, T11, T12, T13, T14, T15> > +{ static const int index = 6; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, Needle, T8, T9, T10, T11, T12, T13, T14, T15> > +{ static const int index = 7; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, Needle, T9, T10, T11, T12, T13, T14, T15> > +{ static const int index = 8; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, Needle, T10, T11, T12, T13, T14, T15> > +{ static const int index = 9; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T11, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Needle, T11, T12, T13, T14, T15> > +{ static const int index = 10; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T12, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, Needle, T12, T13, T14, T15> > +{ static const int index = 11; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T13, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, Needle, T13, T14, T15> > +{ static const int index = 12; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T14, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, Needle, T14, T15> > +{ static const int index = 13; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T15> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, Needle, T15> > +{ static const int index = 14; static const bool value = true; }; +template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14> +struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, Needle> > +{ static const int index = 15; static const bool value = true; }; +typedef TypeList<void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void > EmptyList; +#define IMPLICIT_TYPE_LIST_PARAMS(prefix) typename prefix##0 = void, typename prefix##1 = void, typename prefix##2 = void, typename prefix##3 = void, typename prefix##4 = void, typename prefix##5 = void, typename prefix##6 = void, typename prefix##7 = void, typename prefix##8 = void, typename prefix##9 = void, typename prefix##10 = void, typename prefix##11 = void, typename prefix##12 = void, typename prefix##13 = void, typename prefix##14 = void, typename prefix##15 = void +#define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) typename prefix##0, typename prefix##1, typename prefix##2, typename prefix##3, typename prefix##4, typename prefix##5, typename prefix##6, typename prefix##7, typename prefix##8, typename prefix##9, typename prefix##10, typename prefix##11, typename prefix##12, typename prefix##13, typename prefix##14, typename prefix##15 +#define IMPLICIT_TYPE_LIST_ARGS(prefix) prefix##0, prefix##1, prefix##2, prefix##3, prefix##4, prefix##5, prefix##6, prefix##7, prefix##8, prefix##9, prefix##10, prefix##11, prefix##12, prefix##13, prefix##14, prefix##15 +#define IMPLICIT_TYPE_LIST(prefix) ::input_policy::detail::TypeList<IMPLICIT_TYPE_LIST_ARGS(prefix) > |
