Home | History | Annotate | Download | only in ext
      1 // -*- C++ -*-
      2 
      3 // Copyright (C) 2005-2013 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 #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) >
    390 #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) >
    391 #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) >
    392 #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) >
    393 #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) >
    394 
    395 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
    396 {
    397 _GLIBCXX_BEGIN_NAMESPACE_VERSION
    398 
    399 namespace typelist
    400 {
    401   template<typename Fn, typename Typelist>
    402     void
    403     apply(Fn& fn, Typelist)
    404     {
    405       detail::apply_<Fn, typename Typelist::root> a;
    406       a(fn);
    407     }
    408 
    409   template<typename Fn, typename Typelist>
    410     void
    411     apply_generator(Fn& fn, Typelist)
    412     {
    413       detail::apply_generator1_<Fn, typename Typelist::root> a;
    414       a(fn);
    415     }
    416 
    417   template<typename Fn, typename TypelistT, typename TypelistV>
    418     void
    419     apply_generator(Fn& fn, TypelistT, TypelistV)
    420     {
    421       typedef typename TypelistT::root rootT;
    422       typedef typename TypelistV::root rootV;
    423       detail::apply_generator2_<Fn, rootT, rootV> a;
    424       a(fn);
    425     }
    426 
    427   template<typename Typelist0, typename Typelist1>
    428     struct append
    429     {
    430     private:
    431       typedef typename Typelist0::root 				root0_type;
    432       typedef typename Typelist1::root 				root1_type;
    433       typedef detail::append_<root0_type, root1_type> 		append_type;
    434 
    435     public:
    436       typedef node<typename append_type::type> 			type;
    437     };
    438 
    439   template<typename Typelist_Typelist>
    440     struct append_typelist
    441     {
    442     private:
    443       typedef typename Typelist_Typelist::root 		      	root_type;
    444       typedef detail::append_typelist_<root_type> 		append_type;
    445 
    446     public:
    447       typedef node<typename append_type::type> 			type;
    448     };
    449 
    450   template<typename Typelist, typename T>
    451     struct contains
    452     {
    453     private:
    454       typedef typename Typelist::root 				root_type;
    455 
    456     public:
    457       enum
    458 	{
    459 	  value = detail::contains_<root_type, T>::value
    460 	};
    461     };
    462 
    463   template<typename Typelist, template<typename T> class Pred>
    464     struct filter
    465     {
    466     private:
    467       typedef typename Typelist::root 				root_type;
    468       typedef detail::chain_filter_<root_type, Pred> 		filter_type;
    469 
    470     public:
    471       typedef node<typename filter_type::type> 	       		type;
    472     };
    473 
    474   template<typename Typelist, int i>
    475     struct at_index
    476     {
    477     private:
    478       typedef typename Typelist::root 				root_type;
    479       typedef detail::chain_at_index_<root_type, i> 		index_type;
    480 
    481     public:
    482       typedef typename index_type::type 			type;
    483     };
    484 
    485   template<typename Typelist, template<typename T> class Transform>
    486     struct transform
    487     {
    488     private:
    489       typedef typename Typelist::root 				root_type;
    490       typedef detail::chain_transform_<root_type, Transform> 	transform_type;
    491 
    492     public:
    493       typedef node<typename transform_type::type> 		type;
    494     };
    495 
    496   template<typename Typelist_Typelist>
    497     struct flatten
    498     {
    499     private:
    500       typedef typename Typelist_Typelist::root 		      	root_type;
    501       typedef typename detail::chain_flatten_<root_type>::type 	flatten_type;
    502 
    503     public:
    504       typedef node<flatten_type> 				type;
    505     };
    506 
    507   template<typename Typelist>
    508     struct from_first
    509     {
    510     private:
    511       typedef typename at_index<Typelist, 0>::type 		first_type;
    512 
    513     public:
    514       typedef node<chain<first_type, null_type> > 		type;
    515     };
    516 
    517   template<typename T1>
    518     struct create1
    519     {
    520       typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> 		type;
    521     };
    522 
    523   template<typename T1, typename T2>
    524     struct create2
    525     {
    526       typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> 		type;
    527     };
    528 
    529   template<typename T1, typename T2, typename T3>
    530     struct create3
    531     {
    532       typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)>		type;
    533     };
    534 
    535   template<typename T1, typename T2, typename T3, typename T4>
    536     struct create4
    537     {
    538       typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)>	type;
    539     };
    540 
    541   template<typename T1, typename T2, typename T3,
    542 	   typename T4, typename T5>
    543     struct create5
    544     {
    545       typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)>	type;
    546     };
    547 
    548   template<typename T1, typename T2, typename T3,
    549 	   typename T4, typename T5, typename T6>
    550     struct create6
    551     {
    552       typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)>	type;
    553     };
    554 } // namespace typelist
    555 _GLIBCXX_END_NAMESPACE_VERSION
    556 } // namespace
    557 
    558 
    559 #endif
    560