OSDN Git Service

b7cd95434e6c9edea17b1be20a40279bcbb0c307
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / ext / typelist.h
1 // -*- C++ -*-
2
3 // Copyright (C) 2005, 2006 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 2, 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 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING.  If not, write to the Free
18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 // USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
31
32 // Permission to use, copy, modify, sell, and distribute this software
33 // is hereby granted without fee, provided that the above copyright
34 // notice appears in all copies, and that both that copyright notice and
35 // this permission notice appear in supporting documentation. None of
36 // the above authors, nor IBM Haifa Research Laboratories, make any
37 // representation about the suitability of this software for any
38 // purpose. It is provided "as is" without express or implied warranty.
39
40 /**
41  * @file typelist.h
42  * Contains typelist_chain definitions.
43  * Typelists are an idea by Andrei Alexandrescu.
44  */
45
46 #ifndef _TYPELIST_H
47 #define _TYPELIST_H 1
48
49 #include <ext/type_traits.h>
50
51 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
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   template<typename Fn, class Typelist>
75     void
76     apply(Fn&, Typelist);
77
78   template<typename Typelist0, typename Typelist1>
79     struct append;
80
81   template<typename Typelist_Typelist>
82     struct append_typelist;
83
84   template<typename Typelist, typename T>
85     struct contains;
86  
87   template<typename Typelist, template<typename T> class Pred>
88     struct filter;
89
90   template<typename Typelist, int i>
91     struct at_index;
92
93   template<typename Typelist, template<typename T> class Transform>
94     struct transform;
95
96   template<typename Typelist_Typelist>
97     struct flatten;
98
99   template<typename Typelist>
100     struct from_first;
101
102   template<typename T1>
103     struct create1;
104
105   template<typename T1, typename T2>
106     struct create2;
107
108   template<typename T1, typename T2, typename T3>
109     struct create3;
110
111   template<typename T1, typename T2, typename T3, typename T4>
112     struct create4;
113
114   template<typename T1, typename T2, typename T3, typename T4, typename T5>
115     struct create5;
116
117   template<typename T1, typename T2, typename T3, 
118            typename T4, typename T5, typename T6>
119     struct create6;
120 } // namespace typelist
121
122 _GLIBCXX_END_NAMESPACE
123
124
125 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
126
127 namespace typelist 
128 {
129 namespace detail
130 {
131   template<typename Fn, typename Typelist_Chain>
132     struct apply_;
133
134   template<typename Fn, typename Hd, typename Tl>
135     struct apply_<Fn, chain<Hd, Tl> >
136     {
137       void
138       operator() (Fn& f)
139       {
140         f.operator()(Hd());
141         apply_<Fn, Tl> next;
142         next(f);
143       }
144   };
145
146   template<typename Fn>
147     struct apply_<Fn, null_type>
148     {
149       void
150       operator()(Fn&) { }
151   };
152
153   template<typename Typelist_Chain0, typename Typelist_Chain1>
154     struct append_;
155
156   template<typename Hd, typename Tl, typename Typelist_Chain>
157     struct append_<chain<Hd, Tl>, Typelist_Chain>
158     {
159     private:
160       typedef append_<Tl, Typelist_Chain>                       append_type;
161
162     public:
163       typedef chain<Hd, typename append_type::type>             type;
164     };
165
166   template<typename Typelist_Chain>
167     struct append_<null_type, Typelist_Chain>
168     {
169       typedef Typelist_Chain                                    type;
170     };
171
172   template<typename Typelist_Chain>
173     struct append_<Typelist_Chain, null_type>
174     {
175       typedef Typelist_Chain                                    type;
176     };
177
178   template<>
179     struct append_<null_type, null_type>
180     {
181       typedef null_type                                         type;
182     };
183
184   template<typename Typelist_Typelist_Chain>
185     struct append_typelist_;
186
187   template<typename Hd>
188     struct append_typelist_<chain<Hd, null_type> >
189     {
190       typedef chain<Hd, null_type>                              type;
191     };
192
193   template<typename Hd, typename Tl>
194     struct append_typelist_<chain< Hd, Tl> >
195     {
196     private:
197       typedef typename append_typelist_<Tl>::type               rest_type;
198       
199     public:
200       typedef typename append<Hd, node<rest_type> >::type::root type;
201     };
202
203   template<typename Typelist_Chain, typename T>
204     struct contains_;
205
206   template<typename T>
207     struct contains_<null_type, T>
208     {
209       enum
210         {
211           value = false
212         };
213     };
214
215   template<typename Hd, typename Tl, typename T>
216     struct contains_<chain<Hd, Tl>, T>
217     {
218       enum
219         {
220           value = contains_<Tl, T>::value
221         };
222     };
223   
224   template<typename Tl, typename T>
225     struct contains_<chain<T, Tl>, T>
226     {
227       enum
228         {
229           value = true
230         };
231     };
232
233   template<typename Typelist_Chain, template<typename T> class Pred>
234     struct chain_filter_;
235
236   template<template<typename T> class Pred>
237     struct chain_filter_<null_type, Pred>
238     {
239       typedef null_type                                         type;
240   };
241
242   template<typename Hd, typename Tl, template<typename T> class Pred>
243     struct chain_filter_<chain<Hd, Tl>, Pred>
244     {
245     private:
246       enum
247         {
248           include_hd = Pred<Hd>::value
249         };
250       
251       typedef typename chain_filter_<Tl, Pred>::type            rest_type;
252       typedef chain<Hd, rest_type>                              chain_type;
253
254     public:
255       typedef typename __conditional_type<include_hd, chain_type, rest_type>::__type type;
256   };
257
258   template<typename Typelist_Chain, int i>
259     struct chain_at_index_;
260
261   template<typename Hd, typename Tl>
262     struct chain_at_index_<chain<Hd, Tl>, 0>
263     {
264       typedef Hd                                                type;
265     };
266   
267   template<typename Hd, typename Tl, int i>
268     struct chain_at_index_<chain<Hd, Tl>, i>
269     {
270       typedef typename chain_at_index_<Tl, i - 1>::type         type;
271     };
272
273   template<class Typelist_Chain, template<typename T> class Transform>
274     struct chain_transform_;
275
276   template<template<typename T> class Transform>
277     struct chain_transform_<null_type, Transform>
278     {
279       typedef null_type                                         type;
280     };
281   
282   template<class Hd, class Tl, template<typename T> class Transform>
283     struct chain_transform_<chain<Hd, Tl>, Transform>
284     {
285     private:
286       typedef typename chain_transform_<Tl, Transform>::type    rest_type;
287       typedef typename Transform<Hd>::type                      transform_type;
288
289     public:
290       typedef chain<transform_type, rest_type>                  type;
291     };
292
293   template<typename Typelist_Typelist_Chain>
294     struct chain_flatten_;
295
296   template<typename Hd_Tl>
297   struct chain_flatten_<chain<Hd_Tl, null_type> >
298   {
299     typedef typename Hd_Tl::root                                type;
300   };
301
302   template<typename Hd_Typelist, class Tl_Typelist>
303   struct chain_flatten_<chain<Hd_Typelist, Tl_Typelist> >
304   {
305   private:
306     typedef typename chain_flatten_<Tl_Typelist>::type          rest_type;
307     typedef append<Hd_Typelist, node<rest_type> >               append_type;
308   public:
309     typedef typename append_type::type::root                    type;
310   };
311 } // namespace detail
312 } // namespace typelist
313
314 _GLIBCXX_END_NAMESPACE
315
316 #define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain<X0, __gnu_cxx::typelist::null_type>
317 #define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN1(X1) >
318 #define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN2(X1, X2) >
319 #define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN3(X1, X2, X3) >
320 #define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN4(X1, X2, X3, X4) >
321 #define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN5(X1, X2, X3, X4, X5) >
322 #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) >
323 #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) >
324 #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) >
325 #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) >
326 #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) >
327 #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) >
328 #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) >
329 #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) >
330 #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) >
331
332 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
333
334 namespace typelist
335 {
336   template<typename Fn, class Typelist>
337     void
338     apply(Fn& fn, Typelist)
339     {
340       detail::apply_<Fn, typename Typelist::root> a;
341       a(fn);
342     }
343
344   template<typename Typelist0, typename Typelist1>
345     struct append
346     {
347     private:
348       typedef typename Typelist0::root                          root0_type;
349       typedef typename Typelist1::root                          root1_type;
350       typedef detail::append_<root0_type, root1_type>           append_type;
351
352     public:
353       typedef node<typename append_type::type>                  type;
354     };
355
356   template<typename Typelist_Typelist>
357     struct append_typelist
358     {
359     private:
360       typedef typename Typelist_Typelist::root                  root_type;
361       typedef detail::append_typelist_<root_type>               append_type;
362
363     public:
364       typedef node<typename append_type::type>                  type;
365     };
366
367   template<typename Typelist, typename T>
368     struct contains
369     {
370     private:
371       typedef typename Typelist::root                           root_type;
372
373     public:
374       enum
375         {
376           value = detail::contains_<root_type, T>::value
377         };
378     };
379
380   template<typename Typelist, template<typename T> class Pred>
381     struct filter
382     {
383     private:
384       typedef typename Typelist::root                           root_type;
385       typedef detail::chain_filter_<root_type, Pred>            filter_type;
386
387     public:
388       typedef node<typename filter_type::type>                  type;
389     };
390
391   template<typename Typelist, int i>
392     struct at_index
393     {
394     private:
395       typedef typename Typelist::root                           root_type;
396       typedef detail::chain_at_index_<root_type, i>             index_type;
397       
398     public:
399       typedef typename index_type::type                         type;
400     };
401
402   template<typename Typelist, template<typename T> class Transform>
403     struct transform
404     {
405     private:
406       typedef typename Typelist::root                           root_type;
407       typedef detail::chain_transform_<root_type, Transform>    transform_type;
408
409     public:
410       typedef node<typename transform_type::type>               type;
411     };
412
413   template<typename Typelist_Typelist>
414     struct flatten
415     {
416     private:
417       typedef typename Typelist_Typelist::root                  root_type;
418       typedef typename detail::chain_flatten_<root_type>::type  flatten_type;
419
420     public:
421       typedef node<flatten_type>                                type;
422     };
423
424   template<typename Typelist>
425     struct from_first
426     {
427     private:
428       typedef typename at_index<Typelist, 0>::type              first_type;
429
430     public:
431       typedef node<chain<first_type, null_type> >               type;
432     };
433
434   template<typename T1>
435     struct create1
436     {
437       typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)>                type;
438     };
439
440   template<typename T1, typename T2>
441     struct create2
442     {
443       typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)>             type;
444     };
445
446   template<typename T1, typename T2, typename T3>
447     struct create3
448     {
449       typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)>          type;
450     };
451
452   template<typename T1, typename T2, typename T3, typename T4>
453     struct create4
454     {
455       typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)>       type;
456     };
457
458   template<typename T1, typename T2, typename T3, 
459            typename T4, typename T5>
460     struct create5
461     {
462       typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)>    type;
463     };
464
465   template<typename T1, typename T2, typename T3, 
466            typename T4, typename T5, typename T6>
467     struct create6
468     {
469       typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type;
470     };
471 } // namespace typelist
472 _GLIBCXX_END_NAMESPACE
473
474
475 #endif
476