Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:11

0001 // Boost Lambda Library -- switch.hpp -----------------------------------
0002 //
0003 // Copyright (C) 2000 Gary Powell (powellg@amazon.com)
0004 // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
0005 //
0006 // Distributed under the Boost Software License, Version 1.0. (See
0007 // accompanying file LICENSE_1_0.txt or copy at
0008 // http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 // For more information, see www.boost.org
0011 
0012 // --------------------------------------------------------------------------
0013 
0014 #if !defined(BOOST_LAMBDA_SWITCH_HPP)
0015 #define BOOST_LAMBDA_SWITCH_HPP
0016 
0017 #include "boost/lambda/core.hpp"
0018 #include "boost/lambda/detail/control_constructs_common.hpp"
0019 
0020 #include "boost/preprocessor/enum_shifted_params.hpp"
0021 #include "boost/preprocessor/repeat_2nd.hpp"
0022 #include "boost/preprocessor/tuple.hpp"
0023 
0024 namespace boost { 
0025 namespace lambda {
0026 
0027 // Switch actions
0028 template <int N, class Switch1 = null_type, class Switch2 = null_type, 
0029           class Switch3 = null_type, class Switch4 = null_type,
0030           class Switch5 = null_type, class Switch6 = null_type, 
0031           class Switch7 = null_type, class Switch8 = null_type, 
0032           class Switch9 = null_type>
0033 struct switch_action {};
0034 
0035 
0036 namespace detail {
0037 
0038   // templates to represent special lambda functors for the cases in 
0039   // switch statements
0040   
0041 template <int Value> struct case_label {};
0042 struct default_label {};
0043 
0044 template<class Type> struct switch_case_tag {};
0045 
0046   // a normal case is represented as:
0047   // tagged_lambda_functor<switch_case_tag<case_label<N> > >, LambdaFunctor>
0048   
0049   // the default case as:
0050   // tagged_lambda_functor<switch_case_tag<default_label> >, LambdaFunctor>
0051 
0052 
0053 } // end detail
0054 
0055 
0056 /// create switch_case_tag tagged_lambda_functors
0057 template <int CaseValue, class Arg>
0058 inline const 
0059 tagged_lambda_functor<
0060   detail::switch_case_tag<detail::case_label<CaseValue> >, 
0061   lambda_functor<Arg> 
0062 > 
0063 case_statement(const lambda_functor<Arg>& a) { 
0064   return 
0065     tagged_lambda_functor<
0066       detail::switch_case_tag<detail::case_label<CaseValue> >, 
0067       lambda_functor<Arg> 
0068     >(a); 
0069 }
0070 
0071 // No case body case.
0072 template <int CaseValue>
0073 inline const 
0074 tagged_lambda_functor<
0075   detail::switch_case_tag<detail::case_label<CaseValue> >,
0076   lambda_functor< 
0077     lambda_functor_base< 
0078       do_nothing_action, 
0079       null_type
0080     > 
0081   > 
0082 > 
0083 case_statement() { 
0084 return 
0085   tagged_lambda_functor<
0086     detail::switch_case_tag<detail::case_label<CaseValue> >,
0087     lambda_functor< 
0088       lambda_functor_base< 
0089         do_nothing_action, 
0090         null_type
0091       > 
0092     > 
0093   > () ;
0094 }
0095 
0096 // default label
0097 template <class Arg>
0098 inline const 
0099 tagged_lambda_functor<
0100   detail::switch_case_tag<detail::default_label>, 
0101   lambda_functor<Arg> 
0102 > 
0103 default_statement(const lambda_functor<Arg>& a) { 
0104   return 
0105     tagged_lambda_functor<
0106       detail::switch_case_tag<detail::default_label>, 
0107       lambda_functor<Arg> 
0108     >(a); 
0109 }
0110 
0111 // default lable, no case body case.
0112 inline const 
0113 tagged_lambda_functor<
0114   detail::switch_case_tag<detail::default_label>,
0115   lambda_functor< 
0116     lambda_functor_base< 
0117       do_nothing_action, 
0118       null_type
0119     > 
0120   > 
0121 > 
0122 default_statement() { 
0123 return 
0124       lambda_functor_base< 
0125         do_nothing_action, 
0126         null_type 
0127       > () ;
0128 }
0129 
0130 
0131 // Specializations for lambda_functor_base of case_statement -----------------
0132 
0133 // 0 case type:
0134 // useless (just the condition part) but provided for completeness.
0135 template<class Args>
0136 class 
0137 lambda_functor_base<
0138   switch_action<1>, 
0139   Args
0140 > 
0141 {
0142 public:
0143   Args args;
0144   template <class SigArgs> struct sig { typedef void type; };
0145 public:
0146   explicit lambda_functor_base(const Args& a) : args(a) {}
0147 
0148   template<class RET, CALL_TEMPLATE_ARGS>
0149   RET call(CALL_FORMAL_ARGS) const {
0150     detail::select(::boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);  
0151   }
0152 };
0153 
0154 // 1 case type:
0155 // template<class Args, int Case1>
0156 // class 
0157 // lambda_functor_base<
0158 //   action<
0159 //     2, 
0160 //     return_void_action<switch_action<detail::case_label<Case1> > > 
0161 //   >, 
0162 //   Args
0163 // > 
0164 // {
0165 //   Args args;
0166 // public:
0167 //   explicit lambda_functor_base(const Args& a) : args(a) {}
0168 
0169 //   template<class RET, class A, class B, class C>
0170 //   RET call(A& a, B& b, C& c) const {
0171 //     switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )  
0172 //     {
0173 //       case Case1:                
0174 //         detail::select(::boost::tuples::get<1>(args), a, b, c);
0175 //         break;
0176 //     }
0177 //   }
0178 // };
0179 
0180 // switch with default being the sole label - doesn't make much sense but
0181 // it is there for completeness
0182 // template<class Args>
0183 // class
0184 // lambda_functor_base<
0185 //   action<
0186 //     2,
0187 //     return_void_action<switch_action<detail::default_label> >
0188 //   >,
0189 //   Args
0190 // >
0191 // {
0192 //   Args args;
0193 // public:
0194 //   explicit lambda_functor_base(const Args& a) : args(a) {}
0195 // 
0196 //   template<class RET, class A, class B, class C>
0197 //   RET call(A& a, B& b, C& c) const {
0198 //     switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )
0199 //     {
0200 //       default:
0201 //         detail::select(::boost::tuples::get<1>(args), a, b, c);
0202 //         break;
0203 //     }
0204 //   }
0205 // };
0206 
0207 
0208 
0209 // // 2 case type:
0210 // The different specializations are generated with Vesa Karvonen's 
0211 // preprocessor library.
0212 
0213 // This is just a comment to show what the generated classes look like
0214 
0215 // template<class Args, int Case1, int Case2>
0216 // class 
0217 // lambda_functor_base<
0218 //   action<3, 
0219 //     return_void_action< 
0220 //       switch_action< 
0221 //         detail::case_label<Case1>,
0222 //         detail::case_label<Case2>
0223 //       > 
0224 //     > 
0225 //   >, 
0226 //   Args
0227 // > 
0228 // {
0229 //   Args args;
0230 // public:
0231 //   explicit lambda_functor_base(const Args& a) : args(a) {}
0232 
0233 //   template<class RET, class A, class B, class C>
0234 //   RET call(A& a, B& b, C& c) const {
0235 //     switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )  
0236 //     {
0237 //       case Case1:                
0238 //         detail::select(::boost::tuples::get<1>(args), a, b, c);
0239 //         break;
0240 //       case Case2:                
0241 //         detail::select(::boost::tuples::get<2>(args), a, b, c);
0242 //         break;
0243 //     }
0244 //   }
0245 // };
0246 
0247 // template<class Args, int Case1>
0248 // class 
0249 // lambda_functor_base<
0250 //   action<3, 
0251 //     return_void_action< 
0252 //       switch_action< 
0253 //         detail::case_label<Case1>,
0254 //         detail::default_label 
0255 //       > 
0256 //     > 
0257 //   >, 
0258 //   Args
0259 // > 
0260 // {
0261 //   Args args;
0262 // public:
0263 //   explicit lambda_functor_base(const Args& a) : args(a) {}
0264 
0265 //   template<class RET, class A, class B, class C>
0266 //   RET call(A& a, B& b, C& c) const {
0267 //     switch( detail::select(::boost::tuples::get<0>(args), a, b, c) )  
0268 //     {
0269 //       case Case1:                
0270 //         detail::select(::boost::tuples::get<1>(args), a, b, c);
0271 //         break;
0272 //       default:                
0273 //         detail::select(::boost::tuples::get<2>(args), a, b, c);
0274 //         break;
0275 //     }
0276 //   }
0277 // };
0278 // -------------------------
0279 
0280 // Some helper preprocessor macros ---------------------------------
0281 
0282 // BOOST_LAMBDA_A_I_LIST(N, X) is a list of form X0, X1, ..., XN
0283 // BOOST_LAMBDA_A_I_B_LIST(N, X, Y) is a list of form X0 Y, X1 Y, ..., XN Y
0284 
0285 #define BOOST_LAMBDA_A_I(z, i, A) \
0286 BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A,i)
0287 
0288 #define BOOST_LAMBDA_A_I_B(z, i, T) \
0289 BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2,0,T),i) BOOST_PP_TUPLE_ELEM(2,1,T)
0290 
0291 #define BOOST_LAMBDA_A_I_LIST(i, A) \
0292 BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I, A) 
0293 
0294 #define BOOST_LAMBDA_A_I_B_LIST(i, A, B) \
0295 BOOST_PP_REPEAT(i,BOOST_LAMBDA_A_I_B, (A,B)) 
0296 
0297 
0298 // Switch related macros -------------------------------------------
0299 #define BOOST_LAMBDA_SWITCH_CASE_BLOCK(z, N, A) \
0300   case Case##N: \
0301   detail::select(::boost::tuples::get<BOOST_PP_INC(N)>(args), CALL_ACTUAL_ARGS); \
0302   break;
0303 
0304 #define BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(N) \
0305 BOOST_PP_REPEAT(N, BOOST_LAMBDA_SWITCH_CASE_BLOCK, FOO)
0306 // 2 case type:
0307 
0308 #define BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N)                                \
0309 template<class Args, BOOST_LAMBDA_A_I_LIST(N, int Case)>                      \
0310 class                                                                         \
0311 lambda_functor_base<                                                          \
0312       switch_action<BOOST_PP_INC(N),                                          \
0313         BOOST_LAMBDA_A_I_B_LIST(N, detail::case_label<Case,>)                 \
0314       >,                                                                      \
0315   Args                                                                        \
0316 >                                                                             \
0317 {                                                                             \
0318 public:                                                                       \
0319   Args args;                                                                  \
0320   template <class SigArgs> struct sig { typedef void type; };                 \
0321 public:                                                                       \
0322   explicit lambda_functor_base(const Args& a) : args(a) {}                    \
0323                                                                               \
0324   template<class RET, CALL_TEMPLATE_ARGS>                                     \
0325   RET call(CALL_FORMAL_ARGS) const {                                          \
0326     switch( detail::select(::boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ) \
0327     {                                                                         \
0328       BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(N)                                  \
0329     }                                                                         \
0330   }                                                                           \
0331 };
0332 
0333         
0334 
0335 #define BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N)                              \
0336 template<                                                                     \
0337   class Args BOOST_PP_COMMA_IF(BOOST_PP_DEC(N))                               \
0338   BOOST_LAMBDA_A_I_LIST(BOOST_PP_DEC(N), int Case)                            \
0339 >                                                                             \
0340 class                                                                         \
0341 lambda_functor_base<                                                          \
0342       switch_action<BOOST_PP_INC(N),                                          \
0343         BOOST_LAMBDA_A_I_B_LIST(BOOST_PP_DEC(N),                              \
0344                                 detail::case_label<Case, >)                   \
0345         BOOST_PP_COMMA_IF(BOOST_PP_DEC(N))                                    \
0346         detail::default_label                                                 \
0347       >,                                                                      \
0348   Args                                                                        \
0349 >                                                                             \
0350 {                                                                             \
0351 public:                                                                       \
0352   Args args;                                                                  \
0353   template <class SigArgs> struct sig { typedef void type; };                 \
0354 public:                                                                       \
0355   explicit lambda_functor_base(const Args& a) : args(a) {}                    \
0356                                                                               \
0357   template<class RET, CALL_TEMPLATE_ARGS>                                     \
0358   RET call(CALL_FORMAL_ARGS) const {                                          \
0359     switch( detail::select(::boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ) \
0360     {                                                                         \
0361         BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST(BOOST_PP_DEC(N))                  \
0362       default:                                                                \
0363         detail::select(::boost::tuples::get<N>(args), CALL_ACTUAL_ARGS);      \
0364         break;                                                                \
0365     }                                                                         \
0366   }                                                                           \
0367 };
0368 
0369 
0370 
0371 
0372 
0373 
0374 // switch_statement bind functions -------------------------------------
0375 
0376 // The zero argument case, for completeness sake
0377 inline const 
0378 lambda_functor< 
0379   lambda_functor_base< 
0380     do_nothing_action, 
0381     null_type
0382   > 
0383 >
0384 switch_statement() { 
0385   return 
0386       lambda_functor_base< 
0387         do_nothing_action, 
0388         null_type
0389       > 
0390   ();
0391 }
0392 
0393 // 1 argument case, this is useless as well, just the condition part
0394 template <class TestArg>
0395 inline const 
0396 lambda_functor< 
0397   lambda_functor_base< 
0398     switch_action<1>, 
0399     tuple<lambda_functor<TestArg> >
0400   > 
0401 >
0402 switch_statement(const lambda_functor<TestArg>& a1) { 
0403   return 
0404       lambda_functor_base< 
0405          switch_action<1>, 
0406          tuple< lambda_functor<TestArg> > 
0407       > 
0408     ( tuple<lambda_functor<TestArg> >(a1));
0409 }
0410 
0411 
0412 #define HELPER(z, N, FOO)                                      \
0413 BOOST_PP_COMMA_IF(N)                                           \
0414 BOOST_PP_CAT(                                                  \
0415   const tagged_lambda_functor<detail::switch_case_tag<TagData, \
0416   N>)                                                          \
0417 BOOST_PP_COMMA() Arg##N>& a##N
0418 
0419 #define HELPER_LIST(N) BOOST_PP_REPEAT(N, HELPER, FOO)
0420 
0421 
0422 #define BOOST_LAMBDA_SWITCH_STATEMENT(N)                              \
0423 template <class TestArg,                                              \
0424           BOOST_LAMBDA_A_I_LIST(N, class TagData),                    \
0425           BOOST_LAMBDA_A_I_LIST(N, class Arg)>                        \
0426 inline const                                                          \
0427 lambda_functor<                                                       \
0428   lambda_functor_base<                                                \
0429         switch_action<BOOST_PP_INC(N),                                \
0430           BOOST_LAMBDA_A_I_LIST(N, TagData)                           \
0431         >,                                                            \
0432     tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)>     \
0433   >                                                                   \
0434 >                                                                     \
0435 switch_statement(                                                     \
0436   const lambda_functor<TestArg>& ta,                                  \
0437   HELPER_LIST(N)                                                      \
0438 )                                                                     \
0439 {                                                                     \
0440   return                                                              \
0441       lambda_functor_base<                                            \
0442             switch_action<BOOST_PP_INC(N),                            \
0443               BOOST_LAMBDA_A_I_LIST(N, TagData)                       \
0444             >,                                                        \
0445         tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)> \
0446       >                                                               \
0447     ( tuple<lambda_functor<TestArg>, BOOST_LAMBDA_A_I_LIST(N, Arg)>   \
0448         (ta, BOOST_LAMBDA_A_I_LIST(N, a) ));                          \
0449 }
0450 
0451 
0452 
0453 
0454 // Here's the actual generation
0455 
0456 #define BOOST_LAMBDA_SWITCH(N)           \
0457 BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE(N)   \
0458 BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE(N)        
0459 
0460 // Use this to avoid case 0, these macros work only from case 1 upwards
0461 #define BOOST_LAMBDA_SWITCH_HELPER(z, N, A) \
0462 BOOST_LAMBDA_SWITCH( BOOST_PP_INC(N) )
0463 
0464 // Use this to avoid cases 0 and 1, these macros work only from case 2 upwards
0465 #define BOOST_LAMBDA_SWITCH_STATEMENT_HELPER(z, N, A) \
0466 BOOST_LAMBDA_SWITCH_STATEMENT(BOOST_PP_INC(N))
0467 
0468 #ifdef BOOST_MSVC
0469 #pragma warning(push)
0470 #pragma warning(disable:4065)
0471 #endif
0472 
0473   // up to 9 cases supported (counting default:)
0474 BOOST_PP_REPEAT_2ND(9,BOOST_LAMBDA_SWITCH_HELPER,FOO)
0475 BOOST_PP_REPEAT_2ND(9,BOOST_LAMBDA_SWITCH_STATEMENT_HELPER,FOO)
0476 
0477 #ifdef BOOST_MSVC
0478 #pragma warning(pop)
0479 #endif
0480 
0481 } // namespace lambda 
0482 } // namespace boost
0483 
0484 
0485 #undef HELPER
0486 #undef HELPER_LIST
0487 
0488 #undef BOOST_LAMBDA_SWITCH_HELPER
0489 #undef BOOST_LAMBDA_SWITCH
0490 #undef BOOST_LAMBDA_SWITCH_NO_DEFAULT_CASE
0491 #undef BOOST_LAMBDA_SWITCH_WITH_DEFAULT_CASE
0492 
0493 #undef BOOST_LAMBDA_SWITCH_CASE_BLOCK
0494 #undef BOOST_LAMBDA_SWITCH_CASE_BLOCK_LIST
0495 
0496 #undef BOOST_LAMBDA_SWITCH_STATEMENT
0497 #undef BOOST_LAMBDA_SWITCH_STATEMENT_HELPER
0498 
0499 
0500 
0501 #endif
0502 
0503 
0504 
0505 
0506 
0507 
0508