/** \file * Implementation of Lists of types. * Type lists are rather integral to the operation of Comet, and provide us * with many of the mechanisms that allow us to all but remove the need for * \#define macros in code. */ /* * Copyright © 2000-2002 Sofus Mortensen, Michael Geddes * * This material is provided "as is", with absolutely no warranty * expressed or implied. Any use is at your own risk. Permission to * use or copy this software for any purpose is hereby granted without * fee, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is * granted, provided the above notices are retained, and a notice that * the code was modified is included with the above copyright notice. * * This header is part of Comet version 2. * https://github.com/alamaison/comet */ #ifndef COMET_TYPELIST_H #define COMET_TYPELIST_H #include namespace comet { /** \struct nil typelist.h comet/typelist.h * End of list type. */ struct nil {}; template struct tl_t { typedef T head; typedef U tail; }; #ifndef COMET_TL_TRUNC #ifndef __BORLANDC__ #define COMET_TL_LIST( X01,X02,X03,X04,X05,X06,X07,X08,X09, \ X10,X11,X12,X13,X14,X15,X16,X17,X18,X19, \ X20,X21,X22,X23,X24,X25,X26,X27,X28,X29, \ X30,X31,X32,X33,X34,X35,X36,X37,X38,X39) \ X01,X02,X03,X04,X05,X06,X07,X08,X09, \ X10,X11,X12,X13,X14,X15,X16,X17,X18,X19, \ X20,X21,X22,X23,X24,X25,X26,X27,X28,X29, \ X30,X31,X32,X33,X34,X35,X36,X37,X38,X39 #else #define COMET_TL_LIST( X01,X02,X03,X04,X05,X06,X07,X08,X09, \ X10,X11,X12,X13,X14,X15,X16,X17,X18,X19, \ X20,X21,X22,X23,X24,X25,X26,X27,X28,X29, \ X30,X31,X32,X33,X34,X35,X36,X37,X38,X39) \ X01,X02,X03,X04,X05,X06,X07,X08,X09, \ X10,X11,X12,X13,X14,X15,X16,X17,X18,X19, \ X20,X21,X22,X23,X24,X25,X26,X27,X28,X29 #endif #else #define COMET_TL_LIST( X01,X02,X03,X04,X05,X06,X07,X08,X09, \ X10,X11,X12,X13,X14,X15,X16,X17,X18,X19, \ X20,X21,X22,X23,X24,X25,X26,X27,X28,X29, \ X30,X31,X32,X33,X34,X35,X36,X37,X38,X39) \ X01,X02,X03,X04,X05,X06,X07,X08,X09,X10 #endif #define COMET_LIST_TEMPLATE \ typename X00=comet::nil, COMET_TL_LIST( typename X01=comet::nil, typename X02=comet::nil, typename X03=comet::nil, typename X04=comet::nil, \ typename X05=comet::nil, typename X06=comet::nil, typename X07=comet::nil, typename X08=comet::nil, typename X09=comet::nil, \ typename X10=comet::nil, typename X11=comet::nil, typename X12=comet::nil, typename X13=comet::nil, typename X14=comet::nil, \ typename X15=comet::nil, typename X16=comet::nil, typename X17=comet::nil, typename X18=comet::nil, typename X19=comet::nil, \ typename X20=comet::nil, typename X21=comet::nil, typename X22=comet::nil, typename X23=comet::nil, typename X24=comet::nil, \ typename X25=comet::nil, typename X26=comet::nil, typename X27=comet::nil, typename X28=comet::nil, typename X29=comet::nil, \ typename X30=comet::nil, typename X31=comet::nil, typename X32=comet::nil, typename X33=comet::nil, typename X34=comet::nil, \ typename X35=comet::nil, typename X36=comet::nil, typename X37=comet::nil, typename X38=comet::nil, typename X39=comet::nil) #define COMET_LIST_TEMPLATE_0 typename X00, COMET_TL_LIST(\ typename X01, typename X02, typename X03, typename X04, \ typename X05, typename X06, typename X07, typename X08, typename X09, \ typename X10, typename X11, typename X12, typename X13, typename X14, \ typename X15, typename X16, typename X17, typename X18, typename X19, \ typename X20, typename X21, typename X22, typename X23, typename X24, \ typename X25, typename X26, typename X27, typename X28, typename X29, \ typename X30, typename X31, typename X32, typename X33, typename X34, \ typename X35, typename X36, typename X37, typename X38, typename X39) #define COMET_LIST_ARG_1 X00, COMET_TL_LIST(\ X01,X02,X03,X04,X05,X06,X07,X08,X09, \ X10,X11,X12,X13,X14,X15,X16,X17,X18,X19, \ X20,X21,X22,X23,X24,X25,X26,X27,X28,X29, \ X30,X31,X32,X33,X34,X35,X36,X37,X38,X39) #define COMET_LIST_ARG_0 COMET_TL_LIST(\ X01,X02,X03,X04,X05,X06,X07,X08,X09, \ X10,X11,X12,X13,X14,X15,X16,X17,X18,X19, \ X20,X21,X22,X23,X24,X25,X26,X27,X28,X29, \ X30,X31,X32,X33,X34,X35,X36,X37,X38,X39) #define COMET_LIST_NIL comet::nil, COMET_TL_LIST(\ comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil, \ comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil, \ comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil, \ comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil,comet::nil) /** \struct make_list typelist.h comet/typelist.h * Construct a 'type list' of up to 40 types. * A list is a 'head-tail' list terminated by a 'nil' tail struct. * It is most easily constructe by using make_list: \code comet::make_list< FooType,BarType>::result \endcode * The \e concept of a type-list is that it is either \link comet::nil nil \endlink * or a struct containing a \e typedef of \p head to the first element in the * list and a typedef of \p tail to a type-list that contains the rest of * the list. * * This means that for a type-list \e LST * \code LST::head \endcode * is the first element in the list (assuming it is not * \link comet::nil nil \endlink) and * \code LST::head::tail::head \endcode would be the second element in the list (assuming LST::head::tail is not \link comet::nil nil \endlink), and so on. * Two type lists can be appended together with typelist::append. \sa typelist::append */ template struct make_list { typedef tl_t::result> result; }; template<> struct make_list { typedef nil result; }; namespace typelist { template struct length { enum { value = 1 + length< typename L::tail>::value }; }; template<> struct length { enum { value = 0 }; }; #ifdef COMET_PARTIAL_SPECIALISATION //! Find the type at the specified index. /** \param L Type List * \param idx Index */ template struct type_at { typedef typename type_at::result result; }; template struct type_at { typedef typename L::head result; }; template< unsigned idx> struct type_at { typedef nil result; }; template<> struct type_at { typedef nil result; }; /** \internal */ template struct index_of_aux { enum { value = 1+(index_of_aux::value) }; }; template< typename L, typename T> struct index_of_aux { enum { value = 0 }; }; /** Find the index of the type \a T in the type-list \a L. * The result is in index_of::value. */ template struct index_of { enum { value = index_of_aux::value }; }; #else template struct type_at; template struct type_at_aux { template struct X { typedef typename type_at::result result; // typedef type_at_aux::X::result result; }; template<> struct X<0> { typedef typename L::head result; }; }; template<> struct type_at_aux { template struct X { typedef nil result; }; }; /* template<> struct type_at_aux< make_list<> > { template struct X { typedef nil result; }; };*/ template struct type_at { typedef typename type_at_aux::X::result result; }; template struct index_of; template struct index_of_aux { template struct X1 { template struct X2 { enum { value = 1 + index_of::value }; }; template<> struct X2 { enum { value = 0 }; }; }; }; template struct index_of { enum { value = index_of_aux::X1::X2::value }; }; #endif // COMET_PARTIAL_SPECIALISATION #undef COMET_LIST_ARG #ifdef COMET_PARTIAL_SPECIALISATION /** \struct append typelist.h comet/typelist.h * Appends two type-lists together. * Example: * \code comet::typelist::append< comet::make_list< Type1, Type2 >::result, comet::make_list< Type3, Type4 >::result > \endcode \sa make_list */ template struct append { typedef typename L1::head head; typedef append tail; }; template struct append { typedef typename L2::head head; typedef typename L2::tail tail; }; template struct append,L2> { typedef typename L2::head head; typedef typename L2::tail tail; }; template<> struct append { typedef nil head; typedef nil tail; }; template struct append_element { typedef typename append::result>::head head; typedef typename append::result>::tail tail; }; #else // COMET_PARTIAL_SPECIALISATION template struct append; namespace impl { template struct append_aux { template struct with { typedef typename L1::head head; typedef typename append tail; // typedef typename append_aux::with tail; }; template<> struct with { typedef typename L1::head head; typedef typename L1::tail tail; }; }; template<> struct append_aux { template struct with { typedef typename L2::head head; typedef typename L2::tail tail; }; }; /* template<> struct append_aux > { template struct with { typedef typename L2::head head; typedef typename L2::tail tail; }; };*/ } template struct append { typedef typename impl::append_aux::with::head head; typedef typename impl::append_aux::with::tail tail; }; template struct append_element { typedef typename impl::append_aux::with< typename make_list::result >::head head; typedef typename impl::append_aux::with< typename make_list::result >::tail tail; }; #endif // COMET_PARTIAL_SPECIALISATION #ifdef COMET_NESTED_TEMPLATES /** \struct wrap_each typelist.h comet/typelist.h * Wrap each of the elements of a list in the specified template class. * Due to lack of support for template parameter to templates by Microsoft, * macros have been defined as a necessary evil to get arround this. * The macros are #COMET_WRAP_EACH_DECLARE and #COMET_WRAP_EACH. * There is a propper implementation for compilers that support nested * interfaces, which will be selected by the macro as appropriate. * \sa COMET_WRAP_EACH_DECLARE COMET_WRAP_EACH */ template< template< typename > class T, typename L1> struct wrap_each; namespace impl { template< template< typename > class T, typename L1> struct wrap_each_aux { typedef wrap_each x; }; template< template< typename > class T> struct wrap_each_aux< T, nil> { typedef nil x; }; } template< template< typename > class T, typename L1> struct wrap_each { typedef T head; typedef typename impl::wrap_each_aux::x tail; }; template< template< typename > class T> struct wrap_each< T, ::comet::nil > { }; /** \def COMET_WRAP_EACH_DECLARE(T) * Declare a template for wrapping each element in the specified type. * \relates wrap_each */ #define COMET_WRAP_EACH_DECLARE(T) // MSVC7.1 doesn't like this: // template< template< typename > class T1, typename L1> struct wrap_each; /** \def COMET_WRAP_EACH(T, L1) * Produce a list L2 that consists of each member of list L1 wrapped in type T. * This is very much a Lambda calculus concept for those who care. * \relates wrap_each */ #define COMET_WRAP_EACH(T, L1) typelist::wrap_each #else // COMET_NESTED_TEMPLATES #define COMET_WRAP_EACH_DECLARE(T) \ template< typename L1 > struct wrap_each_aux##T; \ namespace impl \ { \ template< typename L1> struct p_wrap_each_aux##T \ { \ typedef wrap_each_aux##T x; \ }; \ template<> struct p_wrap_each_aux##T < ::comet::nil> \ { \ typedef ::comet::nil x; \ }; \ }; \ template< typename L1> struct wrap_each_aux##T \ { \ typedef T head; \ typedef typename impl::p_wrap_each_aux##T < typename L1::tail>::x tail;\ }; \ template<> struct wrap_each_aux##T< ::comet::nil> { }; #define COMET_WRAP_EACH(T, L1) wrap_each_aux##T #endif // COMET_NESTED_TEMPLATES template struct ATL_NO_VTABLE inherit_all : public ITF_LIST::head, public inherit_all {}; template<> struct inherit_all {}; // template<> struct inherit_all > {}; } /* MSVC7 chokes on this one - not actually used anywhere template struct select { typedef typelist::type_at< make_list::result, idx>::result result; };*/ } // namespace #endif