os/ossrv/ossrv_pub/boost_apis/boost/lambda/switch.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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