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