Home | History | Annotate | Download | only in ext
      1 // -*- C++ -*-
      2 
      3 // Copyright (C) 2005, 2006, 2008, 2009 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 typelist.h
     37  * Contains typelist_chain definitions.
     38  * Typelists are an idea by Andrei Alexandrescu.
     39  */
     40 
     41 #ifndef _TYPELIST_H
     42 #define _TYPELIST_H 1
     43 
     44 #include <ext/type_traits.h>
     45 
     46 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
     47 
     48 /** @namespace __gnu_cxx::typelist
     49  *  @brief GNU typelist extensions for public compile-time use.
     50 */
     51 namespace typelist
     52 {
     53   struct null_type { };
     54 
     55   template<typename Root>
     56     struct node
     57     {
     58       typedef Root 	root;
     59     };
     60 
     61   // Forward declarations of functors.
     62   template<typename Hd, typename Typelist>
     63     struct chain
     64     {
     65       typedef Hd 	head;
     66       typedef Typelist 	tail;
     67     };
     68 
     69   // Apply all typelist types to unary functor.
     70   template<typename Fn, typename Typelist>
     71     void
     72     apply(Fn&, Typelist);
     73 
     74   /// Apply all typelist types to generator functor.
     75   template<typename Gn, typename Typelist>
     76     void
     77     apply_generator(Gn&, Typelist);
     78 
     79   // Apply all typelist types and values to generator functor.
     80   template<typename Gn, typename TypelistT, typename TypelistV>
     81     void
     82     apply_generator(Gn&, TypelistT, TypelistV);
     83 
     84   template<typename Typelist0, typename Typelist1>
     85     struct append;
     86 
     87   template<typename Typelist_Typelist>
     88     struct append_typelist;
     89 
     90   template<typename Typelist, typename T>
     91     struct contains;
     92 
     93   template<typename Typelist, template<typename T> class Pred>
     94     struct filter;
     95 
     96   template<typename Typelist, int i>
     97     struct at_index;
     98 
     99   template<typename Typelist, template<typename T> class Transform>
    100     struct transform;
    101 
    102   template<typename Typelist_Typelist>
    103     struct flatten;
    104 
    105   template<typename Typelist>
    106     struct from_first;
    107 
    108   template<typename T1>
    109     struct create1;
    110 
    111   template<typename T1, typename T2>
    112     struct create2;
    113 
    114   template<typename T1, typename T2, typename T3>
    115     struct create3;
    116 
    117   template<typename T1, typename T2, typename T3, typename T4>
    118     struct create4;
    119 
    120   template<typename T1, typename T2, typename T3, typename T4, typename T5>
    121     struct create5;
    122 
    123   template<typename T1, typename T2, typename T3,
    124 	   typename T4, typename T5, typename T6>
    125     struct create6;
    126 } // namespace typelist
    127 
    128 _GLIBCXX_END_NAMESPACE
    129 
    130 
    131 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
    132 
    133 namespace typelist
    134 {
    135 namespace detail
    136 {
    137   template<typename Fn, typename Typelist_Chain>
    138     struct apply_;
    139 
    140   template<typename Fn, typename Hd, typename Tl>
    141     struct apply_<Fn, chain<Hd, Tl> >
    142     {
    143       void
    144       operator()(Fn& f)
    145       {
    146 	f.operator()(Hd());
    147 	apply_<Fn, Tl> next;
    148 	next(f);
    149       }
    150     };
    151 
    152   template<typename Fn>
    153     struct apply_<Fn, null_type>
    154     {
    155       void
    156       operator()(Fn&) { }
    157     };
    158 
    159   template<typename Gn, typename Typelist_Chain>
    160     struct apply_generator1_;
    161 
    162   template<typename Gn, typename Hd, typename Tl>
    163     struct apply_generator1_<Gn, chain<Hd, Tl> >
    164     {
    165       void
    166       operator()(Gn& g)
    167       {
    168 	g.template operator()<Hd>();
    169 	apply_generator1_<Gn, Tl> next;
    170 	next(g);
    171       }
    172     };
    173 
    174   template<typename Gn>
    175     struct apply_generator1_<Gn, null_type>
    176     {
    177       void
    178       operator()(Gn&) { }
    179     };
    180 
    181   template<typename Gn, typename TypelistT_Chain, typename TypelistV_Chain>
    182     struct apply_generator2_;
    183 
    184   template<typename Gn, typename Hd1, typename TlT, typename Hd2, typename TlV>
    185     struct apply_generator2_<Gn, chain<Hd1, TlT>, chain<Hd2, TlV> >
    186     {
    187       void
    188       operator()(Gn& g)
    189       {
    190 	g.template operator()<Hd1, Hd2>();
    191 	apply_generator2_<Gn, TlT, TlV> next;
    192 	next(g);
    193       }
    194     };
    195 
    196   template<typename Gn>
    197     struct apply_generator2_<Gn, null_type, null_type>
    198     {
    199       void
    200       operator()(Gn&) { }
    201     };
    202 
    203   template<typename Typelist_Chain0, typename Typelist_Chain1>
    204     struct append_;
    205 
    206   template<typename Hd, typename Tl, typename Typelist_Chain>
    207     struct append_<chain<Hd, Tl>, Typelist_Chain>
    208     {
    209     private:
    210       typedef append_<Tl, Typelist_Chain> 			append_type;
    211 
    212     public:
    213       typedef chain<Hd, typename append_type::type> 		type;
    214     };
    215 
    216   template<typename Typelist_Chain>
    217     struct append_<null_type, Typelist_Chain>
    218     {
    219       typedef Typelist_Chain 			      		type;
    220     };
    221 
    222   template<typename Typelist_Chain>
    223     struct append_<Typelist_Chain, null_type>
    224     {
    225       typedef Typelist_Chain 					type;
    226     };
    227 
    228   template<>
    229     struct append_<null_type, null_type>
    230     {
    231       typedef null_type 					type;
    232     };
    233 
    234   template<typename Typelist_Typelist_Chain>
    235     struct append_typelist_;
    236 
    237   template<typename Hd>
    238     struct append_typelist_<chain<Hd, null_type> >
    239     {
    240       typedef chain<Hd, null_type> 				type;
    241     };
    242 
    243   template<typename Hd, typename Tl>
    244     struct append_typelist_<chain< Hd, Tl> >
    245     {
    246     private:
    247       typedef typename append_typelist_<Tl>::type 		rest_type;
    248 
    249     public:
    250       typedef typename append<Hd, node<rest_type> >::type::root	type;
    251     };
    252 
    253   template<typename Typelist_Chain, typename T>
    254     struct contains_;
    255 
    256   template<typename T>
    257     struct contains_<null_type, T>
    258     {
    259       enum
    260 	{
    261 	  value = false
    262 	};
    263     };
    264 
    265   template<typename Hd, typename Tl, typename T>
    266     struct contains_<chain<Hd, Tl>, T>
    267     {
    268       enum
    269 	{
    270 	  value = contains_<Tl, T>::value
    271 	};
    272     };
    273 
    274   template<typename Tl, typename T>
    275     struct contains_<chain<T, Tl>, T>
    276     {
    277       enum
    278 	{
    279 	  value = true
    280 	};
    281     };
    282 
    283   template<typename Typelist_Chain, template<typename T> class Pred>
    284     struct chain_filter_;
    285 
    286   template<template<typename T> class Pred>
    287     struct chain_filter_<null_type, Pred>
    288     {
    289       typedef null_type 					type;
    290   };
    291 
    292   template<typename Hd, typename Tl, template<typename T> class Pred>
    293     struct chain_filter_<chain<Hd, Tl>, Pred>
    294     {
    295     private:
    296       enum
    297 	{
    298 	  include_hd = Pred<Hd>::value
    299 	};
    300 
    301       typedef typename chain_filter_<Tl, Pred>::type 		rest_type;
    302       typedef chain<Hd, rest_type> 				chain_type;
    303 
    304     public:
    305       typedef typename __conditional_type<include_hd, chain_type, rest_type>::__type type;
    306   };
    307 
    308   template<typename Typelist_Chain, int i>
    309     struct chain_at_index_;
    310 
    311   template<typename Hd, typename Tl>
    312     struct chain_at_index_<chain<Hd, Tl>, 0>
    313     {
    314       typedef Hd 						type;
    315     };
    316 
    317   template<typename Hd, typename Tl, int i>
    318     struct chain_at_index_<chain<Hd, Tl>, i>
    319     {
    320       typedef typename chain_at_index_<Tl, i - 1>::type 	type;
    321     };
    322 
    323   template<class Typelist_Chain, template<typename T> class Transform>
    324     struct chain_transform_;
    325 
    326   template<template<typename T> class Transform>
    327     struct chain_transform_<null_type, Transform>
    328     {
    329       typedef null_type 					type;
    330     };
    331 
    332   template<class Hd, class Tl, template<typename T> class Transform>
    333     struct chain_transform_<chain<Hd, Tl>, Transform>
    334     {
    335     private:
    336       typedef typename chain_transform_<Tl, Transform>::type 	rest_type;
    337       typedef typename Transform<Hd>::type 			transform_type;
    338 
    339     public:
    340       typedef chain<transform_type, rest_type> 			type;
    341     };
    342 
    343   template<typename Typelist_Typelist_Chain>
    344     struct chain_flatten_;
    345 
    346   template<typename Hd_Tl>
    347     struct chain_flatten_<chain<Hd_Tl, null_type> >
    348     {
    349       typedef typename Hd_Tl::root 				type;
    350     };
    351 
    352   template<typename Hd_Typelist, class Tl_Typelist>
    353     struct chain_flatten_<chain<Hd_Typelist, Tl_Typelist> >
    354     {
    355     private:
    356       typedef typename chain_flatten_<Tl_Typelist>::type 	rest_type;
    357       typedef append<Hd_Typelist, node<rest_type> >		append_type;
    358     public:
    359       typedef typename append_type::type::root 			type;
    360     };
    361 } // namespace detail
    362 } // namespace typelist
    363 
    364 _GLIBCXX_END_NAMESPACE
    365 
    366 #define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain<X0, __gnu_cxx::typelist::null_type>
    367 #define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN1(X1) >
    368 #define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN2(X1, X2) >
    369 #define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN3(X1, X2, X3) >
    370 #define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN4(X1, X2, X3, X4) >
    371 #define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN5(X1, X2, X3, X4, X5) >
    372 #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) >
    373 #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) >
    374 #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) >
    375 #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) >
    376 #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) >
    377 #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) >
    378 #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) >
    379 #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) >
    380 #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) >
    381 
    382 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
    383 
    384 namespace typelist
    385 {
    386   template<typename Fn, typename Typelist>
    387     void
    388     apply(Fn& fn, Typelist)
    389     {
    390       detail::apply_<Fn, typename Typelist::root> a;
    391       a(fn);
    392     }
    393 
    394   template<typename Fn, typename Typelist>
    395     void
    396     apply_generator(Fn& fn, Typelist)
    397     {
    398       detail::apply_generator1_<Fn, typename Typelist::root> a;
    399       a(fn);
    400     }
    401 
    402   template<typename Fn, typename TypelistT, typename TypelistV>
    403     void
    404     apply_generator(Fn& fn, TypelistT, TypelistV)
    405     {
    406       typedef typename TypelistT::root rootT;
    407       typedef typename TypelistV::root rootV;
    408       detail::apply_generator2_<Fn, rootT, rootV> a;
    409       a(fn);
    410     }
    411 
    412   template<typename Typelist0, typename Typelist1>
    413     struct append
    414     {
    415     private:
    416       typedef typename Typelist0::root 				root0_type;
    417       typedef typename Typelist1::root 				root1_type;
    418       typedef detail::append_<root0_type, root1_type> 		append_type;
    419 
    420     public:
    421       typedef node<typename append_type::type> 			type;
    422     };
    423 
    424   template<typename Typelist_Typelist>
    425     struct append_typelist
    426     {
    427     private:
    428       typedef typename Typelist_Typelist::root 		      	root_type;
    429       typedef detail::append_typelist_<root_type> 		append_type;
    430 
    431     public:
    432       typedef node<typename append_type::type> 			type;
    433     };
    434 
    435   template<typename Typelist, typename T>
    436     struct contains
    437     {
    438     private:
    439       typedef typename Typelist::root 				root_type;
    440 
    441     public:
    442       enum
    443 	{
    444 	  value = detail::contains_<root_type, T>::value
    445 	};
    446     };
    447 
    448   template<typename Typelist, template<typename T> class Pred>
    449     struct filter
    450     {
    451     private:
    452       typedef typename Typelist::root 				root_type;
    453       typedef detail::chain_filter_<root_type, Pred> 		filter_type;
    454 
    455     public:
    456       typedef node<typename filter_type::type> 	       		type;
    457     };
    458 
    459   template<typename Typelist, int i>
    460     struct at_index
    461     {
    462     private:
    463       typedef typename Typelist::root 				root_type;
    464       typedef detail::chain_at_index_<root_type, i> 		index_type;
    465 
    466     public:
    467       typedef typename index_type::type 			type;
    468     };
    469 
    470   template<typename Typelist, template<typename T> class Transform>
    471     struct transform
    472     {
    473     private:
    474       typedef typename Typelist::root 				root_type;
    475       typedef detail::chain_transform_<root_type, Transform> 	transform_type;
    476 
    477     public:
    478       typedef node<typename transform_type::type> 		type;
    479     };
    480 
    481   template<typename Typelist_Typelist>
    482     struct flatten
    483     {
    484     private:
    485       typedef typename Typelist_Typelist::root 		      	root_type;
    486       typedef typename detail::chain_flatten_<root_type>::type 	flatten_type;
    487 
    488     public:
    489       typedef node<flatten_type> 				type;
    490     };
    491 
    492   template<typename Typelist>
    493     struct from_first
    494     {
    495     private:
    496       typedef typename at_index<Typelist, 0>::type 		first_type;
    497 
    498     public:
    499       typedef node<chain<first_type, null_type> > 		type;
    500     };
    501 
    502   template<typename T1>
    503     struct create1
    504     {
    505       typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> 		type;
    506     };
    507 
    508   template<typename T1, typename T2>
    509     struct create2
    510     {
    511       typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> 		type;
    512     };
    513 
    514   template<typename T1, typename T2, typename T3>
    515     struct create3
    516     {
    517       typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)>		type;
    518     };
    519 
    520   template<typename T1, typename T2, typename T3, typename T4>
    521     struct create4
    522     {
    523       typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)>	type;
    524     };
    525 
    526   template<typename T1, typename T2, typename T3,
    527 	   typename T4, typename T5>
    528     struct create5
    529     {
    530       typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)>	type;
    531     };
    532 
    533   template<typename T1, typename T2, typename T3,
    534 	   typename T4, typename T5, typename T6>
    535     struct create6
    536     {
    537       typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)>	type;
    538     };
    539 } // namespace typelist
    540 _GLIBCXX_END_NAMESPACE
    541 
    542 
    543 #endif
    544 
    545