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