1 // Boost Lambda Library -- switch.hpp -----------------------------------
3 // Copyright (C) 2000 Gary Powell (powellg@amazon.com)
4 // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
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)
10 // For more information, see www.boost.org
12 // --------------------------------------------------------------------------
14 #if !defined(BOOST_LAMBDA_SWITCH_HPP)
15 #define BOOST_LAMBDA_SWITCH_HPP
17 #include "boost/lambda/core.hpp"
18 #include "boost/lambda/detail/control_constructs_common.hpp"
20 #include "boost/preprocessor/enum_shifted_params.hpp"
21 #include "boost/preprocessor/repeat_2nd.hpp"
22 #include "boost/preprocessor/tuple.hpp"
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
{};
38 // templates to represent special lambda functors for the cases in
41 template <int Value
> struct case_label
{};
42 struct default_label
{};
44 template<class Type
> struct switch_case_tag
{};
46 // a normal case is represented as:
47 // tagged_lambda_functor<switch_case_tag<case_label<N> > >, LambdaFunctor>
49 // the default case as:
50 // tagged_lambda_functor<switch_case_tag<default_label> >, LambdaFunctor>
56 /// create switch_case_tag tagged_lambda_functors
57 template <int CaseValue
, class Arg
>
59 tagged_lambda_functor
<
60 detail::switch_case_tag
<detail::case_label
<CaseValue
> >,
63 case_statement(const lambda_functor
<Arg
>& a
) {
65 tagged_lambda_functor
<
66 detail::switch_case_tag
<detail::case_label
<CaseValue
> >,
72 template <int CaseValue
>
74 tagged_lambda_functor
<
75 detail::switch_case_tag
<detail::case_label
<CaseValue
> >,
85 tagged_lambda_functor
<
86 detail::switch_case_tag
<detail::case_label
<CaseValue
> >,
99 tagged_lambda_functor
<
100 detail::switch_case_tag
<detail::default_label
>,
103 default_statement(const lambda_functor
<Arg
>& a
) {
105 tagged_lambda_functor
<
106 detail::switch_case_tag
<detail::default_label
>,
111 // default lable, no case body case.
113 tagged_lambda_functor
<
114 detail::switch_case_tag
<detail::default_label
>,
122 default_statement() {
131 // Specializations for lambda_functor_base of case_statement -----------------
134 // useless (just the condition part) but provided for completeness.
144 template <class SigArgs
> struct sig
{ typedef void type
; };
146 explicit lambda_functor_base(const Args
& a
) : args(a
) {}
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
);
155 // template<class Args, int Case1>
157 // lambda_functor_base<
160 // return_void_action<switch_action<detail::case_label<Case1> > >
167 // explicit lambda_functor_base(const Args& a) : args(a) {}
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) )
174 // detail::select(::boost::tuples::get<1>(args), a, b, c);
180 // switch with default being the sole label - doesn't make much sense but
181 // it is there for completeness
182 // template<class Args>
184 // lambda_functor_base<
187 // return_void_action<switch_action<detail::default_label> >
194 // explicit lambda_functor_base(const Args& a) : args(a) {}
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) )
201 // detail::select(::boost::tuples::get<1>(args), a, b, c);
210 // The different specializations are generated with Vesa Karvonen's
211 // preprocessor library.
213 // This is just a comment to show what the generated classes look like
215 // template<class Args, int Case1, int Case2>
217 // lambda_functor_base<
219 // return_void_action<
221 // detail::case_label<Case1>,
222 // detail::case_label<Case2>
231 // explicit lambda_functor_base(const Args& a) : args(a) {}
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) )
238 // detail::select(::boost::tuples::get<1>(args), a, b, c);
241 // detail::select(::boost::tuples::get<2>(args), a, b, c);
247 // template<class Args, int Case1>
249 // lambda_functor_base<
251 // return_void_action<
253 // detail::case_label<Case1>,
254 // detail::default_label
263 // explicit lambda_functor_base(const Args& a) : args(a) {}
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) )
270 // detail::select(::boost::tuples::get<1>(args), a, b, c);
273 // detail::select(::boost::tuples::get<2>(args), a, b, c);
278 // -------------------------
280 // Some helper preprocessor macros ---------------------------------
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
285 #define BOOST_LAMBDA_A_I(z, i, A) \
286 BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A,i)
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)
291 #define BOOST_LAMBDA_A_I_LIST(i, A) \
292 BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I, A)
294 #define BOOST_LAMBDA_A_I_B_LIST(i, A, B) \
295 BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I_B, (A,B))
298 // Switch related macros -------------------------------------------
299 #define BOOST_LAMBDA_SWITCH_CASE_BLOCK(z, N, A) \
301 detail::select(::boost::tuples::get<BOOST_PP_INC(N)>(args), CALL_ACTUAL_ARGS); \
304 #define BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(N) \
305 BOOST_PP_REPEAT(N, BOOST_LAMBDA_SWITCH_CASE_BLOCK, FOO)
308 #define BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N) \
309 template<class Args, BOOST_LAMBDA_A_I_LIST(N, int Case)> \
311 lambda_functor_base< \
312 switch_action<BOOST_PP_INC(N), \
313 BOOST_LAMBDA_A_I_B_LIST(N, detail::case_label<Case,>) \
320 template <class SigArgs> struct sig { typedef void type; }; \
322 explicit lambda_functor_base(const Args& a) : args(a) {} \
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) ) \
328 BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(N) \
335 #define BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N) \
337 class Args BOOST_PP_COMMA_IF(BOOST_PP_DEC(N)) \
338 BOOST_LAMBDA_A_I_LIST(BOOST_PP_DEC(N), int Case) \
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 \
353 template <class SigArgs> struct sig { typedef void type; }; \
355 explicit lambda_functor_base(const Args& a) : args(a) {} \
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) ) \
361 BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(BOOST_PP_DEC(N)) \
363 detail::select(::boost::tuples::get<N>(args), CALL_ACTUAL_ARGS); \
374 // switch_statement bind functions -------------------------------------
376 // The zero argument case, for completeness sake
393 // 1 argument case, this is useless as well, just the condition part
394 template <class TestArg
>
399 tuple
<lambda_functor
<TestArg
> >
402 switch_statement(const lambda_functor
<TestArg
>& a1
) {
406 tuple
< lambda_functor
<TestArg
> >
408 ( tuple
<lambda_functor
<TestArg
> >(a1
));
412 #define HELPER(z, N, FOO) \
413 BOOST_PP_COMMA_IF(N) \
415 const tagged_lambda_functor<detail::switch_case_tag<TagData, \
417 BOOST_PP_COMMA() Arg##N>& a##N
419 #define HELPER_LIST(N) BOOST_PP_REPEAT(N, HELPER, FOO)
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)> \
428 lambda_functor_base< \
429 switch_action<BOOST_PP_INC(N), \
430 BOOST_LAMBDA_A_I_LIST(N, TagData) \
432 tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)> \
436 const lambda_functor<TestArg>& ta, \
441 lambda_functor_base< \
442 switch_action<BOOST_PP_INC(N), \
443 BOOST_LAMBDA_A_I_LIST(N, TagData) \
445 tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)> \
447 ( tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)> \
448 (ta, BOOST_LAMBDA_A_I_LIST(N, a) )); \
454 // Here's the actual generation
456 #define BOOST_LAMBDA_SWITCH(N) \
457 BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N) \
458 BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N)
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) )
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))
469 #pragma warning(push)
470 #pragma warning(disable:4065)
473 // up to 9 cases supported (counting default:)
474 BOOST_PP_REPEAT_2ND(9,BOOST_LAMBDA_SWITCH_HELPER
,FOO
)
475 BOOST_PP_REPEAT_2ND(9,BOOST_LAMBDA_SWITCH_STATEMENT_HELPER
,FOO
)
481 } // namespace lambda
488 #undef BOOST_LAMBDA_SWITCH_HELPER
489 #undef BOOST_LAMBDA_SWITCH
490 #undef BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE
491 #undef BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE
493 #undef BOOST_LAMBDA_SWITCH_CASE_BLOCK
494 #undef BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST
496 #undef BOOST_LAMBDA_SWITCH_STATEMENT
497 #undef BOOST_LAMBDA_SWITCH_STATEMENT_HELPER