libstdc++
typelist.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2005-2015 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 #define _GLIBCXX_TYPELIST_CHAIN16(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN15(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15) >
00390 #define _GLIBCXX_TYPELIST_CHAIN17(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN16(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16) >
00391 #define _GLIBCXX_TYPELIST_CHAIN18(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN17(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17) >
00392 #define _GLIBCXX_TYPELIST_CHAIN19(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN18(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) >
00393 #define _GLIBCXX_TYPELIST_CHAIN20(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN19(X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) >
00394 
00395 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
00396 {
00397 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00398 
00399 namespace typelist
00400 {
00401   template<typename Fn, typename Typelist>
00402     void
00403     apply(Fn& fn, Typelist)
00404     {
00405       detail::apply_<Fn, typename Typelist::root> a;
00406       a(fn);
00407     }
00408 
00409   template<typename Fn, typename Typelist>
00410     void
00411     apply_generator(Fn& fn, Typelist)
00412     {
00413       detail::apply_generator1_<Fn, typename Typelist::root> a;
00414       a(fn);
00415     }
00416 
00417   template<typename Fn, typename TypelistT, typename TypelistV>
00418     void
00419     apply_generator(Fn& fn, TypelistT, TypelistV)
00420     {
00421       typedef typename TypelistT::root rootT;
00422       typedef typename TypelistV::root rootV;
00423       detail::apply_generator2_<Fn, rootT, rootV> a;
00424       a(fn);
00425     }
00426 
00427   template<typename Typelist0, typename Typelist1>
00428     struct append
00429     {
00430     private:
00431       typedef typename Typelist0::root                          root0_type;
00432       typedef typename Typelist1::root                          root1_type;
00433       typedef detail::append_<root0_type, root1_type>           append_type;
00434 
00435     public:
00436       typedef node<typename append_type::type>                  type;
00437     };
00438 
00439   template<typename Typelist_Typelist>
00440     struct append_typelist
00441     {
00442     private:
00443       typedef typename Typelist_Typelist::root                  root_type;
00444       typedef detail::append_typelist_<root_type>               append_type;
00445 
00446     public:
00447       typedef node<typename append_type::type>                  type;
00448     };
00449 
00450   template<typename Typelist, typename T>
00451     struct contains
00452     {
00453     private:
00454       typedef typename Typelist::root                           root_type;
00455 
00456     public:
00457       enum
00458         {
00459           value = detail::contains_<root_type, T>::value
00460         };
00461     };
00462 
00463   template<typename Typelist, template<typename T> class Pred>
00464     struct filter
00465     {
00466     private:
00467       typedef typename Typelist::root                           root_type;
00468       typedef detail::chain_filter_<root_type, Pred>            filter_type;
00469 
00470     public:
00471       typedef node<typename filter_type::type>                  type;
00472     };
00473 
00474   template<typename Typelist, int i>
00475     struct at_index
00476     {
00477     private:
00478       typedef typename Typelist::root                           root_type;
00479       typedef detail::chain_at_index_<root_type, i>             index_type;
00480 
00481     public:
00482       typedef typename index_type::type                         type;
00483     };
00484 
00485   template<typename Typelist, template<typename T> class Transform>
00486     struct transform
00487     {
00488     private:
00489       typedef typename Typelist::root                           root_type;
00490       typedef detail::chain_transform_<root_type, Transform>    transform_type;
00491 
00492     public:
00493       typedef node<typename transform_type::type>               type;
00494     };
00495 
00496   template<typename Typelist_Typelist>
00497     struct flatten
00498     {
00499     private:
00500       typedef typename Typelist_Typelist::root                  root_type;
00501       typedef typename detail::chain_flatten_<root_type>::type  flatten_type;
00502 
00503     public:
00504       typedef node<flatten_type>                                type;
00505     };
00506 
00507   template<typename Typelist>
00508     struct from_first
00509     {
00510     private:
00511       typedef typename at_index<Typelist, 0>::type              first_type;
00512 
00513     public:
00514       typedef node<chain<first_type, null_type> >               type;
00515     };
00516 
00517   template<typename T1>
00518     struct create1
00519     {
00520       typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)>                type;
00521     };
00522 
00523   template<typename T1, typename T2>
00524     struct create2
00525     {
00526       typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)>             type;
00527     };
00528 
00529   template<typename T1, typename T2, typename T3>
00530     struct create3
00531     {
00532       typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)>          type;
00533     };
00534 
00535   template<typename T1, typename T2, typename T3, typename T4>
00536     struct create4
00537     {
00538       typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)>       type;
00539     };
00540 
00541   template<typename T1, typename T2, typename T3,
00542            typename T4, typename T5>
00543     struct create5
00544     {
00545       typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)>    type;
00546     };
00547 
00548   template<typename T1, typename T2, typename T3,
00549            typename T4, typename T5, typename T6>
00550     struct create6
00551     {
00552       typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type;
00553     };
00554 } // namespace typelist
00555 _GLIBCXX_END_NAMESPACE_VERSION
00556 } // namespace
00557 
00558 
00559 #endif