ossrv_pub/boost_apis/boost/lambda/switch.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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