typelist.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
00026 
00027 // Permission to use, copy, modify, sell, and distribute this software
00028 // is hereby granted without fee, provided that the above copyright
00029 // notice appears in all copies, and that both that copyright notice and
00030 // this permission notice appear in supporting documentation. None of
00031 // the above authors, nor IBM Haifa Research Laboratories, make any
00032 // representation about the suitability of this software for any
00033 // purpose. It is provided "as is" without express or implied warranty.
00034 
00035 /**
00036  * @file typelist.h
00037  * Contains typelist_chain definitions.
00038  * Typelists are an idea by Andrei Alexandrescu.
00039  */
00040 
00041 #ifndef _TYPELIST_H
00042 #define _TYPELIST_H 1
00043 
00044 #include <ext/type_traits.h>
00045 
00046 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
00047 
00048 /** @namespace __gnu_cxx::typelist
00049  *  @brief GNU typelist extensions for public compile-time use.
00050 */
00051 namespace typelist
00052 {
00053   struct null_type { };
00054 
00055   template<typename Root>
00056     struct node
00057     {
00058       typedef Root  root;
00059     };
00060 
00061   // Forward declarations of functors.
00062   template<typename Hd, typename Typelist>
00063     struct chain
00064     {
00065       typedef Hd    head;
00066       typedef Typelist  tail;
00067     };
00068 
00069   // Apply all typelist types to unary functor.
00070   template<typename Fn, typename Typelist>
00071     void
00072     apply(Fn&, Typelist);
00073 
00074   /// Apply all typelist types to generator functor.
00075   template<typename Gn, typename Typelist>
00076     void
00077     apply_generator(Gn&, Typelist);
00078 
00079   // Apply all typelist types and values to generator functor.
00080   template<typename Gn, typename TypelistT, typename TypelistV>
00081     void
00082     apply_generator(Gn&, TypelistT, TypelistV);
00083 
00084   template<typename Typelist0, typename Typelist1>
00085     struct append;
00086 
00087   template<typename Typelist_Typelist>
00088     struct append_typelist;
00089 
00090   template<typename Typelist, typename T>
00091     struct contains;
00092  
00093   template<typename Typelist, template<typename T> class Pred>
00094     struct filter;
00095 
00096   template<typename Typelist, int i>
00097     struct at_index;
00098 
00099   template<typename Typelist, template<typename T> class Transform>
00100     struct transform;
00101 
00102   template<typename Typelist_Typelist>
00103     struct flatten;
00104 
00105   template<typename Typelist>
00106     struct from_first;
00107 
00108   template<typename T1>
00109     struct create1;
00110 
00111   template<typename T1, typename T2>
00112     struct create2;
00113 
00114   template<typename T1, typename T2, typename T3>
00115     struct create3;
00116 
00117   template<typename T1, typename T2, typename T3, typename T4>
00118     struct create4;
00119 
00120   template<typename T1, typename T2, typename T3, typename T4, typename T5>
00121     struct create5;
00122 
00123   template<typename T1, typename T2, typename T3, 
00124        typename T4, typename T5, typename T6>
00125     struct create6;
00126 } // namespace typelist
00127 
00128 _GLIBCXX_END_NAMESPACE
00129 
00130 
00131 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
00132 
00133 namespace typelist 
00134 {
00135 namespace detail
00136 {
00137   template<typename Fn, typename Typelist_Chain>
00138     struct apply_;
00139 
00140   template<typename Fn, typename Hd, typename Tl>
00141     struct apply_<Fn, chain<Hd, Tl> >
00142     {
00143       void
00144       operator()(Fn& f)
00145       {
00146     f.operator()(Hd());
00147     apply_<Fn, Tl> next;
00148     next(f);
00149       }
00150     };
00151 
00152   template<typename Fn>
00153     struct apply_<Fn, null_type>
00154     {
00155       void
00156       operator()(Fn&) { }
00157     };
00158 
00159   template<typename Gn, typename Typelist_Chain>
00160     struct apply_generator1_;
00161 
00162   template<typename Gn, typename Hd, typename Tl>
00163     struct apply_generator1_<Gn, chain<Hd, Tl> >
00164     {
00165       void
00166       operator()(Gn& g)
00167       {
00168     g.template operator()<Hd>();
00169     apply_generator1_<Gn, Tl> next;
00170     next(g);
00171       }
00172     };
00173 
00174   template<typename Gn>
00175     struct apply_generator1_<Gn, null_type>
00176     {
00177       void
00178       operator()(Gn&) { }
00179     };
00180 
00181   template<typename Gn, typename TypelistT_Chain, typename TypelistV_Chain>
00182     struct apply_generator2_;
00183 
00184   template<typename Gn, typename Hd1, typename TlT, typename Hd2, typename TlV>
00185     struct apply_generator2_<Gn, chain<Hd1, TlT>, chain<Hd2, TlV> >
00186     {
00187       void
00188       operator()(Gn& g)
00189       {
00190     g.template operator()<Hd1, Hd2>();
00191     apply_generator2_<Gn, TlT, TlV> next;
00192     next(g);
00193       }
00194     };
00195 
00196   template<typename Gn>
00197     struct apply_generator2_<Gn, null_type, null_type>
00198     {
00199       void
00200       operator()(Gn&) { }
00201     };
00202 
00203   template<typename Typelist_Chain0, typename Typelist_Chain1>
00204     struct append_;
00205 
00206   template<typename Hd, typename Tl, typename Typelist_Chain>
00207     struct append_<chain<Hd, Tl>, Typelist_Chain>
00208     {
00209     private:
00210       typedef append_<Tl, Typelist_Chain>           append_type;
00211 
00212     public:
00213       typedef chain<Hd, typename append_type::type>         type;
00214     };
00215 
00216   template<typename Typelist_Chain>
00217     struct append_<null_type, Typelist_Chain>
00218     {
00219       typedef Typelist_Chain                        type;
00220     };
00221 
00222   template<typename Typelist_Chain>
00223     struct append_<Typelist_Chain, null_type>
00224     {
00225       typedef Typelist_Chain                    type;
00226     };
00227 
00228   template<>
00229     struct append_<null_type, null_type>
00230     {
00231       typedef null_type                     type;
00232     };
00233 
00234   template<typename Typelist_Typelist_Chain>
00235     struct append_typelist_;
00236 
00237   template<typename Hd>
00238     struct append_typelist_<chain<Hd, null_type> >
00239     {
00240       typedef chain<Hd, null_type>              type;
00241     };
00242 
00243   template<typename Hd, typename Tl>
00244     struct append_typelist_<chain< Hd, Tl> >
00245     {
00246     private:
00247       typedef typename append_typelist_<Tl>::type       rest_type;
00248       
00249     public:
00250       typedef typename append<Hd, node<rest_type> >::type::root type;
00251     };
00252 
00253   template<typename Typelist_Chain, typename T>
00254     struct contains_;
00255 
00256   template<typename T>
00257     struct contains_<null_type, T>
00258     {
00259       enum
00260     {
00261       value = false
00262     };
00263     };
00264 
00265   template<typename Hd, typename Tl, typename T>
00266     struct contains_<chain<Hd, Tl>, T>
00267     {
00268       enum
00269     {
00270       value = contains_<Tl, T>::value
00271     };
00272     };
00273   
00274   template<typename Tl, typename T>
00275     struct contains_<chain<T, Tl>, T>
00276     {
00277       enum
00278     {
00279       value = true
00280     };
00281     };
00282 
00283   template<typename Typelist_Chain, template<typename T> class Pred>
00284     struct chain_filter_;
00285 
00286   template<template<typename T> class Pred>
00287     struct chain_filter_<null_type, Pred>
00288     {
00289       typedef null_type                     type;
00290   };
00291 
00292   template<typename Hd, typename Tl, template<typename T> class Pred>
00293     struct chain_filter_<chain<Hd, Tl>, Pred>
00294     {
00295     private:
00296       enum
00297     {
00298       include_hd = Pred<Hd>::value
00299     };
00300       
00301       typedef typename chain_filter_<Tl, Pred>::type        rest_type;
00302       typedef chain<Hd, rest_type>              chain_type;
00303 
00304     public:
00305       typedef typename __conditional_type<include_hd, chain_type, rest_type>::__type type;
00306   };
00307 
00308   template<typename Typelist_Chain, int i>
00309     struct chain_at_index_;
00310 
00311   template<typename Hd, typename Tl>
00312     struct chain_at_index_<chain<Hd, Tl>, 0>
00313     {
00314       typedef Hd                        type;
00315     };
00316   
00317   template<typename Hd, typename Tl, int i>
00318     struct chain_at_index_<chain<Hd, Tl>, i>
00319     {
00320       typedef typename chain_at_index_<Tl, i - 1>::type     type;
00321     };
00322 
00323   template<class Typelist_Chain, template<typename T> class Transform>
00324     struct chain_transform_;
00325 
00326   template<template<typename T> class Transform>
00327     struct chain_transform_<null_type, Transform>
00328     {
00329       typedef null_type                     type;
00330     };
00331   
00332   template<class Hd, class Tl, template<typename T> class Transform>
00333     struct chain_transform_<chain<Hd, Tl>, Transform>
00334     {
00335     private:
00336       typedef typename chain_transform_<Tl, Transform>::type    rest_type;
00337       typedef typename Transform<Hd>::type          transform_type;
00338 
00339     public:
00340       typedef chain<transform_type, rest_type>          type;
00341     };
00342 
00343   template<typename Typelist_Typelist_Chain>
00344     struct chain_flatten_;
00345 
00346   template<typename Hd_Tl>
00347     struct chain_flatten_<chain<Hd_Tl, null_type> >
00348     {
00349       typedef typename Hd_Tl::root              type;
00350     };
00351 
00352   template<typename Hd_Typelist, class Tl_Typelist>
00353     struct chain_flatten_<chain<Hd_Typelist, Tl_Typelist> >
00354     {
00355     private:
00356       typedef typename chain_flatten_<Tl_Typelist>::type    rest_type;
00357       typedef append<Hd_Typelist, node<rest_type> >     append_type;
00358     public:
00359       typedef typename append_type::type::root          type;
00360     };
00361 } // namespace detail
00362 } // namespace typelist
00363 
00364 _GLIBCXX_END_NAMESPACE
00365 
00366 #define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain<X0, __gnu_cxx::typelist::null_type>
00367 #define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN1(X1) >
00368 #define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN2(X1, X2) >
00369 #define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN3(X1, X2, X3) >
00370 #define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN4(X1, X2, X3, X4) >
00371 #define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN5(X1, X2, X3, X4, X5) >
00372 #define _GLIBCXX_TYPELIST_CHAIN7(X0, X1, X2, X3, X4, X5, X6) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN6(X1, X2, X3, X4, X5, X6) >
00373 #define _GLIBCXX_TYPELIST_CHAIN8(X0, X1, X2, X3, X4, X5, X6, X7) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN7(X1, X2, X3, X4, X5, X6, X7) >
00374 #define _GLIBCXX_TYPELIST_CHAIN9(X0, X1, X2, X3, X4, X5, X6, X7, X8) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN8(X1, X2, X3, X4, X5, X6, X7, X8) >
00375 #define _GLIBCXX_TYPELIST_CHAIN10(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN9(X1, X2, X3, X4, X5, X6, X7, X8, X9) >
00376 #define _GLIBCXX_TYPELIST_CHAIN11(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN10(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) >
00377 #define _GLIBCXX_TYPELIST_CHAIN12(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN11(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) >
00378 #define _GLIBCXX_TYPELIST_CHAIN13(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN12(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) >
00379 #define _GLIBCXX_TYPELIST_CHAIN14(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN13(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) >
00380 #define _GLIBCXX_TYPELIST_CHAIN15(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN14(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) >
00381 
00382 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
00383 
00384 namespace typelist
00385 {
00386   template<typename Fn, typename Typelist>
00387     void
00388     apply(Fn& fn, Typelist)
00389     {
00390       detail::apply_<Fn, typename Typelist::root> a;
00391       a(fn);
00392     }
00393 
00394   template<typename Fn, typename Typelist>
00395     void
00396     apply_generator(Fn& fn, Typelist)
00397     {
00398       detail::apply_generator1_<Fn, typename Typelist::root> a;
00399       a(fn);
00400     }
00401 
00402   template<typename Fn, typename TypelistT, typename TypelistV>
00403     void
00404     apply_generator(Fn& fn, TypelistT, TypelistV)
00405     {
00406       typedef typename TypelistT::root rootT;
00407       typedef typename TypelistV::root rootV;
00408       detail::apply_generator2_<Fn, rootT, rootV> a;
00409       a(fn);
00410     }
00411 
00412   template<typename Typelist0, typename Typelist1>
00413     struct append
00414     {
00415     private:
00416       typedef typename Typelist0::root              root0_type;
00417       typedef typename Typelist1::root              root1_type;
00418       typedef detail::append_<root0_type, root1_type>       append_type;
00419 
00420     public:
00421       typedef node<typename append_type::type>          type;
00422     };
00423 
00424   template<typename Typelist_Typelist>
00425     struct append_typelist
00426     {
00427     private:
00428       typedef typename Typelist_Typelist::root              root_type;
00429       typedef detail::append_typelist_<root_type>       append_type;
00430 
00431     public:
00432       typedef node<typename append_type::type>          type;
00433     };
00434 
00435   template<typename Typelist, typename T>
00436     struct contains
00437     {
00438     private:
00439       typedef typename Typelist::root               root_type;
00440 
00441     public:
00442       enum
00443     {
00444       value = detail::contains_<root_type, T>::value
00445     };
00446     };
00447 
00448   template<typename Typelist, template<typename T> class Pred>
00449     struct filter
00450     {
00451     private:
00452       typedef typename Typelist::root               root_type;
00453       typedef detail::chain_filter_<root_type, Pred>        filter_type;
00454 
00455     public:
00456       typedef node<typename filter_type::type>              type;
00457     };
00458 
00459   template<typename Typelist, int i>
00460     struct at_index
00461     {
00462     private:
00463       typedef typename Typelist::root               root_type;
00464       typedef detail::chain_at_index_<root_type, i>         index_type;
00465       
00466     public:
00467       typedef typename index_type::type             type;
00468     };
00469 
00470   template<typename Typelist, template<typename T> class Transform>
00471     struct transform
00472     {
00473     private:
00474       typedef typename Typelist::root               root_type;
00475       typedef detail::chain_transform_<root_type, Transform>    transform_type;
00476 
00477     public:
00478       typedef node<typename transform_type::type>       type;
00479     };
00480 
00481   template<typename Typelist_Typelist>
00482     struct flatten
00483     {
00484     private:
00485       typedef typename Typelist_Typelist::root              root_type;
00486       typedef typename detail::chain_flatten_<root_type>::type  flatten_type;
00487 
00488     public:
00489       typedef node<flatten_type>                type;
00490     };
00491 
00492   template<typename Typelist>
00493     struct from_first
00494     {
00495     private:
00496       typedef typename at_index<Typelist, 0>::type      first_type;
00497 
00498     public:
00499       typedef node<chain<first_type, null_type> >       type;
00500     };
00501 
00502   template<typename T1>
00503     struct create1
00504     {
00505       typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)>        type;
00506     };
00507 
00508   template<typename T1, typename T2>
00509     struct create2
00510     {
00511       typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)>         type;
00512     };
00513 
00514   template<typename T1, typename T2, typename T3>
00515     struct create3
00516     {
00517       typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)>      type;
00518     };
00519 
00520   template<typename T1, typename T2, typename T3, typename T4>
00521     struct create4
00522     {
00523       typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)>   type;
00524     };
00525 
00526   template<typename T1, typename T2, typename T3, 
00527        typename T4, typename T5>
00528     struct create5
00529     {
00530       typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)>    type;
00531     };
00532 
00533   template<typename T1, typename T2, typename T3, 
00534        typename T4, typename T5, typename T6>
00535     struct create6
00536     {
00537       typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type;
00538     };
00539 } // namespace typelist
00540 _GLIBCXX_END_NAMESPACE
00541 
00542 
00543 #endif
00544 

Generated on Tue Apr 21 13:13:35 2009 for libstdc++ by  doxygen 1.5.8