Home | History | Annotate | Download | only in ext
      1 // -*- C++ -*-
      2 
      3 // Copyright (C) 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
     26 
     27 // Permission to use, copy, modify, sell, and distribute this software
     28 // is hereby granted without fee, provided that the above copyright
     29 // notice appears in all copies, and that both that copyright notice and
     30 // this permission notice appear in supporting documentation. None of
     31 // the above authors, nor IBM Haifa Research Laboratories, make any
     32 // representation about the suitability of this software for any
     33 // purpose. It is provided "as is" without express or implied warranty.
     34 
     35 /**
     36  *  @file ext/typelist.h
     37  *  This file is a GNU extension to the Standard C++ Library.
     38  *
     39  *  Contains typelist_chain definitions.
     40  *  Typelists are an idea by Andrei Alexandrescu.
     41  */
     42 
     43 #ifndef _TYPELIST_H
     44 #define _TYPELIST_H 1
     45 
     46 #include <ext/type_traits.h>
     47 
     48 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
     49 {
     50 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     51 
     52 /** @namespace __gnu_cxx::typelist
     53  *  @brief GNU typelist extensions for public compile-time use.
     54 */
     55 namespace typelist
     56 {
     57   struct null_type { };
     58 
     59   template<typename Root>
     60     struct node
     61     {
     62       typedef Root 	root;
     63     };
     64 
     65   // Forward declarations of functors.
     66   template<typename Hd, typename Typelist>
     67     struct chain
     68     {
     69       typedef Hd 	head;
     70       typedef Typelist 	tail;
     71     };
     72 
     73   // Apply all typelist types to unary functor.
     74   template<typename Fn, typename Typelist>
     75     void
     76     apply(Fn&, Typelist);
     77 
     78   /// Apply all typelist types to generator functor.
     79   template<typename Gn, typename Typelist>
     80     void
     81     apply_generator(Gn&, Typelist);
     82 
     83   // Apply all typelist types and values to generator functor.
     84   template<typename Gn, typename TypelistT, typename TypelistV>
     85     void
     86     apply_generator(Gn&, TypelistT, TypelistV);
     87 
     88   template<typename Typelist0, typename Typelist1>
     89     struct append;
     90 
     91   template<typename Typelist_Typelist>
     92     struct append_typelist;
     93 
     94   template<typename Typelist, typename T>
     95     struct contains;
     96 
     97   template<typename Typelist, template<typename T> class Pred>
     98     struct filter;
     99 
    100   template<typename Typelist, int i>
    101     struct at_index;
    102 
    103   template<typename Typelist, template<typename T> class Transform>
    104     struct transform;
    105 
    106   template<typename Typelist_Typelist>
    107     struct flatten;
    108 
    109   template<typename Typelist>
    110     struct from_first;
    111 
    112   template<typename T1>
    113     struct create1;
    114 
    115   template<typename T1, typename T2>
    116     struct create2;
    117 
    118   template<typename T1, typename T2, typename T3>
    119     struct create3;
    120 
    121   template<typename T1, typename T2, typename T3, typename T4>
    122     struct create4;
    123 
    124   template<typename T1, typename T2, typename T3, typename T4, typename T5>
    125     struct create5;
    126 
    127   template<typename T1, typename T2, typename T3,
    128 	   typename T4, typename T5, typename T6>
    129     struct create6;
    130 } // namespace typelist
    131 
    132 _GLIBCXX_END_NAMESPACE_VERSION
    133 } // namespace
    134 
    135 
    136 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
    137 {
    138 _GLIBCXX_BEGIN_NAMESPACE_VERSION
    139 
    140 namespace typelist
    141 {
    142 namespace detail
    143 {
    144   template<typename Fn, typename Typelist_Chain>
    145     struct apply_;
    146 
    147   template<typename Fn, typename Hd, typename Tl>
    148     struct apply_<Fn, chain<Hd, Tl> >
    149     {
    150       void
    151       operator()(Fn& f)
    152       {
    153 	f.operator()(Hd());
    154 	apply_<Fn, Tl> next;
    155 	next(f);
    156       }
    157     };
    158 
    159   template<typename Fn>
    160     struct apply_<Fn, null_type>
    161     {
    162       void
    163       operator()(Fn&) { }
    164     };
    165 
    166   template<typename Gn, typename Typelist_Chain>
    167     struct apply_generator1_;
    168 
    169   template<typename Gn, typename Hd, typename Tl>
    170     struct apply_generator1_<Gn, chain<Hd, Tl> >
    171     {
    172       void
    173       operator()(Gn& g)
    174       {
    175 	g.template operator()<Hd>();
    176 	apply_generator1_<Gn, Tl> next;
    177 	next(g);
    178       }
    179     };
    180 
    181   template<typename Gn>
    182     struct apply_generator1_<Gn, null_type>
    183     {
    184       void
    185       operator()(Gn&) { }
    186     };
    187 
    188   template<typename Gn, typename TypelistT_Chain, typename TypelistV_Chain>
    189     struct apply_generator2_;
    190 
    191   template<typename Gn, typename Hd1, typename TlT, typename Hd2, typename TlV>
    192     struct apply_generator2_<Gn, chain<Hd1, TlT>, chain<Hd2, TlV> >
    193     {
    194       void
    195       operator()(Gn& g)
    196       {
    197 	g.template operator()<Hd1, Hd2>();
    198 	apply_generator2_<Gn, TlT, TlV> next;
    199 	next(g);
    200       }
    201     };
    202 
    203   template<typename Gn>
    204     struct apply_generator2_<Gn, null_type, null_type>
    205     {
    206       void
    207       operator()(Gn&) { }
    208     };
    209 
    210   template<typename Typelist_Chain0, typename Typelist_Chain1>
    211     struct append_;
    212 
    213   template<typename Hd, typename Tl, typename Typelist_Chain>
    214     struct append_<chain<Hd, Tl>, Typelist_Chain>
    215     {
    216     private:
    217       typedef append_<Tl, Typelist_Chain> 			append_type;
    218 
    219     public:
    220       typedef chain<Hd, typename append_type::type> 		type;
    221     };
    222 
    223   template<typename Typelist_Chain>
    224     struct append_<null_type, Typelist_Chain>
    225     {
    226       typedef Typelist_Chain 			      		type;
    227     };
    228 
    229   template<typename Typelist_Chain>
    230     struct append_<Typelist_Chain, null_type>
    231     {
    232       typedef Typelist_Chain 					type;
    233     };
    234 
    235   template<>
    236     struct append_<null_type, null_type>
    237     {
    238       typedef null_type 					type;
    239     };
    240 
    241   template<typename Typelist_Typelist_Chain>
    242     struct append_typelist_;
    243 
    244   template<typename Hd>
    245     struct append_typelist_<chain<Hd, null_type> >
    246     {
    247       typedef chain<Hd, null_type> 				type;
    248     };
    249 
    250   template<typename Hd, typename Tl>
    251     struct append_typelist_<chain< Hd, Tl> >
    252     {
    253     private:
    254       typedef typename append_typelist_<Tl>::type 		rest_type;
    255 
    256     public:
    257       typedef typename append<Hd, node<rest_type> >::type::root	type;
    258     };
    259 
    260   template<typename Typelist_Chain, typename T>
    261     struct contains_;
    262 
    263   template<typename T>
    264     struct contains_<null_type, T>
    265     {
    266       enum
    267 	{
    268 	  value = false
    269 	};
    270     };
    271 
    272   template<typename Hd, typename Tl, typename T>
    273     struct contains_<chain<Hd, Tl>, T>
    274     {
    275       enum
    276 	{
    277 	  value = contains_<Tl, T>::value
    278 	};
    279     };
    280 
    281   template<typename Tl, typename T>
    282     struct contains_<chain<T, Tl>, T>
    283     {
    284       enum
    285 	{
    286 	  value = true
    287 	};
    288     };
    289 
    290   template<typename Typelist_Chain, template<typename T> class Pred>
    291     struct chain_filter_;
    292 
    293   template<template<typename T> class Pred>
    294     struct chain_filter_<null_type, Pred>
    295     {
    296       typedef null_type 					type;
    297   };
    298 
    299   template<typename Hd, typename Tl, template<typename T> class Pred>
    300     struct chain_filter_<chain<Hd, Tl>, Pred>
    301     {
    302     private:
    303       enum
    304 	{
    305 	  include_hd = Pred<Hd>::value
    306 	};
    307 
    308       typedef typename chain_filter_<Tl, Pred>::type 		rest_type;
    309       typedef chain<Hd, rest_type> 				chain_type;
    310 
    311     public:
    312       typedef typename __conditional_type<include_hd, chain_type, rest_type>::__type type;
    313   };
    314 
    315   template<typename Typelist_Chain, int i>
    316     struct chain_at_index_;
    317 
    318   template<typename Hd, typename Tl>
    319     struct chain_at_index_<chain<Hd, Tl>, 0>
    320     {
    321       typedef Hd 						type;
    322     };
    323 
    324   template<typename Hd, typename Tl, int i>
    325     struct chain_at_index_<chain<Hd, Tl>, i>
    326     {
    327       typedef typename chain_at_index_<Tl, i - 1>::type 	type;
    328     };
    329 
    330   template<class Typelist_Chain, template<typename T> class Transform>
    331     struct chain_transform_;
    332 
    333   template<template<typename T> class Transform>
    334     struct chain_transform_<null_type, Transform>
    335     {
    336       typedef null_type 					type;
    337     };
    338 
    339   template<class Hd, class Tl, template<typename T> class Transform>
    340     struct chain_transform_<chain<Hd, Tl>, Transform>
    341     {
    342     private:
    343       typedef typename chain_transform_<Tl, Transform>::type 	rest_type;
    344       typedef typename Transform<Hd>::type 			transform_type;
    345 
    346     public:
    347       typedef chain<transform_type, rest_type> 			type;
    348     };
    349 
    350   template<typename Typelist_Typelist_Chain>
    351     struct chain_flatten_;
    352 
    353   template<typename Hd_Tl>
    354     struct chain_flatten_<chain<Hd_Tl, null_type> >
    355     {
    356       typedef typename Hd_Tl::root 				type;
    357     };
    358 
    359   template<typename Hd_Typelist, class Tl_Typelist>
    360     struct chain_flatten_<chain<Hd_Typelist, Tl_Typelist> >
    361     {
    362     private:
    363       typedef typename chain_flatten_<Tl_Typelist>::type 	rest_type;
    364       typedef append<Hd_Typelist, node<rest_type> >		append_type;
    365     public:
    366       typedef typename append_type::type::root 			type;
    367     };
    368 } // namespace detail
    369 } // namespace typelist
    370 
    371 _GLIBCXX_END_NAMESPACE_VERSION
    372 } // namespace
    373 
    374 #define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain<X0, __gnu_cxx::typelist::null_type>
    375 #define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN1(X1) >
    376 #define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN2(X1, X2) >
    377 #define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN3(X1, X2, X3) >
    378 #define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN4(X1, X2, X3, X4) >
    379 #define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN5(X1, X2, X3, X4, X5) >
    380 #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) >
    381 #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) >
    382 #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) >
    383 #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) >
    384 #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) >
    385 #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) >
    386 #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) >
    387 #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) >
    388 #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) >
    389 
    390 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
    391 {
    392 _GLIBCXX_BEGIN_NAMESPACE_VERSION
    393 
    394 namespace typelist
    395 {
    396   template<typename Fn, typename Typelist>
    397     void
    398     apply(Fn& fn, Typelist)
    399     {
    400       detail::apply_<Fn, typename Typelist::root> a;
    401       a(fn);
    402     }
    403 
    404   template<typename Fn, typename Typelist>
    405     void
    406     apply_generator(Fn& fn, Typelist)
    407     {
    408       detail::apply_generator1_<Fn, typename Typelist::root> a;
    409       a(fn);
    410     }
    411 
    412   template<typename Fn, typename TypelistT, typename TypelistV>
    413     void
    414     apply_generator(Fn& fn, TypelistT, TypelistV)
    415     {
    416       typedef typename TypelistT::root rootT;
    417       typedef typename TypelistV::root rootV;
    418       detail::apply_generator2_<Fn, rootT, rootV> a;
    419       a(fn);
    420     }
    421 
    422   template<typename Typelist0, typename Typelist1>
    423     struct append
    424     {
    425     private:
    426       typedef typename Typelist0::root 				root0_type;
    427       typedef typename Typelist1::root 				root1_type;
    428       typedef detail::append_<root0_type, root1_type> 		append_type;
    429 
    430     public:
    431       typedef node<typename append_type::type> 			type;
    432     };
    433 
    434   template<typename Typelist_Typelist>
    435     struct append_typelist
    436     {
    437     private:
    438       typedef typename Typelist_Typelist::root 		      	root_type;
    439       typedef detail::append_typelist_<root_type> 		append_type;
    440 
    441     public:
    442       typedef node<typename append_type::type> 			type;
    443     };
    444 
    445   template<typename Typelist, typename T>
    446     struct contains
    447     {
    448     private:
    449       typedef typename Typelist::root 				root_type;
    450 
    451     public:
    452       enum
    453 	{
    454 	  value = detail::contains_<root_type, T>::value
    455 	};
    456     };
    457 
    458   template<typename Typelist, template<typename T> class Pred>
    459     struct filter
    460     {
    461     private:
    462       typedef typename Typelist::root 				root_type;
    463       typedef detail::chain_filter_<root_type, Pred> 		filter_type;
    464 
    465     public:
    466       typedef node<typename filter_type::type> 	       		type;
    467     };
    468 
    469   template<typename Typelist, int i>
    470     struct at_index
    471     {
    472     private:
    473       typedef typename Typelist::root 				root_type;
    474       typedef detail::chain_at_index_<root_type, i> 		index_type;
    475 
    476     public:
    477       typedef typename index_type::type 			type;
    478     };
    479 
    480   template<typename Typelist, template<typename T> class Transform>
    481     struct transform
    482     {
    483     private:
    484       typedef typename Typelist::root 				root_type;
    485       typedef detail::chain_transform_<root_type, Transform> 	transform_type;
    486 
    487     public:
    488       typedef node<typename transform_type::type> 		type;
    489     };
    490 
    491   template<typename Typelist_Typelist>
    492     struct flatten
    493     {
    494     private:
    495       typedef typename Typelist_Typelist::root 		      	root_type;
    496       typedef typename detail::chain_flatten_<root_type>::type 	flatten_type;
    497 
    498     public:
    499       typedef node<flatten_type> 				type;
    500     };
    501 
    502   template<typename Typelist>
    503     struct from_first
    504     {
    505     private:
    506       typedef typename at_index<Typelist, 0>::type 		first_type;
    507 
    508     public:
    509       typedef node<chain<first_type, null_type> > 		type;
    510     };
    511 
    512   template<typename T1>
    513     struct create1
    514     {
    515       typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> 		type;
    516     };
    517 
    518   template<typename T1, typename T2>
    519     struct create2
    520     {
    521       typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> 		type;
    522     };
    523 
    524   template<typename T1, typename T2, typename T3>
    525     struct create3
    526     {
    527       typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)>		type;
    528     };
    529 
    530   template<typename T1, typename T2, typename T3, typename T4>
    531     struct create4
    532     {
    533       typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)>	type;
    534     };
    535 
    536   template<typename T1, typename T2, typename T3,
    537 	   typename T4, typename T5>
    538     struct create5
    539     {
    540       typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)>	type;
    541     };
    542 
    543   template<typename T1, typename T2, typename T3,
    544 	   typename T4, typename T5, typename T6>
    545     struct create6
    546     {
    547       typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)>	type;
    548     };
    549 } // namespace typelist
    550 _GLIBCXX_END_NAMESPACE_VERSION
    551 } // namespace
    552 
    553 
    554 #endif
    555