1 // typelist.hpp 2 // 3 // Copyright (c) 2003 Eugene Gladyshev 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 11 #ifndef __ttl_typelist__hpp 12 #define __ttl_typelist__hpp 13 14 #include "settings/extern/ttl/config.hpp" 15 #include "settings/extern/ttl/data_holder.hpp" 16 #include "settings/extern/ttl/exception.hpp" 17 #include "settings/extern/ttl/macro_params.hpp" 18 #include "settings/extern/ttl/equivalent_types.hpp" 19 #include "settings/extern/ttl/meta/is_same.hpp" 20 #include "settings/extern/ttl/selector.hpp" 21 22 23 namespace ttl 24 { 25 namespace meta 26 { 27 struct exception : ttl::exception 28 { exceptionttl::meta::exception29 exception() : ttl::exception("typelist error") {} 30 }; 31 //internal implementation 32 namespace impl 33 { 34 //////////////////////////////////////////////////////////// 35 template< TTL_TPARAMS_DEF(TTL_MAX_TYPELIST_PARAMS, empty_type) > 36 struct typelist_traits 37 { 38 typedef typelist_traits< TTL_ARGS_S(TTL_DEC(TTL_MAX_TYPELIST_PARAMS)) > tail; 39 40 enum 41 { 42 length = 1 + tail::length 43 }; 44 45 typedef typename selector< sizeof(ttl::data_holder<T1>) >=sizeof(ttl::data_holder<typename tail::largest_type>), 46 T1, 47 typename tail::largest_type 48 >::type largest_type; 49 }; 50 51 template<> 52 struct typelist_traits< TTL_LIST_ITEMS(TTL_MAX_TYPELIST_PARAMS,empty_type) > 53 { 54 typedef empty_type tail; 55 enum 56 { 57 length = 0 58 }; 59 typedef empty_type largest_type; 60 }; 61 62 //////////////////////////////////////////////////////////// 63 // 64 //Instantiate TTL_MAX_TYPELIST_PARAMS get<> templates 65 // template<typename T> struct get<T, 0> 66 // { 67 // enum { index = 0 }; 68 // typedef typename T::type1 type; 69 // }; 70 // 71 // template<typename T> struct get<T, 1> 72 // { 73 // enum { index = 1 }; 74 // typedef typename T::type2 type; 75 // }; 76 // ... 77 // 78 79 template< typename T, int N > struct get; 80 #define TTL_META_TYPELIST_GET(n, t) template<typename T> struct get<T, TTL_CNTDEC_##n> \ 81 { enum {index = n-1}; typedef typename T::t##n type; }; 82 83 TTL_REPEAT( TTL_MAX_TYPELIST_PARAMS, TTL_META_TYPELIST_GET, TTL_META_TYPELIST_GET, type ) 84 85 #undef TTL_META_TYPELIST_GET 86 } 87 88 template < TTL_TPARAMS_DEF(TTL_MAX_TYPELIST_PARAMS, empty_type) > 89 struct typelist 90 { 91 TTL_TYPEDEFS(TTL_MAX_TYPELIST_PARAMS) 92 93 typedef impl::typelist_traits< TTL_ARGS(TTL_MAX_TYPELIST_PARAMS) > list_traits; 94 95 enum{ length = list_traits::length }; 96 typedef typename list_traits::largest_type largest_type; 97 }; 98 99 //////////////////////////////////////////////////////////// 100 template < typename L > 101 struct length 102 { 103 enum { value = L::length }; 104 }; 105 106 /////////////////////////////////////////////////////////// 107 template< typename L, int N, bool Ok = (N < length<L>::value) > 108 struct get 109 { 110 typedef typename impl::get<L,N>::type type; 111 enum{ index = N }; 112 }; 113 114 template< typename L, int N > 115 struct get<L,N,false> 116 { 117 //index is out of range 118 }; 119 120 //////////////////////////////////////////////////////////// 121 // run-time type switch 122 template <typename L, int N = 0, bool Stop=(N==length<L>::value) > struct type_switch; 123 124 template <typename L, int N, bool Stop> 125 struct type_switch 126 { 127 template< typename F > operator ()ttl::meta::type_switch128 void operator()( size_t i, F& f ) 129 { 130 if( i == N ) 131 { 132 // Edited(BM) 07/05/16 added the 'template' 133 // f.operator()<typename impl::get<L,N>::type>(); 134 f.template operator()<typename impl::get<L,N>::type>(); 135 } 136 else 137 { 138 type_switch<L, N+1> next; 139 next(i, f); 140 } 141 } 142 }; 143 144 template <typename L, int N> 145 struct type_switch<L, N, true> 146 { 147 template< typename F > operator ()ttl::meta::type_switch148 void operator()( size_t /*i*/, F& /*f*/ ) 149 { 150 throw meta::exception(); 151 } 152 }; 153 154 155 ////////////////////////////////////////////////////////////// 156 template< typename T, typename L, int N = 0, bool Stop=(N>=length<L>::value) > 157 struct find_equivalent_type 158 { 159 private: 160 typedef impl::get<L,N> get_type; 161 162 typedef typename selector< equivalent_types<typename get_type::type, T>::value, 163 get_type, 164 find_equivalent_type<T,L,N+1> 165 >::type found; 166 167 public: 168 typedef typename found::type type; 169 enum {index = found::index}; 170 }; 171 172 template<typename T, typename L, int N> 173 struct find_equivalent_type<T, L, N, true> 174 { 175 }; 176 177 178 ////////////////////////////////////////////// 179 template< typename T, typename L, int N = 0, bool Stop=(N>=length<L>::value) > 180 struct find 181 { 182 private: 183 typedef impl::get<L,N> get_type; 184 185 typedef typename selector< is_same<typename get_type::type, T>::value, 186 get_type, 187 find<T,L,N+1> 188 >::type found; 189 190 public: 191 typedef typename found::type type; 192 enum {index = found::index}; 193 }; 194 195 template<typename T, typename L, int N> 196 struct find<T, L, N, true> 197 { 198 }; 199 200 } 201 } 202 203 #endif //__typelist__hpp 204