# 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