ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/meta/typemap.hpp
Go to the documentation of this file.
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