The c++ template metaprogramming( Chapter 11. A DSEL Design )

来源:转载

[c-sharp] view plaincopy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. #include <boost/mpl/fold.hpp>  
  4. #include <boost/mpl/filter_view.hpp>  
  5. #include <boost/type_traits/is_same.hpp>  
  6. #include <boost/mpl/vector.hpp>  
  7. #include <boost/mpl/placeholders.hpp>  
  8. #include <boost/mpl/assert.hpp>  
  9. #include <boost/static_assert.hpp>  
  10. #include <vector>  
  11. #include <ctime>  
  12. #include <cassert>  
  13.   
  14.   
  15. namespace mpl = boost::mpl;  
  16. using namespace mpl::placeholders;  
  17.   
  18. //通过递归的“分派”  
  19. template<  
  20.     class Transition  
  21.         , class Next  
  22. >  
  23. struct event_dispatcher  
  24. {  //Finite State Machines  
  25.     typedef typename Transition::fsm_t fsm_t;  
  26.     typedef typename Transition::event event;  
  27.   
  28.     static int dispatch(  
  29.         fsm_t& fsm, int state, event const& e)  
  30.     {  
  31.         if (state == Transition::current_state)  
  32.         {  
  33.             Transition::execute(fsm, e);  
  34.             return Transition::next_state;  
  35.         }  
  36.         else // move on to the next node in the chain.  
  37.         {  
  38.             return Next::dispatch(fsm, state, e);  
  39.         }  
  40.     }  
  41.   
  42. };  
  43.   
  44.   
  45.   
  46. template <class Derived> class state_machine;  
  47. //默认的转发,实际上是一个初始值。  
  48. struct default_event_dispatcher  
  49. {  
  50.     template<class FSM, class Event>  
  51.     static int dispatch(  
  52.         state_machine<FSM>& m, int state, Event const& e)  
  53.     {  
  54.         return m.call_no_transition(state, e);  
  55.     }  
  56. };  
  57.   
  58.   
  59. template<class Table, class Event>  
  60. struct generate_dispatcher;  
  61.   
  62. template<class Derived>  
  63. class state_machine  
  64. {  
  65.     // ...  
  66. protected:  
  67.     template<  
  68.         int CurrentState  
  69.         , class Event  
  70.         , int NextState  
  71.         , void (*action)(Derived&, Event const&)  
  72.     >  
  73.     struct row  
  74.     {  
  75.         // for later use by our metaprogram  
  76.         enum { current_state = CurrentState };  
  77.         enum { next_state = NextState };  
  78.         typedef Event event;  
  79.         typedef Derived fsm_t;  
  80.   
  81.         // do the transition action.  
  82.         static void execute(Derived& fsm, Event const& e)  
  83.         {  
  84.             (*action)(fsm, e);  
  85.         }  
  86.     };  
  87.   
  88.   
  89.     friend struct default_event_dispatcher;  
  90.   
  91.     template <class Event>  
  92.     int call_no_transition(int state, Event const& e)  
  93.     {  
  94.         return static_cast<Derived*>(this)->no_transition(state, e);  // CRTP downcast  
  95.               
  96.     }  
  97.     //   
  98. public:  
  99.         template<class Event>  
  100.     int process_event(Event const& evt)  
  101.     {  
  102.         // generate the dispatcher type.  
  103.         typedef typename generate_dispatcher<  
  104.             /*typename*/ Derived::transition_table, Event  
  105.         >::type dispatcher;//相同的"Event"为一个row  
  106.         
  107.         // dispatch the event.  
  108.         //这儿来递归的调用。对于相同的"Event",用state来区分。  
  109.         this->state = dispatcher::dispatch(  
  110.             *static_cast<Derived*>(this)        // CRTP downcast  
  111.             , this->state  
  112.             , evt  
  113.             );  
  114.   
  115.         // return the new state  
  116.         return this->state;  
  117.     }  
  118.   
  119.     // ...  
  120. protected:  
  121.     state_machine()  
  122.         : state(Derived::initial_state)  
  123.     {  
  124.     }  
  125.   
  126. private:  
  127.     int state;  
  128.     // ...  
  129.   
  130.     // ...  
  131. public:  
  132.     template <class Event>  
  133.     int no_transition(int state, Event const& e)  
  134.     {  
  135.     //  assert(false);  
  136.         return state;  
  137.     }  
  138.     // ...  
  139.     ////  
  140. };  
  141.   
  142. //在元编程中的固定写法。用类封装。  
  143. template <class Event>   
  144. struct is_same_event  
  145. {  
  146.     template <class Transition> struct apply  
  147.         : boost::is_same<Event,typename Transition::event>  
  148.     {//is_same比较两者类型是否相同,如果一者有const,另外一个没有const,这样算不同的类型。  
  149.     };  
  150. };  
  151. //is_same_event比较"event"是否相同  
  152. //filter_view,把相同的"event"存放在一起。  
  153. //fold对相同的这些"event"调用方法。  
  154. /* 
  155. template<typename Sequence 
  156.         ,typename State    
  157.         ,typename ForwardOp     
  158.         >struct fold 
  159.     typedef unspecified type; 
  160. }; 
  161. 描述持续调用二元 ForwardOp, 
  162. 以上一次调用 ForwardOp 所得结果(第一次调用时使用 State)和区间  
  163. [begin<Sequence>::type, end<Sequence>::type) 的每个元素为参数, 
  164. 返回最终的结果。 
  165. */  
  166.   
  167. template<class Table, class Event>  
  168. struct generate_dispatcher  
  169.     : mpl::fold<  
  170.     mpl::filter_view<   // select rows triggered by Event  
  171.     Table  
  172.     , is_same_event<Event>  
  173.     >  
  174.     , default_event_dispatcher  
  175.     , event_dispatcher<_2,_1>   
  176.     >  
  177. {};  
  178. //全例子最难的就是这个算法调用。上面的调用经过扩展,当参数是  
  179. //open_close()的时候  
  180. //event_dispatcher<state_machine<player>::row<4,open_close,1,&player::stop_and_open>,  
  181.         //  event_dispatcher<state_machine<player>::row<3,open_close,1,&player::stop_and_open>,  
  182.         //  event_dispatcher<state_machine<player>::row<0,open_close,1,&player::open_drawer>,  
  183.         //  event_dispatcher<state_machine<player>::row<2,open_close,1,&player::open_drawer>,default_event_dispatcher>>>>  
  184. //可以利用新建对象的方法来跟踪其类型。这是一个诀窍。  
  185.   
  186. struct play {};  
  187. struct open_close {};  
  188. struct cd_detected {   
  189.     cd_detected(char const*, std::vector<clock_t> const&) {}  
  190. };  
  191. #ifdef __GNUC__ // in which pause seems to have a predefined meaning  
  192. # define pause pause_  
  193. #endif  
  194. struct pause {};  
  195. struct stop {};  
  196.   
  197.   
  198. // concrete FSM implementation   
  199. class player : public state_machine<player>  
  200. {  
  201. public:  
  202.     // the list of FSM states  
  203.     enum states {  
  204.         Empty, Open, Stopped, Playing, Paused  
  205.         , initial_state = Empty  
  206.     };  
  207.  
  208.  
  209. #ifdef __MWERKS__  
  210. public: // Codewarrior bug workaround.  Tested at 0x3202  
  211. #endif  
  212.   
  213.     static void start_playback(player&, play const&);  
  214.     static void open_drawer(player&, open_close const&);  
  215.     static void close_drawer(player&, open_close const&);  
  216.     static void store_cd_info(player&, cd_detected const&);  
  217.     static void stop_playback(player&, stop const&);  
  218.     static void pause_playback(player&, pause const&);  
  219.     static void resume_playback(player&, play const&);  
  220.     static void stop_and_open(player&, open_close const&);  
  221.  
  222.  
  223. #ifdef __MWERKS__  
  224. private:  
  225. #endif   
  226.     friend class state_machine<player>;  
  227.     typedef player p; // makes transition table cleaner  
  228.   
  229.     // transition table  
  230.     struct transition_table : mpl::vector<  
  231.   
  232.         //    Start     Event         Next      Action  
  233.         //  +---------+-------------+---------+------------------+  
  234.         row < Stopped , play        , Playing , &start_playback  >,  
  235.         row < Stopped , open_close  , Open    , &open_drawer     >,  
  236.         //  +---------+-------------+---------+------------------+  
  237.         row < Open    , open_close  , Empty   , &close_drawer    >,  
  238.         //  +---------+-------------+---------+------------------+  
  239.         row < Empty   , open_close  , Open    , &open_drawer     >,  
  240.         row < Empty   , cd_detected , Stopped , &store_cd_info   >,  
  241.         //  +---------+-------------+---------+------------------+  
  242.         row < Playing , stop        , Stopped , &stop_playback   >,  
  243.         row < Playing , pause       , Paused  , &pause_playback  >,  
  244.         row < Playing , open_close  , Open    , &stop_and_open   >,  
  245.         //  +---------+-------------+---------+------------------+  
  246.         row < Paused  , play        , Playing , &resume_playback >,  
  247.         row < Paused  , stop        , Stopped , &stop_playback   >,  
  248.         row < Paused  , open_close  , Open    , &stop_and_open   >  
  249.         //  +---------+-------------+---------+------------------+  
  250.   
  251.     > {};  
  252.     typedef  
  253.   
  254.         event_dispatcher<  
  255.         row<Stopped, play const, Playing, &start_playback>  
  256.         , event_dispatcher<  
  257.         row<Paused, play const, Playing, &resume_playback>  
  258.         , default_event_dispatcher  
  259.         >  
  260.         >  
  261.         dummy;  
  262. };  
  263.   
  264. void player::start_playback(player&, play const&)  
  265. {  
  266.     std::cout<<"start_playback "<< std::endl;  
  267. }  
  268.   
  269. void player::open_drawer(player&, open_close const&)  
  270. {  
  271.     std::cout<<"open_drawer "<< std::endl;  
  272. }  
  273.   
  274. void player::close_drawer(player&, open_close const&)  
  275. {  
  276.     std::cout<<"close_drawer "<< std::endl;  
  277. }  
  278. void player::store_cd_info(player&, cd_detected const&)  
  279. {  
  280.     std::cout<<"store_cd_info "<< std::endl;  
  281. }  
  282.   
  283. void player::stop_playback(player&, stop const&)  
  284. {  
  285.     std::cout<<"stop_playback "<< std::endl;  
  286. }  
  287.   
  288. void player::pause_playback(player&, pause const&)  
  289. {  
  290.     std::cout<<"pause_playback "<< std::endl;  
  291. }  
  292.   
  293. void player::resume_playback(player&, play const&)  
  294. {  
  295.     std::cout<<"resume_playback "<< std::endl;  
  296. }  
  297.   
  298. void player::stop_and_open(player&, open_close const&)  
  299. {  
  300.     std::cout<<"stop_and_open "<<std::endl;  
  301. }  
  302.   
  303. int _tmain(int argc, _TCHAR* argv[])  
  304. {   
  305.     player p;                      // An instance of the FSM  
  306.   
  307.     p.process_event(open_close()); // user opens CD player  
  308.     p.process_event(open_close()); // inserts CD and closes  
  309.     p.process_event(               // CD is detected  
  310.         cd_detected(  
  311.         "Louie, Louie"  
  312.         , std::vector<clock_t>( /* track lengths */ )  
  313.         )  
  314.         );  
  315.     p.process_event(play());       // etc.  
  316.     p.process_event(pause());  
  317.     p.process_event(play());  
  318.     p.process_event(stop());  
  319.   
  320.     return 0;  
  321. }  

上文来自:http://blog.csdn.net/yshuise/article/details/4762313


分享给朋友:
您可能感兴趣的文章:
随机阅读: