Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / lambda / switch.hpp
1 // Boost Lambda Library -- switch.hpp -----------------------------------
2 //
3 // Copyright (C) 2000 Gary Powell (powellg@amazon.com)
4 // Copyright (C) 1999, 2000 Jaakko J√§rvi (jaakko.jarvi@cs.utu.fi)
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 //
10 // For more information, see www.boost.org
11
12 // --------------------------------------------------------------------------
13
14 #if !defined(BOOST_LAMBDA_SWITCH_HPP)
15 #define BOOST_LAMBDA_SWITCH_HPP
16
17 #include "boost/lambda/core.hpp"
18 #include "boost/lambda/detail/control_constructs_common.hpp"
19
20 #include "boost/preprocessor/enum_shifted_params.hpp"
21 #include "boost/preprocessor/repeat_2nd.hpp"
22 #include "boost/preprocessor/tuple.hpp"
23
24 namespace boost { 
25 namespace lambda {
26
27 // Switch actions
28 template <int N, class Switch1 = null_type, class Switch2 = null_type, 
29           class Switch3 = null_type, class Switch4 = null_type,
30           class Switch5 = null_type, class Switch6 = null_type, 
31           class Switch7 = null_type, class Switch8 = null_type, 
32           class Switch9 = null_type>
33 struct switch_action {};
34
35
36 namespace detail {
37
38   // templates to represent special lambda functors for the cases in 
39   // switch statements
40   
41 template <int Value> struct case_label {};
42 struct default_label {};
43
44 template<class Type> struct switch_case_tag {};
45
46   // a normal case is represented as:
47   // tagged_lambda_functor<switch_case_tag<case_label<N> > >, LambdaFunctor>
48   
49   // the default case as:
50   // tagged_lambda_functor<switch_case_tag<default_label> >, LambdaFunctor>
51
52
53 } // end detail
54
55
56 /// create switch_case_tag tagged_lambda_functors
57 template <int CaseValue, class Arg>
58 inline const 
59 tagged_lambda_functor<
60   detail::switch_case_tag<detail::case_label<CaseValue> >, 
61   lambda_functor<Arg> 
62
63 case_statement(const lambda_functor<Arg>& a) { 
64   return 
65     tagged_lambda_functor<
66       detail::switch_case_tag<detail::case_label<CaseValue> >, 
67       lambda_functor<Arg> 
68     >(a); 
69 }
70
71 // No case body case.
72 template <int CaseValue>
73 inline const 
74 tagged_lambda_functor<
75   detail::switch_case_tag<detail::case_label<CaseValue> >,
76   lambda_functor< 
77     lambda_functor_base< 
78       do_nothing_action, 
79       null_type
80     > 
81   > 
82
83 case_statement() { 
84 return 
85   tagged_lambda_functor<
86     detail::switch_case_tag<detail::case_label<CaseValue> >,
87     lambda_functor< 
88       lambda_functor_base< 
89         do_nothing_action, 
90         null_type
91       > 
92     > 
93   > () ;
94 }
95
96 // default label
97 template <class Arg>
98 inline const 
99 tagged_lambda_functor<
100   detail::switch_case_tag<detail::default_label>, 
101   lambda_functor<Arg> 
102
103 default_statement(const lambda_functor<Arg>& a) { 
104   return 
105     tagged_lambda_functor<
106       detail::switch_case_tag<detail::default_label>, 
107       lambda_functor<Arg> 
108     >(a); 
109 }
110
111 // default lable, no case body case.
112 inline const 
113 tagged_lambda_functor<
114   detail::switch_case_tag<detail::default_label>,
115   lambda_functor< 
116     lambda_functor_base< 
117       do_nothing_action, 
118       null_type
119     > 
120   > 
121
122 default_statement() { 
123 return 
124       lambda_functor_base< 
125         do_nothing_action, 
126         null_type 
127       > () ;
128 }
129
130
131 // Specializations for lambda_functor_base of case_statement -----------------
132
133 // 0 case type:
134 // useless (just the condition part) but provided for completeness.
135 template<class Args>
136 class 
137 lambda_functor_base<
138   switch_action<1>, 
139   Args
140
141 {
142 public:
143   Args args;
144   template <class SigArgs> struct sig { typedef void type; };
145 public:
146   explicit lambda_functor_base(const Args& a) : args(a) {}
147
148   template<class RET, CALL_TEMPLATE_ARGS>
149   RET call(CALL_FORMAL_ARGS) const {
150     detail::select(::boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);  
151   }
152 };
153
154 // 1 case type:
155 // template<class Args, int Case1>
156 // class 
157 // lambda_functor_base<
158 //   action<
159 //     2, 
160 //     return_void_action<switch_action<detail::case_label<Case1> > > 
161 //   >, 
162 //   Args
163 // > 
164 // {
165 //   Args args;
166 // public:
167 //   explicit lambda_functor_base(const Args& a) : args(a) {}
168
169 //   template<class RET, class A, class B, class C>
170 //   RET call(A& a, B& b, C& c) const {
171 //     switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )  
172 //     {
173 //       case Case1:                
174 //         detail::select(::boost::tuples::get<1>(args), a, b, c);
175 //         break;
176 //     }
177 //   }
178 // };
179
180 // switch with default being the sole label - doesn't make much sense but
181 // it is there for completeness
182 // template<class Args>
183 // class
184 // lambda_functor_base<
185 //   action<
186 //     2,
187 //     return_void_action<switch_action<detail::default_label> >
188 //   >,
189 //   Args
190 // >
191 // {
192 //   Args args;
193 // public:
194 //   explicit lambda_functor_base(const Args& a) : args(a) {}
195 // 
196 //   template<class RET, class A, class B, class C>
197 //   RET call(A& a, B& b, C& c) const {
198 //     switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )
199 //     {
200 //       default:
201 //         detail::select(::boost::tuples::get<1>(args), a, b, c);
202 //         break;
203 //     }
204 //   }
205 // };
206
207
208
209 // // 2 case type:
210 // The different specializations are generated with Vesa Karvonen's 
211 // preprocessor library.
212
213 // This is just a comment to show what the generated classes look like
214
215 // template<class Args, int Case1, int Case2>
216 // class 
217 // lambda_functor_base<
218 //   action<3, 
219 //     return_void_action< 
220 //       switch_action< 
221 //         detail::case_label<Case1>,
222 //         detail::case_label<Case2>
223 //       > 
224 //     > 
225 //   >, 
226 //   Args
227 // > 
228 // {
229 //   Args args;
230 // public:
231 //   explicit lambda_functor_base(const Args& a) : args(a) {}
232
233 //   template<class RET, class A, class B, class C>
234 //   RET call(A& a, B& b, C& c) const {
235 //     switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )  
236 //     {
237 //       case Case1:                
238 //         detail::select(::boost::tuples::get<1>(args), a, b, c);
239 //         break;
240 //       case Case2:                
241 //         detail::select(::boost::tuples::get<2>(args), a, b, c);
242 //         break;
243 //     }
244 //   }
245 // };
246
247 // template<class Args, int Case1>
248 // class 
249 // lambda_functor_base<
250 //   action<3, 
251 //     return_void_action< 
252 //       switch_action< 
253 //         detail::case_label<Case1>,
254 //         detail::default_label 
255 //       > 
256 //     > 
257 //   >, 
258 //   Args
259 // > 
260 // {
261 //   Args args;
262 // public:
263 //   explicit lambda_functor_base(const Args& a) : args(a) {}
264
265 //   template<class RET, class A, class B, class C>
266 //   RET call(A& a, B& b, C& c) const {
267 //     switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )  
268 //     {
269 //       case Case1:                
270 //         detail::select(::boost::tuples::get<1>(args), a, b, c);
271 //         break;
272 //       default:                
273 //         detail::select(::boost::tuples::get<2>(args), a, b, c);
274 //         break;
275 //     }
276 //   }
277 // };
278 // -------------------------
279
280 // Some helper preprocessor macros ---------------------------------
281
282 // BOOST_LAMBDA_A_I_LIST(N, X) is a list of form X0, X1, ..., XN
283 // BOOST_LAMBDA_A_I_B_LIST(N, X, Y) is a list of form X0 Y, X1 Y, ..., XN Y
284
285 #define BOOST_LAMBDA_A_I(z, i, A) \
286 BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A,i)
287
288 #define BOOST_LAMBDA_A_I_B(z, i, T) \
289 BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2,0,T),i) BOOST_PP_TUPLE_ELEM(2,1,T)
290
291 #define BOOST_LAMBDA_A_I_LIST(i, A) \
292 BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I, A) 
293
294 #define BOOST_LAMBDA_A_I_B_LIST(i, A, B) \
295 BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I_B, (A,B)) 
296
297
298 // Switch related macros -------------------------------------------
299 #define BOOST_LAMBDA_SWITCH_CASE_BLOCK(z, N, A) \
300   case Case##N: \
301   detail::select(::boost::tuples::get<BOOST_PP_INC(N)>(args), CALL_ACTUAL_ARGS); \
302   break;
303
304 #define BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(N) \
305 BOOST_PP_REPEAT(N, BOOST_LAMBDA_SWITCH_CASE_BLOCK, FOO)
306 // 2 case type:
307
308 #define BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N)                                \
309 template<class Args, BOOST_LAMBDA_A_I_LIST(N, int Case)>                      \
310 class                                                                         \
311 lambda_functor_base<                                                          \
312       switch_action<BOOST_PP_INC(N),                                          \
313         BOOST_LAMBDA_A_I_B_LIST(N, detail::case_label<Case,>)                 \
314       >,                                                                      \
315   Args                                                                        \
316 >                                                                             \
317 {                                                                             \
318 public:                                                                       \
319   Args args;                                                                  \
320   template <class SigArgs> struct sig { typedef void type; };                 \
321 public:                                                                       \
322   explicit lambda_functor_base(const Args& a) : args(a) {}                    \
323                                                                               \
324   template<class RET, CALL_TEMPLATE_ARGS>                                     \
325   RET call(CALL_FORMAL_ARGS) const {                                          \
326     switch( detail::select(::boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ) \
327     {                                                                         \
328       BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(N)                                  \
329     }                                                                         \
330   }                                                                           \
331 };
332
333         
334
335 #define BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N)                              \
336 template<                                                                     \
337   class Args BOOST_PP_COMMA_IF(BOOST_PP_DEC(N))                               \
338   BOOST_LAMBDA_A_I_LIST(BOOST_PP_DEC(N), int Case)                            \
339 >                                                                             \
340 class                                                                         \
341 lambda_functor_base<                                                          \
342       switch_action<BOOST_PP_INC(N),                                          \
343         BOOST_LAMBDA_A_I_B_LIST(BOOST_PP_DEC(N),                              \
344                                 detail::case_label<Case, >)                   \
345         BOOST_PP_COMMA_IF(BOOST_PP_DEC(N))                                    \
346         detail::default_label                                                 \
347       >,                                                                      \
348   Args                                                                        \
349 >                                                                             \
350 {                                                                             \
351 public:                                                                       \
352   Args args;                                                                  \
353   template <class SigArgs> struct sig { typedef void type; };                 \
354 public:                                                                       \
355   explicit lambda_functor_base(const Args& a) : args(a) {}                    \
356                                                                               \
357   template<class RET, CALL_TEMPLATE_ARGS>                                     \
358   RET call(CALL_FORMAL_ARGS) const {                                          \
359     switch( detail::select(::boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ) \
360     {                                                                         \
361         BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(BOOST_PP_DEC(N))                  \
362       default:                                                                \
363         detail::select(::boost::tuples::get<N>(args), CALL_ACTUAL_ARGS);      \
364         break;                                                                \
365     }                                                                         \
366   }                                                                           \
367 };
368
369
370
371
372
373
374 // switch_statement bind functions -------------------------------------
375
376 // The zero argument case, for completeness sake
377 inline const 
378 lambda_functor< 
379   lambda_functor_base< 
380     do_nothing_action, 
381     null_type
382   > 
383 >
384 switch_statement() { 
385   return 
386       lambda_functor_base< 
387         do_nothing_action, 
388         null_type
389       > 
390   ();
391 }
392
393 // 1 argument case, this is useless as well, just the condition part
394 template <class TestArg>
395 inline const 
396 lambda_functor< 
397   lambda_functor_base< 
398     switch_action<1>, 
399     tuple<lambda_functor<TestArg> >
400   > 
401 >
402 switch_statement(const lambda_functor<TestArg>& a1) { 
403   return 
404       lambda_functor_base< 
405          switch_action<1>, 
406          tuple< lambda_functor<TestArg> > 
407       > 
408     ( tuple<lambda_functor<TestArg> >(a1));
409 }
410
411
412 #define HELPER(z, N, FOO)                                      \
413 BOOST_PP_COMMA_IF(N)                                           \
414 BOOST_PP_CAT(                                                  \
415   const tagged_lambda_functor<detail::switch_case_tag<TagData, \
416   N>)                                                          \
417 BOOST_PP_COMMA() Arg##N>& a##N
418
419 #define HELPER_LIST(N) BOOST_PP_REPEAT(N, HELPER, FOO)
420
421
422 #define BOOST_LAMBDA_SWITCH_STATEMENT(N)                              \
423 template <class TestArg,                                              \
424           BOOST_LAMBDA_A_I_LIST(N, class TagData),                    \
425           BOOST_LAMBDA_A_I_LIST(N, class Arg)>                        \
426 inline const                                                          \
427 lambda_functor<                                                       \
428   lambda_functor_base<                                                \
429         switch_action<BOOST_PP_INC(N),                                \
430           BOOST_LAMBDA_A_I_LIST(N, TagData)                           \
431         >,                                                            \
432     tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)>     \
433   >                                                                   \
434 >                                                                     \
435 switch_statement(                                                     \
436   const lambda_functor<TestArg>& ta,                                  \
437   HELPER_LIST(N)                                                      \
438 )                                                                     \
439 {                                                                     \
440   return                                                              \
441       lambda_functor_base<                                            \
442             switch_action<BOOST_PP_INC(N),                            \
443               BOOST_LAMBDA_A_I_LIST(N, TagData)                       \
444             >,                                                        \
445         tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)> \
446       >                                                               \
447     ( tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)>   \
448         (ta, BOOST_LAMBDA_A_I_LIST(N, a) ));                          \
449 }
450
451
452
453
454 // Here's the actual generation
455
456 #define BOOST_LAMBDA_SWITCH(N)           \
457 BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N)   \
458 BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N)        
459
460 // Use this to avoid case 0, these macros work only from case 1 upwards
461 #define BOOST_LAMBDA_SWITCH_HELPER(z, N, A) \
462 BOOST_LAMBDA_SWITCH( BOOST_PP_INC(N) )
463
464 // Use this to avoid cases 0 and 1, these macros work only from case 2 upwards
465 #define BOOST_LAMBDA_SWITCH_STATEMENT_HELPER(z, N, A) \
466 BOOST_LAMBDA_SWITCH_STATEMENT(BOOST_PP_INC(N))
467
468
469
470   // up to 9 cases supported (counting default:)
471 BOOST_PP_REPEAT_2ND(9,BOOST_LAMBDA_SWITCH_HELPER,FOO)
472 BOOST_PP_REPEAT_2ND(9,BOOST_LAMBDA_SWITCH_STATEMENT_HELPER,FOO)
473
474
475 } // namespace lambda 
476 } // namespace boost
477
478
479 #undef HELPER
480 #undef HELPER_LIST
481
482 #undef BOOST_LAMBDA_SWITCH_HELPER
483 #undef BOOST_LAMBDA_SWITCH
484 #undef BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE
485 #undef BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE
486
487 #undef BOOST_LAMBDA_SWITCH_CASE_BLOCK
488 #undef BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST
489
490 #undef BOOST_LAMBDA_SWITCH_STATEMENT
491 #undef BOOST_LAMBDA_SWITCH_STATEMENT_HELPER
492
493
494
495 #endif
496
497
498
499
500
501
502