1169691Skan// -*- C++ -*-
2169691Skan
3169691Skan// Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4169691Skan//
5169691Skan// This file is part of the GNU ISO C++ Library.  This library is free
6169691Skan// software; you can redistribute it and/or modify it under the
7169691Skan// terms of the GNU General Public License as published by the
8169691Skan// Free Software Foundation; either version 2, or (at your option)
9169691Skan// any later version.
10169691Skan
11169691Skan// This library is distributed in the hope that it will be useful,
12169691Skan// but WITHOUT ANY WARRANTY; without even the implied warranty of
13169691Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14169691Skan// GNU General Public License for more details.
15169691Skan
16169691Skan// You should have received a copy of the GNU General Public License along
17169691Skan// with this library; see the file COPYING.  If not, write to the Free
18169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19169691Skan// USA.
20169691Skan
21169691Skan// As a special exception, you may use this file as part of a free software
22169691Skan// library without restriction.  Specifically, if other files instantiate
23169691Skan// templates or use macros or inline functions from this file, or you compile
24169691Skan// this file and link it with other files to produce an executable, this
25169691Skan// file does not by itself cause the resulting executable to be covered by
26169691Skan// the GNU General Public License.  This exception does not however
27169691Skan// invalidate any other reasons why the executable file might be covered by
28169691Skan// the GNU General Public License.
29169691Skan
30169691Skan// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
31169691Skan
32169691Skan// Permission to use, copy, modify, sell, and distribute this software
33169691Skan// is hereby granted without fee, provided that the above copyright
34169691Skan// notice appears in all copies, and that both that copyright notice and
35169691Skan// this permission notice appear in supporting documentation. None of
36169691Skan// the above authors, nor IBM Haifa Research Laboratories, make any
37169691Skan// representation about the suitability of this software for any
38169691Skan// purpose. It is provided "as is" without express or implied warranty.
39169691Skan
40169691Skan/**
41169691Skan * @file typelist.h
42169691Skan * Contains typelist_chain definitions.
43169691Skan * Typelists are an idea by Andrei Alexandrescu.
44169691Skan */
45169691Skan
46169691Skan#ifndef _TYPELIST_H
47169691Skan#define _TYPELIST_H 1
48169691Skan
49169691Skan#include <ext/type_traits.h>
50169691Skan
51169691Skan_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
52169691Skan
53169691Skannamespace typelist
54169691Skan{
55169691Skan  struct null_type { };
56169691Skan
57169691Skan  template<typename Root>
58169691Skan    struct node
59169691Skan    {
60169691Skan      typedef Root 	root;
61169691Skan    };
62169691Skan
63169691Skan  // Forward declarations of functors.
64169691Skan  template<typename Hd, typename Typelist>
65169691Skan    struct chain
66169691Skan    {
67169691Skan      typedef Hd 	head;
68169691Skan      typedef Typelist 	tail;
69169691Skan    };
70169691Skan
71169691Skan  template<typename Fn, class Typelist>
72169691Skan    void
73169691Skan    apply(Fn&, Typelist);
74169691Skan
75169691Skan  template<typename Typelist0, typename Typelist1>
76169691Skan    struct append;
77169691Skan
78169691Skan  template<typename Typelist_Typelist>
79169691Skan    struct append_typelist;
80169691Skan
81169691Skan  template<typename Typelist, typename T>
82169691Skan    struct contains;
83169691Skan
84169691Skan  template<typename Typelist, template<typename T> class Pred>
85169691Skan    struct filter;
86169691Skan
87169691Skan  template<typename Typelist, int i>
88169691Skan    struct at_index;
89169691Skan
90169691Skan  template<typename Typelist, template<typename T> class Transform>
91169691Skan    struct transform;
92169691Skan
93169691Skan  template<typename Typelist_Typelist>
94169691Skan    struct flatten;
95169691Skan
96169691Skan  template<typename Typelist>
97169691Skan    struct from_first;
98169691Skan
99169691Skan  template<typename T1>
100169691Skan    struct create1;
101169691Skan
102169691Skan  template<typename T1, typename T2>
103169691Skan    struct create2;
104169691Skan
105169691Skan  template<typename T1, typename T2, typename T3>
106169691Skan    struct create3;
107169691Skan
108169691Skan  template<typename T1, typename T2, typename T3, typename T4>
109169691Skan    struct create4;
110169691Skan
111169691Skan  template<typename T1, typename T2, typename T3, typename T4, typename T5>
112169691Skan    struct create5;
113169691Skan
114169691Skan  template<typename T1, typename T2, typename T3,
115169691Skan	   typename T4, typename T5, typename T6>
116169691Skan    struct create6;
117169691Skan} // namespace typelist
118169691Skan
119169691Skan_GLIBCXX_END_NAMESPACE
120169691Skan
121169691Skan
122169691Skan_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
123169691Skan
124169691Skannamespace typelist
125169691Skan{
126169691Skannamespace detail
127169691Skan{
128169691Skan  template<typename Fn, typename Typelist_Chain>
129169691Skan    struct apply_;
130169691Skan
131169691Skan  template<typename Fn, typename Hd, typename Tl>
132169691Skan    struct apply_<Fn, chain<Hd, Tl> >
133169691Skan    {
134169691Skan      void
135169691Skan      operator() (Fn& f)
136169691Skan      {
137169691Skan	f.operator()(Hd());
138169691Skan	apply_<Fn, Tl> next;
139169691Skan	next(f);
140169691Skan      }
141169691Skan  };
142169691Skan
143169691Skan  template<typename Fn>
144169691Skan    struct apply_<Fn, null_type>
145169691Skan    {
146169691Skan      void
147169691Skan      operator()(Fn&) { }
148169691Skan  };
149169691Skan
150169691Skan  template<typename Typelist_Chain0, typename Typelist_Chain1>
151169691Skan    struct append_;
152169691Skan
153169691Skan  template<typename Hd, typename Tl, typename Typelist_Chain>
154169691Skan    struct append_<chain<Hd, Tl>, Typelist_Chain>
155169691Skan    {
156169691Skan    private:
157169691Skan      typedef append_<Tl, Typelist_Chain> 			append_type;
158169691Skan
159169691Skan    public:
160169691Skan      typedef chain<Hd, typename append_type::type> 		type;
161169691Skan    };
162169691Skan
163169691Skan  template<typename Typelist_Chain>
164169691Skan    struct append_<null_type, Typelist_Chain>
165169691Skan    {
166169691Skan      typedef Typelist_Chain 			      		type;
167169691Skan    };
168169691Skan
169169691Skan  template<typename Typelist_Chain>
170169691Skan    struct append_<Typelist_Chain, null_type>
171169691Skan    {
172169691Skan      typedef Typelist_Chain 					type;
173169691Skan    };
174169691Skan
175169691Skan  template<>
176169691Skan    struct append_<null_type, null_type>
177169691Skan    {
178169691Skan      typedef null_type 					type;
179169691Skan    };
180169691Skan
181169691Skan  template<typename Typelist_Typelist_Chain>
182169691Skan    struct append_typelist_;
183169691Skan
184169691Skan  template<typename Hd>
185169691Skan    struct append_typelist_<chain<Hd, null_type> >
186169691Skan    {
187169691Skan      typedef chain<Hd, null_type> 				type;
188169691Skan    };
189169691Skan
190169691Skan  template<typename Hd, typename Tl>
191169691Skan    struct append_typelist_<chain< Hd, Tl> >
192169691Skan    {
193169691Skan    private:
194169691Skan      typedef typename append_typelist_<Tl>::type 		rest_type;
195169691Skan
196169691Skan    public:
197169691Skan      typedef typename append<Hd, node<rest_type> >::type::root	type;
198169691Skan    };
199169691Skan
200169691Skan  template<typename Typelist_Chain, typename T>
201169691Skan    struct contains_;
202169691Skan
203169691Skan  template<typename T>
204169691Skan    struct contains_<null_type, T>
205169691Skan    {
206169691Skan      enum
207169691Skan	{
208169691Skan	  value = false
209169691Skan	};
210169691Skan    };
211169691Skan
212169691Skan  template<typename Hd, typename Tl, typename T>
213169691Skan    struct contains_<chain<Hd, Tl>, T>
214169691Skan    {
215169691Skan      enum
216169691Skan	{
217169691Skan	  value = contains_<Tl, T>::value
218169691Skan	};
219169691Skan    };
220169691Skan
221169691Skan  template<typename Tl, typename T>
222169691Skan    struct contains_<chain<T, Tl>, T>
223169691Skan    {
224169691Skan      enum
225169691Skan	{
226169691Skan	  value = true
227169691Skan	};
228169691Skan    };
229169691Skan
230169691Skan  template<typename Typelist_Chain, template<typename T> class Pred>
231169691Skan    struct chain_filter_;
232169691Skan
233169691Skan  template<template<typename T> class Pred>
234169691Skan    struct chain_filter_<null_type, Pred>
235169691Skan    {
236169691Skan      typedef null_type 					type;
237169691Skan  };
238169691Skan
239169691Skan  template<typename Hd, typename Tl, template<typename T> class Pred>
240169691Skan    struct chain_filter_<chain<Hd, Tl>, Pred>
241169691Skan    {
242169691Skan    private:
243169691Skan      enum
244169691Skan	{
245169691Skan	  include_hd = Pred<Hd>::value
246169691Skan	};
247169691Skan
248169691Skan      typedef typename chain_filter_<Tl, Pred>::type 		rest_type;
249169691Skan      typedef chain<Hd, rest_type> 				chain_type;
250169691Skan
251169691Skan    public:
252169691Skan      typedef typename __conditional_type<include_hd, chain_type, rest_type>::__type type;
253169691Skan  };
254169691Skan
255169691Skan  template<typename Typelist_Chain, int i>
256169691Skan    struct chain_at_index_;
257169691Skan
258169691Skan  template<typename Hd, typename Tl>
259169691Skan    struct chain_at_index_<chain<Hd, Tl>, 0>
260169691Skan    {
261169691Skan      typedef Hd 						type;
262169691Skan    };
263169691Skan
264169691Skan  template<typename Hd, typename Tl, int i>
265169691Skan    struct chain_at_index_<chain<Hd, Tl>, i>
266169691Skan    {
267169691Skan      typedef typename chain_at_index_<Tl, i - 1>::type 	type;
268169691Skan    };
269169691Skan
270169691Skan  template<class Typelist_Chain, template<typename T> class Transform>
271169691Skan    struct chain_transform_;
272169691Skan
273169691Skan  template<template<typename T> class Transform>
274169691Skan    struct chain_transform_<null_type, Transform>
275169691Skan    {
276169691Skan      typedef null_type 					type;
277169691Skan    };
278169691Skan
279169691Skan  template<class Hd, class Tl, template<typename T> class Transform>
280169691Skan    struct chain_transform_<chain<Hd, Tl>, Transform>
281169691Skan    {
282169691Skan    private:
283169691Skan      typedef typename chain_transform_<Tl, Transform>::type 	rest_type;
284169691Skan      typedef typename Transform<Hd>::type 			transform_type;
285169691Skan
286169691Skan    public:
287169691Skan      typedef chain<transform_type, rest_type> 			type;
288169691Skan    };
289169691Skan
290169691Skan  template<typename Typelist_Typelist_Chain>
291169691Skan    struct chain_flatten_;
292169691Skan
293169691Skan  template<typename Hd_Tl>
294169691Skan  struct chain_flatten_<chain<Hd_Tl, null_type> >
295169691Skan  {
296169691Skan    typedef typename Hd_Tl::root 				type;
297169691Skan  };
298169691Skan
299169691Skan  template<typename Hd_Typelist, class Tl_Typelist>
300169691Skan  struct chain_flatten_<chain<Hd_Typelist, Tl_Typelist> >
301169691Skan  {
302169691Skan  private:
303169691Skan    typedef typename chain_flatten_<Tl_Typelist>::type 		rest_type;
304169691Skan    typedef append<Hd_Typelist, node<rest_type> >		append_type;
305169691Skan  public:
306169691Skan    typedef typename append_type::type::root 			type;
307169691Skan  };
308169691Skan} // namespace detail
309169691Skan} // namespace typelist
310169691Skan
311169691Skan_GLIBCXX_END_NAMESPACE
312169691Skan
313169691Skan#define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain<X0, __gnu_cxx::typelist::null_type>
314169691Skan#define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN1(X1) >
315169691Skan#define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN2(X1, X2) >
316169691Skan#define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN3(X1, X2, X3) >
317169691Skan#define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN4(X1, X2, X3, X4) >
318169691Skan#define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain<X0, _GLIBCXX_TYPELIST_CHAIN5(X1, X2, X3, X4, X5) >
319169691Skan#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) >
320169691Skan#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) >
321169691Skan#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) >
322169691Skan#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) >
323169691Skan#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) >
324169691Skan#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) >
325169691Skan#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) >
326169691Skan#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) >
327169691Skan#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) >
328169691Skan
329169691Skan_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
330169691Skan
331169691Skannamespace typelist
332169691Skan{
333169691Skan  template<typename Fn, class Typelist>
334169691Skan    void
335169691Skan    apply(Fn& fn, Typelist)
336169691Skan    {
337169691Skan      detail::apply_<Fn, typename Typelist::root> a;
338169691Skan      a(fn);
339169691Skan    }
340169691Skan
341169691Skan  template<typename Typelist0, typename Typelist1>
342169691Skan    struct append
343169691Skan    {
344169691Skan    private:
345169691Skan      typedef typename Typelist0::root 				root0_type;
346169691Skan      typedef typename Typelist1::root 				root1_type;
347169691Skan      typedef detail::append_<root0_type, root1_type> 		append_type;
348169691Skan
349169691Skan    public:
350169691Skan      typedef node<typename append_type::type> 			type;
351169691Skan    };
352169691Skan
353169691Skan  template<typename Typelist_Typelist>
354169691Skan    struct append_typelist
355169691Skan    {
356169691Skan    private:
357169691Skan      typedef typename Typelist_Typelist::root 		      	root_type;
358169691Skan      typedef detail::append_typelist_<root_type> 		append_type;
359169691Skan
360169691Skan    public:
361169691Skan      typedef node<typename append_type::type> 			type;
362169691Skan    };
363169691Skan
364169691Skan  template<typename Typelist, typename T>
365169691Skan    struct contains
366169691Skan    {
367169691Skan    private:
368169691Skan      typedef typename Typelist::root 				root_type;
369169691Skan
370169691Skan    public:
371169691Skan      enum
372169691Skan	{
373169691Skan	  value = detail::contains_<root_type, T>::value
374169691Skan	};
375169691Skan    };
376169691Skan
377169691Skan  template<typename Typelist, template<typename T> class Pred>
378169691Skan    struct filter
379169691Skan    {
380169691Skan    private:
381169691Skan      typedef typename Typelist::root 				root_type;
382169691Skan      typedef detail::chain_filter_<root_type, Pred> 		filter_type;
383169691Skan
384169691Skan    public:
385169691Skan      typedef node<typename filter_type::type> 	       		type;
386169691Skan    };
387169691Skan
388169691Skan  template<typename Typelist, int i>
389169691Skan    struct at_index
390169691Skan    {
391169691Skan    private:
392169691Skan      typedef typename Typelist::root 				root_type;
393169691Skan      typedef detail::chain_at_index_<root_type, i> 		index_type;
394169691Skan
395169691Skan    public:
396169691Skan      typedef typename index_type::type 			type;
397169691Skan    };
398169691Skan
399169691Skan  template<typename Typelist, template<typename T> class Transform>
400169691Skan    struct transform
401169691Skan    {
402169691Skan    private:
403169691Skan      typedef typename Typelist::root 				root_type;
404169691Skan      typedef detail::chain_transform_<root_type, Transform> 	transform_type;
405169691Skan
406169691Skan    public:
407169691Skan      typedef node<typename transform_type::type> 		type;
408169691Skan    };
409169691Skan
410169691Skan  template<typename Typelist_Typelist>
411169691Skan    struct flatten
412169691Skan    {
413169691Skan    private:
414169691Skan      typedef typename Typelist_Typelist::root 		      	root_type;
415169691Skan      typedef typename detail::chain_flatten_<root_type>::type 	flatten_type;
416169691Skan
417169691Skan    public:
418169691Skan      typedef node<flatten_type> 				type;
419169691Skan    };
420169691Skan
421169691Skan  template<typename Typelist>
422169691Skan    struct from_first
423169691Skan    {
424169691Skan    private:
425169691Skan      typedef typename at_index<Typelist, 0>::type 		first_type;
426169691Skan
427169691Skan    public:
428169691Skan      typedef node<chain<first_type, null_type> > 		type;
429169691Skan    };
430169691Skan
431169691Skan  template<typename T1>
432169691Skan    struct create1
433169691Skan    {
434169691Skan      typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> 		type;
435169691Skan    };
436169691Skan
437169691Skan  template<typename T1, typename T2>
438169691Skan    struct create2
439169691Skan    {
440169691Skan      typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> 		type;
441169691Skan    };
442169691Skan
443169691Skan  template<typename T1, typename T2, typename T3>
444169691Skan    struct create3
445169691Skan    {
446169691Skan      typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)>		type;
447169691Skan    };
448169691Skan
449169691Skan  template<typename T1, typename T2, typename T3, typename T4>
450169691Skan    struct create4
451169691Skan    {
452169691Skan      typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)>	type;
453169691Skan    };
454169691Skan
455169691Skan  template<typename T1, typename T2, typename T3,
456169691Skan	   typename T4, typename T5>
457169691Skan    struct create5
458169691Skan    {
459169691Skan      typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)>	type;
460169691Skan    };
461169691Skan
462169691Skan  template<typename T1, typename T2, typename T3,
463169691Skan	   typename T4, typename T5, typename T6>
464169691Skan    struct create6
465169691Skan    {
466169691Skan      typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)>	type;
467169691Skan    };
468169691Skan} // namespace typelist
469169691Skan_GLIBCXX_END_NAMESPACE
470169691Skan
471169691Skan
472169691Skan#endif
473169691Skan
474