libstdc++
typelist.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2005, 2006, 2008, 2009, 2010 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 ext/typelist.h
00037  *  This file is a GNU extension to the Standard C++ Library.
00038  *
00039  *  Contains typelist_chain definitions.
00040  *  Typelists are an idea by Andrei Alexandrescu.
00041  */
00042 
00043 #ifndef _TYPELIST_H
00044 #define _TYPELIST_H 1
00045 
00046 #include <ext/type_traits.h>
00047 
00048 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
00049 {
00050 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00051 
00052 /** @namespace __gnu_cxx::typelist
00053  *  @brief GNU typelist extensions for public compile-time use.
00054 */
00055 namespace typelist
00056 {
00057   struct null_type { };
00058 
00059   template<typename Root>
00060     struct node
00061     {
00062       typedef Root  root;
00063     };
00064 
00065   // Forward declarations of functors.
00066   template<typename Hd, typename Typelist>
00067     struct chain
00068     {
00069       typedef Hd    head;
00070       typedef Typelist  tail;
00071     };
00072 
00073   // Apply all typelist types to unary functor.
00074   template<typename Fn, typename Typelist>
00075     void
00076     apply(Fn&, Typelist);
00077 
00078   /// Apply all typelist types to generator functor.
00079   template<typename Gn, typename Typelist>
00080     void
00081     apply_generator(Gn&, Typelist);
00082 
00083   // Apply all typelist types and values to generator functor.
00084   template<typename Gn, typename TypelistT, typename TypelistV>
00085     void
00086     apply_generator(Gn&, TypelistT, TypelistV);
00087 
00088   template<typename Typelist0, typename Typelist1>
00089     struct append;
00090 
00091   template<typename Typelist_Typelist>
00092     struct append_typelist;
00093 
00094   template<typename Typelist, typename T>
00095     struct contains;
00096 
00097   template<typename Typelist, template<typename T> class Pred>
00098     struct filter;
00099 
00100   template<typename Typelist, int i>
00101     struct at_index;
00102 
00103   template<typename Typelist, template<typename T> class Transform>
00104     struct transform;
00105 
00106   template<typename Typelist_Typelist>
00107     struct flatten;
00108 
00109   template<typename Typelist>
00110     struct from_first;
00111 
00112   template<typename T1>
00113     struct create1;
00114 
00115   template<typename T1, typename T2>
00116     struct create2;
00117 
00118   template<typename T1, typename T2, typename T3>
00119     struct create3;
00120 
00121   template<typename T1, typename T2, typename T3, typename T4>
00122     struct create4;
00123 
00124   template<typename T1, typename T2, typename T3, typename T4, typename T5>
00125     struct create5;
00126 
00127   template<typename T1, typename T2, typename T3,
00128        typename T4, typename T5, typename T6>
00129     struct create6;
00130 } // namespace typelist
00131 
00132 _GLIBCXX_END_NAMESPACE_VERSION
00133 } // namespace
00134 
00135 
00136 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
00137 {
00138 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00139 
00140 namespace typelist
00141 {
00142 namespace detail
00143 {
00144   template<typename Fn, typename Typelist_Chain>
00145     struct apply_;
00146 
00147   template<typename Fn, typename Hd, typename Tl>
00148     struct apply_<Fn, chain<Hd, Tl> >
00149     {
00150       void
00151       operator()(Fn& f)
00152       {
00153     f.operator()(Hd());
00154     apply_<Fn, Tl> next;
00155     next(f);
00156       }
00157     };
00158 
00159   template<typename Fn>
00160     struct apply_<Fn, null_type>
00161     {
00162       void
00163       operator()(Fn&) { }
00164     };
00165 
00166   template<typename Gn, typename Typelist_Chain>
00167     struct apply_generator1_;
00168 
00169   template<typename Gn, typename Hd, typename Tl>
00170     struct apply_generator1_<Gn, chain<Hd, Tl> >
00171     {
00172       void
00173       operator()(Gn& g)
00174       {
00175     g.template operator()<Hd>();
00176     apply_generator1_<Gn, Tl> next;
00177     next(g);
00178       }
00179     };
00180 
00181   template<typename Gn>
00182     struct apply_generator1_<Gn, null_type>
00183     {
00184       void
00185       operator()(Gn&) { }
00186     };
00187 
00188   template<typename Gn, typename TypelistT_Chain, typename TypelistV_Chain>
00189     struct apply_generator2_;
00190 
00191   template<typename Gn, typename Hd1, typename TlT, typename Hd2, typename TlV>
00192     struct apply_generator2_<Gn, chain<Hd1, TlT>, chain<Hd2, TlV> >
00193     {
00194       void
00195       operator()(Gn& g)
00196       {
00197     g.template operator()<Hd1, Hd2>();
00198     apply_generator2_<Gn, TlT, TlV> next;
00199     next(g);
00200       }
00201     };
00202 
00203   template<typename Gn>
00204     struct apply_generator2_<Gn, null_type, null_type>
00205     {
00206       void
00207       operator()(Gn&) { }
00208     };
00209 
00210   template<typename Typelist_Chain0, typename Typelist_Chain1>
00211     struct append_;
00212 
00213   template<typename Hd, typename Tl, typename Typelist_Chain>
00214     struct append_<chain<Hd, Tl>, Typelist_Chain>
00215     {
00216     private:
00217       typedef append_<Tl, Typelist_Chain>           append_type;
00218 
00219     public:
00220       typedef chain<Hd, typename append_type::type>         type;
00221     };
00222 
00223   template<typename Typelist_Chain>
00224     struct append_<null_type, Typelist_Chain>
00225     {
00226       typedef Typelist_Chain                        type;
00227     };
00228 
00229   template<typename Typelist_Chain>
00230     struct append_<Typelist_Chain, null_type>
00231     {
00232       typedef Typelist_Chain                    type;
00233     };
00234 
00235   template<>
00236     struct append_<null_type, null_type>
00237     {
00238       typedef null_type                     type;
00239     };
00240 
00241   template<typename Typelist_Typelist_Chain>
00242     struct append_typelist_;
00243 
00244   template<typename Hd>
00245     struct append_typelist_<chain<Hd, null_type> >
00246     {
00247       typedef chain<Hd, null_type>              type;
00248     };
00249 
00250   template<typename Hd, typename Tl>
00251     struct append_typelist_<chain< Hd, Tl> >
00252     {
00253     private:
00254       typedef typename append_typelist_<Tl>::type       rest_type;
00255 
00256     public:
00257       typedef typename append<Hd, node<rest_type> >::type::root type;
00258     };
00259 
00260   template<typename Typelist_Chain, typename T>
00261     struct contains_;
00262 
00263   template<typename T>
00264     struct contains_<null_type, T>
00265     {
00266       enum
00267     {
00268       value = false
00269     };
00270     };
00271 
00272   template<typename Hd, typename Tl, typename T>
00273     struct contains_<chain<Hd, Tl>, T>
00274     {
00275       enum
00276     {
00277       value = contains_<Tl, T>::value
00278     };
00279     };
00280 
00281   template<typename Tl, typename T>
00282     struct contains_<chain<T, Tl>, T>
00283     {
00284       enum
00285     {
00286       value = true
00287     };
00288     };
00289 
00290   template<typename Typelist_Chain, template<typename T> class Pred>
00291     struct chain_filter_;
00292 
00293   template<template<typename T> class Pred>
00294     struct chain_filter_<null_type, Pred>
00295     {
00296       typedef null_type                     type;
00297   };
00298 
00299   template<typename Hd, typename Tl, template<typename T> class Pred>
00300     struct chain_filter_<chain<Hd, Tl>, Pred>
00301     {
00302     private:
00303       enum
00304     {
00305       include_hd = Pred<Hd>::value
00306     };
00307 
00308       typedef typename chain_filter_<Tl, Pred>::type        rest_type;
00309       typedef chain<Hd, rest_type>              chain_type;
00310 
00311     public:
00312       typedef typename __conditional_type<include_hd, chain_type, rest_type>::__type type;
00313   };
00314 
00315   template<typename Typelist_Chain, int i>
00316     struct chain_at_index_;
00317 
00318   template<typename Hd, typename Tl>
00319     struct chain_at_index_<chain<Hd, Tl>, 0>
00320     {
00321       typedef Hd                        type;
00322     };
00323 
00324   template<typename Hd, typename Tl, int i>
00325     struct chain_at_index_<chain<Hd, Tl>, i>
00326     {
00327       typedef typename chain_at_index_<Tl, i - 1>::type     type;
00328     };
00329 
00330   template<class Typelist_Chain, template<typename T> class Transform>
00331     struct chain_transform_;
00332 
00333   template<template<typename T> class Transform>
00334     struct chain_transform_<null_type, Transform>
00335     {
00336       typedef null_type                     type;
00337     };
00338 
00339   template<class Hd, class Tl, template<typename T> class Transform>
00340     struct chain_transform_<chain<Hd, Tl>, Transform>
00341     {
00342     private:
00343       typedef typename chain_transform_<Tl, Transform>::type    rest_type;
00344       typedef typename Transform<Hd>::type          transform_type;
00345 
00346     public:
00347       typedef chain<transform_type, rest_type>          type;
00348     };
00349 
00350   template<typename Typelist_Typelist_Chain>
00351     struct chain_flatten_;
00352 
00353   template<typename Hd_Tl>
00354     struct chain_flatten_<chain<Hd_Tl, null_type> >
00355     {
00356       typedef typename Hd_Tl::root              type;
00357     };
00358 
00359   template<typename Hd_Typelist, class Tl_Typelist>
00360     struct chain_flatten_<chain<Hd_Typelist, Tl_Typelist> >
00361     {
00362     private:
00363       typedef typename chain_flatten_<Tl_Typelist>::type    rest_type;
00364       typedef append<Hd_Typelist, node<rest_type> >     append_type;
00365     public:
00366       typedef typename append_type::type::root          type;
00367     };
00368 } // namespace detail
00369 } // namespace typelist
00370 
00371 _GLIBCXX_END_NAMESPACE_VERSION
00372 } // namespace
00373 
00374 #define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain<X0, __gnu_cxx::typelist::null_type>
00375 #define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN1(X1) >
00376 #define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN2(X1, X2) >
00377 #define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN3(X1, X2, X3) >
00378 #define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN4(X1, X2, X3, X4) >
00379 #define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN5(X1, X2, X3, X4, X5) >
00380 #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) >
00381 #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) >
00382 #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) >
00383 #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) >
00384 #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) >
00385 #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) >
00386 #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) >
00387 #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) >
00388 #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) >
00389 
00390 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
00391 {
00392 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00393 
00394 namespace typelist
00395 {
00396   template<typename Fn, typename Typelist>
00397     void
00398     apply(Fn& fn, Typelist)
00399     {
00400       detail::apply_<Fn, typename Typelist::root> a;
00401       a(fn);
00402     }
00403 
00404   template<typename Fn, typename Typelist>
00405     void
00406     apply_generator(Fn& fn, Typelist)
00407     {
00408       detail::apply_generator1_<Fn, typename Typelist::root> a;
00409       a(fn);
00410     }
00411 
00412   template<typename Fn, typename TypelistT, typename TypelistV>
00413     void
00414     apply_generator(Fn& fn, TypelistT, TypelistV)
00415     {
00416       typedef typename TypelistT::root rootT;
00417       typedef typename TypelistV::root rootV;
00418       detail::apply_generator2_<Fn, rootT, rootV> a;
00419       a(fn);
00420     }
00421 
00422   template<typename Typelist0, typename Typelist1>
00423     struct append
00424     {
00425     private:
00426       typedef typename Typelist0::root              root0_type;
00427       typedef typename Typelist1::root              root1_type;
00428       typedef detail::append_<root0_type, root1_type>       append_type;
00429 
00430     public:
00431       typedef node<typename append_type::type>          type;
00432     };
00433 
00434   template<typename Typelist_Typelist>
00435     struct append_typelist
00436     {
00437     private:
00438       typedef typename Typelist_Typelist::root              root_type;
00439       typedef detail::append_typelist_<root_type>       append_type;
00440 
00441     public:
00442       typedef node<typename append_type::type>          type;
00443     };
00444 
00445   template<typename Typelist, typename T>
00446     struct contains
00447     {
00448     private:
00449       typedef typename Typelist::root               root_type;
00450 
00451     public:
00452       enum
00453     {
00454       value = detail::contains_<root_type, T>::value
00455     };
00456     };
00457 
00458   template<typename Typelist, template<typename T> class Pred>
00459     struct filter
00460     {
00461     private:
00462       typedef typename Typelist::root               root_type;
00463       typedef detail::chain_filter_<root_type, Pred>        filter_type;
00464 
00465     public:
00466       typedef node<typename filter_type::type>              type;
00467     };
00468 
00469   template<typename Typelist, int i>
00470     struct at_index
00471     {
00472     private:
00473       typedef typename Typelist::root               root_type;
00474       typedef detail::chain_at_index_<root_type, i>         index_type;
00475 
00476     public:
00477       typedef typename index_type::type             type;
00478     };
00479 
00480   template<typename Typelist, template<typename T> class Transform>
00481     struct transform
00482     {
00483     private:
00484       typedef typename Typelist::root               root_type;
00485       typedef detail::chain_transform_<root_type, Transform>    transform_type;
00486 
00487     public:
00488       typedef node<typename transform_type::type>       type;
00489     };
00490 
00491   template<typename Typelist_Typelist>
00492     struct flatten
00493     {
00494     private:
00495       typedef typename Typelist_Typelist::root              root_type;
00496       typedef typename detail::chain_flatten_<root_type>::type  flatten_type;
00497 
00498     public:
00499       typedef node<flatten_type>                type;
00500     };
00501 
00502   template<typename Typelist>
00503     struct from_first
00504     {
00505     private:
00506       typedef typename at_index<Typelist, 0>::type      first_type;
00507 
00508     public:
00509       typedef node<chain<first_type, null_type> >       type;
00510     };
00511 
00512   template<typename T1>
00513     struct create1
00514     {
00515       typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)>        type;
00516     };
00517 
00518   template<typename T1, typename T2>
00519     struct create2
00520     {
00521       typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)>         type;
00522     };
00523 
00524   template<typename T1, typename T2, typename T3>
00525     struct create3
00526     {
00527       typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)>      type;
00528     };
00529 
00530   template<typename T1, typename T2, typename T3, typename T4>
00531     struct create4
00532     {
00533       typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)>   type;
00534     };
00535 
00536   template<typename T1, typename T2, typename T3,
00537        typename T4, typename T5>
00538     struct create5
00539     {
00540       typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)>    type;
00541     };
00542 
00543   template<typename T1, typename T2, typename T3,
00544        typename T4, typename T5, typename T6>
00545     struct create6
00546     {
00547       typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type;
00548     };
00549 } // namespace typelist
00550 _GLIBCXX_END_NAMESPACE_VERSION
00551 } // namespace
00552 
00553 
00554 #endif