ViennaGrid - The Vienna Grid Library
2.1.0
|
00001 #ifndef VIENNAGRID_META_TYPEMAP_HPP 00002 #define VIENNAGRID_META_TYPEMAP_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 #include "viennagrid/meta/typelist.hpp" 00018 00023 namespace viennagrid 00024 { 00025 namespace detail 00026 { 00027 namespace result_of 00028 { 00029 00031 template<typename ConfigEntryT> 00032 struct unpack_second 00033 { 00034 typedef typename ConfigEntryT::second type; 00035 }; 00036 00037 template<> 00038 struct unpack_second<viennagrid::not_found> 00039 { 00040 typedef viennagrid::not_found type; 00041 }; 00042 00043 00044 00045 00046 template <typename to_find, typename value_type, typename tail> 00047 struct index_of<typelist< static_pair<to_find, value_type>, tail>, to_find> 00048 { 00049 static const int value = 0; 00050 }; 00051 00052 template <typename key_type, typename value_type, typename tail, typename to_find> 00053 struct index_of<typelist< static_pair<key_type, value_type>, tail>, to_find> 00054 { 00055 private: 00056 static const int temp = index_of<tail, to_find>::value; 00057 public: 00058 static const int value = (temp == -1 ? -1 : 1 + temp); 00059 }; 00060 00061 00062 // find a key 00063 template<typename typemap, typename to_find> 00064 struct find 00065 {}; 00066 00067 template<typename to_find> 00068 struct find< null_type, to_find > 00069 { 00070 typedef not_found type; 00071 }; 00072 00073 template<typename value, typename tail, typename to_find> 00074 struct find< typelist<static_pair<to_find, value>, tail>, to_find> 00075 { 00076 typedef static_pair<to_find, value> type; 00077 }; 00078 00079 template<typename key, typename value, typename tail, typename to_find> 00080 struct find< typelist<static_pair<key, value>, tail>, to_find> 00081 { 00082 typedef typename find<tail, to_find>::type type; 00083 }; 00084 00085 00086 00087 // find a key 00088 template<typename typemap, typename to_find> 00089 struct lookup 00090 { 00091 typedef typename unpack_second< 00092 typename find<typemap, to_find>::type 00093 >::type type; 00094 }; 00095 00096 // insert 00097 template <typename typemap, typename to_insert> struct insert; 00098 00099 template <> 00100 struct insert<null_type, null_type> 00101 { 00102 typedef null_type type; 00103 }; 00104 00105 template <typename map_key, typename map_value, typename tail> 00106 struct insert<typelist<static_pair<map_key, map_value>, tail>, null_type> 00107 { 00108 typedef typelist<static_pair<map_key, map_value>, tail> type; 00109 }; 00110 00111 template<typename key, typename value> 00112 struct insert< null_type, static_pair<key, value> > 00113 { 00114 typedef typelist<static_pair<key, value>, null_type> type; 00115 }; 00116 00117 template <typename map_key, typename map_value, typename tail, typename to_insert_key, typename to_insert_value> 00118 struct insert<typelist<static_pair<map_key, map_value>, tail>, static_pair<to_insert_key, to_insert_value> > 00119 { 00120 typedef typelist<static_pair<map_key, map_value>, tail> typemap; 00121 00122 // !!!!! INFO !!!!! 00123 // if a compiler error points to the next lines, you might want to insert a key which is already present 00124 typedef typename STATIC_ASSERT<EQUAL< 00125 not_found, 00126 typename find<typemap,to_insert_key>::type 00127 >::value >::type static_assert_typedef; 00128 00129 typedef typename result_of::push_back<typemap, static_pair<to_insert_key, to_insert_value> >::type type; 00130 }; 00131 00132 00133 00134 // modifies an element 00135 template<typename typemap, typename to_modify> 00136 struct modify 00137 {}; 00138 00139 template <typename map_key, typename map_value, typename tail> 00140 struct modify<typelist<static_pair<map_key, map_value>, tail>, null_type> 00141 { 00142 typedef typelist<static_pair<map_key, map_value>, tail> type; 00143 }; 00144 00145 template<typename key_to_find, typename modified_value> 00146 struct modify< null_type, static_pair<key_to_find, modified_value> > 00147 { 00148 // !!!!! INFO !!!!! 00149 // if a compiler error points here, your might want to insert an element in an empty map 00150 }; 00151 00152 template<typename map_key, typename map_value, typename tail, typename key_to_find, typename modified_value> 00153 struct modify< typelist<static_pair<map_key, map_value>, tail>, static_pair<key_to_find, modified_value> > 00154 { 00155 typedef typelist<static_pair<map_key, map_value>, tail> typemap; 00156 static const int index = index_of<typemap, key_to_find>::value; 00157 00158 // !!!!! INFO !!!!! 00159 // if a compiler error points to the next lines, you might want to modify an element which is not present 00160 typedef typename STATIC_ASSERT<index != -1>::type static_assert_typedef; 00161 00162 typedef typename result_of::replace_at< 00163 typemap, 00164 index, 00165 static_pair<key_to_find, modified_value> 00166 >::type type; 00167 }; 00168 00169 00170 // modifies or inserts an element 00171 template<typename typemap, typename to_modify> 00172 struct insert_or_modify 00173 {}; 00174 00175 template <typename map_key, typename map_value, typename tail> 00176 struct insert_or_modify<typelist<static_pair<map_key, map_value>, tail>, null_type> 00177 { 00178 typedef typelist<static_pair<map_key, map_value>, tail> type; 00179 }; 00180 00181 template<typename key_to_find, typename modified_value> 00182 struct insert_or_modify< null_type, static_pair<key_to_find, modified_value> > 00183 { 00184 typedef typelist<static_pair<key_to_find, modified_value>, null_type> type; 00185 }; 00186 00187 template<typename map_key, typename map_value, typename tail, typename key_to_find, typename modified_value> 00188 struct insert_or_modify< typelist<static_pair<map_key, map_value>, tail>, static_pair<key_to_find, modified_value> > 00189 { 00190 typedef typelist<static_pair<map_key, map_value>, tail> typemap; 00191 static const int index = index_of<typemap, key_to_find>::value; 00192 00193 // !!!!! INFO !!!!! 00194 // if a compiler error points to the next lines, you might want to modify an element which is not present 00195 typedef typename IF< 00196 index == -1, 00197 typename result_of::push_back<typemap, static_pair<key_to_find, modified_value> >::type, 00198 typename result_of::replace_at<typemap, index, static_pair<key_to_find, modified_value> >::type 00199 >::type type; 00200 }; 00201 00202 00203 00204 // erases the element with key 00205 template<typename head_key, typename head_value, typename tail, typename to_erase> 00206 struct erase< typelist< static_pair<head_key, head_value>, tail>, to_erase> 00207 { 00208 typedef typelist< static_pair<head_key, head_value>, tail> typemap; 00209 static const int index = index_of<typemap, to_erase>::value; 00210 00211 // !!!!! INFO !!!!! 00212 // if a compiler error points to the next lines, you might want to erase a key which does not exist 00213 typedef typename STATIC_ASSERT<index != -1>::type static_assert_typedef; 00214 00215 typedef typename result_of::erase_at< 00216 typemap, 00217 index 00218 >::type type; 00219 }; 00220 00221 00222 // merge two lists 00223 template<typename to_insert, typename search_result> 00224 struct merge_helper_error 00225 {}; 00226 00227 template<typename to_insert> 00228 struct merge_helper_error<to_insert, not_found> 00229 { 00230 typedef to_insert type; 00231 }; 00232 00233 template<typename to_insert, typename search_result> 00234 struct merge_helper_ignore 00235 { 00236 typedef search_result type; 00237 }; 00238 00239 template<typename to_insert> 00240 struct merge_helper_ignore<to_insert, not_found> 00241 { 00242 typedef to_insert type; 00243 }; 00244 00245 template<typename to_insert, typename search_result> 00246 struct merge_helper_overwrite 00247 { 00248 typedef to_insert type; 00249 }; 00250 00251 00252 template <typename typemap, typename typemap_to_merge, template<typename,typename> class merge_helper> struct merge_impl; 00253 00254 template <template<typename,typename> class merge_helper> 00255 struct merge_impl<null_type, null_type, merge_helper> 00256 { 00257 typedef null_type type; 00258 }; 00259 00260 template <typename key1, typename value1, typename tail1, template<typename,typename> class merge_helper> 00261 struct merge_impl<typelist<static_pair<key1, value1>, tail1>, null_type, merge_helper> 00262 { 00263 typedef typelist<static_pair<key1, value1>, tail1> type; 00264 }; 00265 00266 template <typename key2, typename value2, typename tail2, template<typename,typename> class merge_helper> 00267 struct merge_impl<null_type, typelist<static_pair<key2, value2>, tail2>, merge_helper> 00268 { 00269 typedef typelist<static_pair<key2, value2>, tail2> type; 00270 }; 00271 00272 template <typename key1, typename value1, typename tail1, typename key2, typename value2, typename tail2, template<typename,typename> class merge_helper> 00273 struct merge_impl<typelist<static_pair<key1, value1>, tail1>, typelist<static_pair<key2, value2>, tail2>, merge_helper> 00274 { 00275 typedef typelist<static_pair<key1, value1>, tail1> typemap1; 00276 typedef typelist<static_pair<key2, value2>, tail1> typemap2; 00277 00278 typedef typename find<typemap1, key2>::type search_result; 00279 00280 // !!!!! INFO !!!!! 00281 // if a compiler error points to the next lines, you might want to merge a two lists with both contain the same key 00282 typedef typename merge_impl< 00283 typename insert_or_modify< 00284 typemap1, 00285 typename merge_helper< 00286 static_pair<key2, value2>, 00287 search_result 00288 >::type 00289 >::type, 00290 tail2, 00291 merge_helper 00292 >::type type; 00293 }; 00294 00295 00296 00297 template <typename typemap, typename typemap_to_merge> 00298 struct merge 00299 { 00300 typedef typename merge_impl<typemap, typemap_to_merge, merge_helper_error>::type type; 00301 }; 00302 00303 template <typename typemap, typename typemap_to_merge> 00304 struct merge_ignore 00305 { 00306 typedef typename merge_impl<typemap, typemap_to_merge, merge_helper_ignore>::type type; 00307 }; 00308 00309 template <typename typemap, typename typemap_to_merge> 00310 struct merge_overwrite 00311 { 00312 typedef typename merge_impl<typemap, typemap_to_merge, merge_helper_overwrite>::type type; 00313 }; 00314 00315 00316 // check consistency 00317 template<typename typemap> 00318 struct consistency {}; 00319 00320 template<> 00321 struct consistency<null_type> 00322 { 00323 typedef null_type type; 00324 }; 00325 00326 00327 template<typename key, typename value, typename tail> 00328 struct consistency< typelist<static_pair<key, value>, tail> > 00329 { 00330 // !!!!! INFO !!!!! 00331 // if a compiler error points to the next lines, your viennamta::map is corrupted (e.g. duplicate keys, ...) 00332 typedef typename STATIC_ASSERT< 00333 EQUAL< 00334 not_found, 00335 typename find<tail, key>::type 00336 >::value >::type static_assert_typedef; 00337 00338 typedef typelist< 00339 static_pair<key,value>, 00340 typename consistency<tail>::type 00341 > type; 00342 }; 00343 00344 00345 00346 template<typename typemap_> 00347 struct key_typelist; 00348 00349 template<> 00350 struct key_typelist<viennagrid::null_type> 00351 { 00352 typedef viennagrid::null_type type; 00353 }; 00354 00355 template<typename key_, typename value_, typename tail> 00356 struct key_typelist< viennagrid::typelist< viennagrid::static_pair<key_, value_> , tail> > 00357 { 00358 typedef viennagrid::typelist< key_, typename key_typelist<tail>::type > type; 00359 }; 00360 00361 00362 00363 00364 template<typename typemap_> 00365 struct value_typelist; 00366 00367 template<> 00368 struct value_typelist<viennagrid::null_type> 00369 { 00370 typedef viennagrid::null_type type; 00371 }; 00372 00373 template<typename key_, typename value_, typename tail> 00374 struct value_typelist< viennagrid::typelist< viennagrid::static_pair<key_, value_> , tail> > 00375 { 00376 typedef viennagrid::typelist< value_, typename key_typelist<tail>::type > type; 00377 }; 00378 00379 } 00380 00381 00382 // C++11 version 00383 00384 // template<typename ... types> 00385 // struct make_typemap_unsafe; 00386 // 00387 // template<> 00388 // struct make_typemap_unsafe<> 00389 // { 00390 // typedef viennagrid::null_type type; 00391 // }; 00392 // 00393 // template<typename key, typename value, typename ... tail> 00394 // struct make_typemap_unsafe<key, value, tail...> 00395 // { 00396 // typedef viennagrid::typelist< 00397 // viennagrid::static_pair<key,value>, 00398 // typename make_typemap_unsafe<tail...>::type 00399 // > type; 00400 // }; 00401 // 00402 // 00403 // template<typename ... types> 00404 // struct make_typemap 00405 // { 00406 // typedef typename viennagrid::detail::result_of::consistency< typename make_typemap_unsafe<types...>::type>::type type; 00407 // }; 00408 00409 00412 template< typename K01 = viennagrid::null_type, typename V01 = viennagrid::null_type, typename K02 = viennagrid::null_type, typename V02 = viennagrid::null_type, 00413 typename K03 = viennagrid::null_type, typename V03 = viennagrid::null_type, typename K04 = viennagrid::null_type, typename V04 = viennagrid::null_type, 00414 typename K05 = viennagrid::null_type, typename V05 = viennagrid::null_type, typename K06 = viennagrid::null_type, typename V06 = viennagrid::null_type, 00415 typename K07 = viennagrid::null_type, typename V07 = viennagrid::null_type, typename K08 = viennagrid::null_type, typename V08 = viennagrid::null_type, 00416 typename K09 = viennagrid::null_type, typename V09 = viennagrid::null_type, typename K10 = viennagrid::null_type, typename V10 = viennagrid::null_type, 00417 typename K11 = viennagrid::null_type, typename V11 = viennagrid::null_type, typename K12 = viennagrid::null_type, typename V12 = viennagrid::null_type, 00418 typename K13 = viennagrid::null_type, typename V13 = viennagrid::null_type, typename K14 = viennagrid::null_type, typename V14 = viennagrid::null_type, 00419 typename K15 = viennagrid::null_type, typename V15 = viennagrid::null_type, typename K16 = viennagrid::null_type, typename V16 = viennagrid::null_type, 00420 typename K17 = viennagrid::null_type, typename V17 = viennagrid::null_type, typename K18 = viennagrid::null_type, typename V18 = viennagrid::null_type, 00421 typename K19 = viennagrid::null_type, typename V19 = viennagrid::null_type, typename K20 = viennagrid::null_type, typename V20 = viennagrid::null_type > 00422 struct make_typemap_unsafe 00423 { 00424 typedef 00425 typelist< 00426 viennagrid::static_pair<K01,V01>, 00427 typename make_typemap_unsafe< K02, V02, K03, V03, K04, V04, K05, V05, K06, V06, K07, V07, K08, V08, K09, V09, K10, V10, 00428 K11, V11, K12, V12, K13, V13, K14, V14, K15, V15, K16, V16, K17, V17, K18, V18, K19, V19, K20, V20>::type 00429 > type; 00430 }; 00431 00432 template<> 00433 struct make_typemap_unsafe< 00434 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00435 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00436 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00437 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00438 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00439 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00440 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00441 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00442 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, 00443 viennagrid::null_type, viennagrid::null_type, viennagrid::null_type, viennagrid::null_type > 00444 { 00445 typedef viennagrid::null_type type; 00446 }; 00447 00450 } // namespace detail 00451 00455 template< typename K01 = viennagrid::null_type, typename V01 = viennagrid::null_type, typename K02 = viennagrid::null_type, typename V02 = viennagrid::null_type, 00456 typename K03 = viennagrid::null_type, typename V03 = viennagrid::null_type, typename K04 = viennagrid::null_type, typename V04 = viennagrid::null_type, 00457 typename K05 = viennagrid::null_type, typename V05 = viennagrid::null_type, typename K06 = viennagrid::null_type, typename V06 = viennagrid::null_type, 00458 typename K07 = viennagrid::null_type, typename V07 = viennagrid::null_type, typename K08 = viennagrid::null_type, typename V08 = viennagrid::null_type, 00459 typename K09 = viennagrid::null_type, typename V09 = viennagrid::null_type, typename K10 = viennagrid::null_type, typename V10 = viennagrid::null_type, 00460 typename K11 = viennagrid::null_type, typename V11 = viennagrid::null_type, typename K12 = viennagrid::null_type, typename V12 = viennagrid::null_type, 00461 typename K13 = viennagrid::null_type, typename V13 = viennagrid::null_type, typename K14 = viennagrid::null_type, typename V14 = viennagrid::null_type, 00462 typename K15 = viennagrid::null_type, typename V15 = viennagrid::null_type, typename K16 = viennagrid::null_type, typename V16 = viennagrid::null_type, 00463 typename K17 = viennagrid::null_type, typename V17 = viennagrid::null_type, typename K18 = viennagrid::null_type, typename V18 = viennagrid::null_type, 00464 typename K19 = viennagrid::null_type, typename V19 = viennagrid::null_type, typename K20 = viennagrid::null_type, typename V20 = viennagrid::null_type > 00465 struct make_typemap 00466 { 00467 typedef typename viennagrid::detail::result_of::consistency< 00468 typename detail::make_typemap_unsafe< 00469 K01, V01, K02, V02, K03, V03, K04, V04, K05, V05, K06, V06, K07, V07, K08, V08, K09, V09, K10, V10, 00470 K11, V11, K12, V12, K13, V13, K14, V14, K15, V15, K16, V16, K17, V17, K18, V18, K19, V19, K20, V20 00471 >::type 00472 >::type type; 00473 }; 00474 00477 } // namespace viennagrid 00478 00479 #endif