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