ViennaGrid - The Vienna Grid Library
2.1.0
|
00001 #ifndef VIENNAGRID_META_TYPELIST_HPP 00002 #define VIENNAGRID_META_TYPELIST_HPP 00003 00004 /* ======================================================================= 00005 Copyright (c) 2011-2014, Institute for Microelectronics, 00006 Institute for Analysis and Scientific Computing, 00007 TU Wien. 00008 00009 ----------------- 00010 ViennaGrid - The Vienna Grid Library 00011 ----------------- 00012 00013 License: MIT (X11), see file LICENSE in the base directory 00014 ======================================================================= */ 00015 00016 #include "viennagrid/meta/utils.hpp" 00017 00022 namespace viennagrid 00023 { 00025 template <class HeadT, class TailT> 00026 struct typelist 00027 { 00028 typedef HeadT head; 00029 typedef TailT tail; 00030 }; 00031 00032 00033 // C++11 version 00034 00035 // template<typename ... types> 00036 // struct make_typelist; 00037 // 00038 // template<> 00039 // struct make_typelist<> 00040 // { 00041 // typedef viennagrid::null_type type; 00042 // }; 00043 // 00044 // template<typename head, typename ... tail> 00045 // struct make_typelist<head, tail...> 00046 // { 00047 // typedef viennagrid::typelist<head, typename make_typelist<tail...>::type> type; 00048 // }; 00049 00050 00051 00052 00054 template< typename T01 = viennagrid::null_type, typename T02 = viennagrid::null_type, typename T03 = viennagrid::null_type, typename T04 = viennagrid::null_type, 00055 typename T05 = viennagrid::null_type, typename T06 = viennagrid::null_type, typename T07 = viennagrid::null_type, typename T08 = viennagrid::null_type, 00056 typename T09 = viennagrid::null_type, typename T10 = viennagrid::null_type, typename T11 = viennagrid::null_type, typename T12 = viennagrid::null_type, 00057 typename T13 = viennagrid::null_type, typename T14 = viennagrid::null_type, typename T15 = viennagrid::null_type, typename T16 = viennagrid::null_type, 00058 typename T17 = viennagrid::null_type, typename T18 = viennagrid::null_type, typename T19 = viennagrid::null_type, typename T20 = viennagrid::null_type > 00059 struct make_typelist 00060 { 00061 typedef 00062 typelist< 00063 T01, 00064 typename make_typelist<T02, T03, T04, T05, T06, T07, T08, T09, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20>::type 00065 > type; 00066 }; 00067 00069 template<> 00070 struct make_typelist< 00071 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00072 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00073 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00074 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00075 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type> 00076 { 00077 typedef viennagrid::null_type type; 00078 }; 00082 namespace detail 00083 { 00084 00085 namespace result_of 00086 { 00087 00088 // size of a typelist 00089 template <typename typelist> struct size; 00090 00091 template <> struct size<null_type> 00092 { 00093 static const int value = 0; 00094 }; 00095 00096 template <typename head, typename tail> 00097 struct size< typelist<head, tail> > 00098 { 00099 static const int value = 1 + size<tail>::value; 00100 }; 00101 00102 00103 // index access 00104 template <typename typelist, int index> 00105 struct at 00106 { 00107 typedef out_of_range type; 00108 }; 00109 00110 template <typename head, typename tail> 00111 struct at<typelist<head, tail>, 0> 00112 { 00113 typedef head type; 00114 }; 00115 00116 template <typename head, typename tail, int i> 00117 struct at<typelist<head, tail>, i> 00118 { 00119 typedef typename at<tail, i - 1>::type type; 00120 }; 00121 00122 00123 00124 // returns the index of the first type in the typelist 00125 template <typename typelist, typename to_find> struct index_of; 00126 00127 template <typename to_find> 00128 struct index_of<null_type, to_find> 00129 { 00130 static const int value = -1; 00131 }; 00132 00133 template <typename to_find, typename tail> 00134 struct index_of<typelist<to_find, tail>, to_find> 00135 { 00136 static const int value = 0; 00137 }; 00138 00139 template <typename head, typename tail, typename to_find> 00140 struct index_of<typelist<head, tail>, to_find> 00141 { 00142 private: 00143 static const int temp = index_of<tail, to_find>::value; 00144 public: 00145 static const int value = (temp == -1 ? -1 : 1 + temp); 00146 }; 00147 00148 00149 00150 // push back a single type 00151 template <typename typelist, typename to_add> struct push_back; 00152 00153 template <> 00154 struct push_back<null_type, null_type> 00155 { 00156 typedef null_type type; 00157 }; 00158 00159 template <typename to_add> 00160 struct push_back<null_type, to_add> 00161 { 00162 typedef typelist<to_add, null_type> type; 00163 }; 00164 00165 template <typename head, typename tail, typename to_add> 00166 struct push_back<typelist<head, tail>, to_add> 00167 { 00168 typedef typelist<head, typename push_back<tail, to_add>::type> type; 00169 }; 00170 00171 00172 00173 // push back list 00174 template <typename typelist, typename typelisto_add> struct push_back_list; 00175 00176 template <> 00177 struct push_back_list<null_type, null_type> 00178 { 00179 typedef null_type type; 00180 }; 00181 00182 template <typename head, typename tail> 00183 struct push_back_list<null_type, typelist<head, tail> > 00184 { 00185 typedef typelist<head, tail> type; 00186 }; 00187 00188 template <typename head, typename tail> 00189 struct push_back_list<typelist<head, tail>, null_type > 00190 { 00191 typedef typelist<head, tail> type; 00192 }; 00193 00194 template <typename head1, typename tail1, typename head2, typename tail2> 00195 struct push_back_list<typelist<head1, tail1>, typelist<head2, tail2> > 00196 { 00197 typedef typename push_back_list< typename push_back< typelist<head1, tail1>, head2>::type, tail2 >::type type; 00198 }; 00199 00200 00201 00202 // erase_at the type at index 00203 template <typename typelist, int index_to_erase> 00204 struct erase_at; 00205 00206 template <int index_to_erase> 00207 struct erase_at<null_type, index_to_erase> 00208 { 00209 typedef null_type type; 00210 }; 00211 00212 template <typename head, typename tail> 00213 struct erase_at< typelist<head, tail>, 0> 00214 { 00215 typedef tail type; 00216 }; 00217 00218 template <typename head, typename tail, int index_to_erase> 00219 struct erase_at< typelist<head, tail>, index_to_erase> 00220 { 00221 typedef typelist<head, typename erase_at<tail, index_to_erase-1>::type> type; 00222 }; 00223 00224 00225 00226 // erase the first type 00227 template <typename typelist, typename to_erase> struct erase; 00228 00229 template <typename to_erase> 00230 struct erase<null_type, to_erase> 00231 { 00232 typedef null_type type; 00233 }; 00234 00235 template <typename to_erase, typename tail> 00236 struct erase< typelist<to_erase, tail>, to_erase> 00237 { 00238 typedef tail type; 00239 }; 00240 00241 template <typename head, typename tail, typename to_erase> 00242 struct erase< typelist<head, tail>, to_erase> 00243 { 00244 typedef typelist<head, typename erase<tail, to_erase>::type> type; 00245 }; 00246 00247 00248 // erase all types 00249 template <typename typelist, typename to_erase> 00250 struct erase_all; 00251 00252 template <typename to_erase> 00253 struct erase_all<null_type, to_erase> 00254 { 00255 typedef null_type type; 00256 }; 00257 00258 template <typename to_erase, typename tail> 00259 struct erase_all< typelist<to_erase, tail>, to_erase> 00260 { 00261 // Go all the way down the list removing the type 00262 typedef typename erase_all<tail, to_erase>::type type; 00263 }; 00264 template <typename head, typename tail, typename to_erase> 00265 00266 struct erase_all< typelist<head, tail>, to_erase> 00267 { 00268 // Go all the way down the list removing the type 00269 typedef typelist<head, typename erase_all<tail, to_erase>::type> type; 00270 }; 00271 00272 00273 00274 // reverse 00275 template <typename typelist> struct reverse; 00276 00277 template <> struct 00278 reverse<null_type> 00279 { 00280 typedef null_type type; 00281 }; 00282 00283 template <typename head, typename tail> 00284 struct reverse< typelist<head, tail> > 00285 { 00286 typedef typelist<head, tail> t_list; 00287 public: 00288 00289 typedef typelist< 00290 typename at< 00291 t_list, 00292 size<t_list>::value-1 00293 >::type, 00294 typename reverse< 00295 typename erase_at< 00296 t_list, 00297 size<t_list>::value-1 00298 >::type 00299 >::type 00300 > type; 00301 }; 00302 00303 00304 00305 // no duplicate types 00306 template <typename typelist> struct no_duplicates; 00307 00308 template <> struct 00309 no_duplicates<null_type> 00310 { 00311 typedef null_type type; 00312 }; 00313 00314 template <typename head, typename tail> 00315 struct no_duplicates< typelist<head, tail> > 00316 { 00317 private: 00318 typedef typename no_duplicates<tail>::type L1; 00319 typedef typename erase<L1, head>::type L2; 00320 public: 00321 typedef typelist<head, L2> type; 00322 }; 00323 00324 00325 // replace the type at index by another type 00326 template <typename typelist, int index_to_replace, typename replaced> struct replace_at; 00327 00328 template <typename replaced> 00329 struct replace_at<null_type, -1, replaced> 00330 { 00331 typedef null_type type; 00332 }; 00333 00334 template <typename head, typename tail, typename replaced> 00335 struct replace_at<typelist<head, tail>, -1, replaced> 00336 { 00337 typedef null_type type; 00338 }; 00339 00340 template <int index_to_replace, typename replaced> 00341 struct replace_at<null_type, index_to_replace, replaced> 00342 { 00343 typedef null_type type; 00344 }; 00345 00346 template <typename head, typename tail, typename replaced> 00347 struct replace_at<typelist<head, tail>, 0, replaced> 00348 { 00349 typedef typelist<replaced, tail> type; 00350 }; 00351 00352 template <typename head, typename tail, int index_to_replace, typename replaced> 00353 struct replace_at<typelist<head, tail>, index_to_replace, replaced> 00354 { 00355 typedef typelist<head, typename replace_at<tail, index_to_replace-1, replaced>::type> type; 00356 }; 00357 00358 // replace the first type by another type 00359 template <typename typelist, typename to_replace, typename replaced> struct replace; 00360 00361 template <typename to_replace, typename replaced> 00362 struct replace<null_type, to_replace, replaced> 00363 { 00364 typedef null_type type; 00365 }; 00366 00367 template <typename to_replace, typename tail, typename replaced> 00368 struct replace<typelist<to_replace, tail>, to_replace, replaced> 00369 { 00370 typedef typelist<replaced, tail> type; 00371 }; 00372 00373 template <typename head, typename tail, typename to_replace, typename replaced> 00374 struct replace<typelist<head, tail>, to_replace, replaced> 00375 { 00376 typedef typelist<head, typename replace<tail, to_replace, replaced>::type> type; 00377 }; 00378 00379 00380 // replace all types by another type 00381 template <typename typelist, typename to_replace, typename replaced> struct replace_all; 00382 00383 template <typename to_replace, typename replaced> 00384 struct replace_all<null_type, to_replace, replaced> 00385 { 00386 typedef null_type type; 00387 }; 00388 00389 template <typename to_replace, typename tail, typename replaced> 00390 struct replace_all<typelist<to_replace, tail>, to_replace, replaced> 00391 { 00392 typedef typelist<replaced, typename replace_all<tail, to_replace, replaced>::type> type; 00393 }; 00394 00395 template <typename head, typename tail, typename to_replace, typename replaced> 00396 struct replace_all<typelist<head, tail>, to_replace, replaced> 00397 { 00398 typedef typelist<head, typename replace_all<tail, to_replace, replaced>::type> type; 00399 }; 00400 00401 00402 00403 // returns only those types which are in both typelists 00404 template<typename typelist1, typename typelist2> 00405 struct intersection {}; 00406 00407 template<> 00408 struct intersection<null_type, null_type> 00409 { 00410 typedef null_type type; 00411 }; 00412 00413 template<typename head1, typename tail1> 00414 struct intersection<typelist<head1, tail1>, null_type> 00415 { 00416 typedef null_type type; 00417 }; 00418 00419 template<typename head2, typename tail2> 00420 struct intersection<null_type, typelist<head2, tail2> > 00421 { 00422 typedef null_type type; 00423 }; 00424 00425 template<typename head1, typename tail1, typename head2, typename tail2> 00426 struct intersection< typelist<head1, tail1>, typelist<head2, tail2> > 00427 { 00428 typedef typelist<head1, tail1> typelist1; 00429 typedef typelist<head2, tail2> typelist2; 00430 00431 static const int search_result = index_of< typelist2, head1 >::value; 00432 static const bool found = (search_result >= 0); //otherwise there are parsing problems with Doxygen 1.7.6.1 00433 00434 typedef typename IF< 00435 found, 00436 typename erase_at<typelist2, search_result>::type, 00437 typelist2 00438 >::type new_typelist2; 00439 00440 typedef typename IF< 00441 found, 00442 typelist<head1, typename intersection<tail1, new_typelist2>::type >, 00443 typename intersection<tail1, new_typelist2>::type 00444 >::type type; 00445 }; 00446 00447 } 00448 } // namespace detail 00449 } // namespace viennagrid 00450 00451 00452 #endif // end file guardian