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