给大家助兴,把以前的模板元代码拿出来分享!

yshuise 2010-09-29 06:39:16
这是模板元编程书籍上的一段代码,很有意思。

#include "stdafx.h"  
#include <iostream>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/filter_view.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/static_assert.hpp>
#include <vector>
#include <ctime>
#include <cassert>


namespace mpl = boost::mpl;
using namespace mpl::placeholders;

//通过递归的“分派”
template<
class Transition
, class Next
>
struct event_dispatcher
{ //Finite State Machines
typedef typename Transition::fsm_t fsm_t;
typedef typename Transition::event event;

static int dispatch(
fsm_t& fsm, int state, event const& e)
{
if (state == Transition::current_state)
{
Transition::execute(fsm, e);
return Transition::next_state;
}
else // move on to the next node in the chain.
{
return Next::dispatch(fsm, state, e);
}
}

};



template <class Derived> class state_machine;
//默认的转发,实际上是一个初始值。
struct default_event_dispatcher
{
template<class FSM, class Event>
static int dispatch(
state_machine<FSM>& m, int state, Event const& e)
{
return m.call_no_transition(state, e);
}
};


template<class Table, class Event>
struct generate_dispatcher;

template<class Derived>
class state_machine
{
// ...
protected:
template<
int CurrentState
, class Event
, int NextState
, void (*action)(Derived&, Event const&)
>
struct row
{
// for later use by our metaprogram
enum { current_state = CurrentState };
enum { next_state = NextState };
typedef Event event;
typedef Derived fsm_t;

// do the transition action.
static void execute(Derived& fsm, Event const& e)
{
(*action)(fsm, e);
}
};


friend struct default_event_dispatcher;

template <class Event>
int call_no_transition(int state, Event const& e)
{
return static_cast<Derived*>(this)->no_transition(state, e); // CRTP downcast

}
//
public:
template<class Event>
int process_event(Event const& evt)
{
// generate the dispatcher type.
typedef typename generate_dispatcher<
/*typename*/ Derived::transition_table, Event
>::type dispatcher;//相同的"Event"为一个row

// dispatch the event.
//这儿来递归的调用。对于相同的"Event",用state来区分。
this->state = dispatcher::dispatch(
*static_cast<Derived*>(this) // CRTP downcast
, this->state
, evt
);

// return the new state
return this->state;
}

// ...
protected:
state_machine()
: state(Derived::initial_state)
{
}

private:
int state;
// ...

// ...
public:
template <class Event>
int no_transition(int state, Event const& e)
{
// assert(false);
return state;
}
// ...
////
};

//在元编程中的固定写法。用类封装。
template <class Event>
struct is_same_event
{
template <class Transition> struct apply
: boost::is_same<Event,typename Transition::event>
{//is_same比较两者类型是否相同,如果一者有const,另外一个没有const,这样算不同的类型。
};
};
//is_same_event比较"event"是否相同
//filter_view,把相同的"event"存放在一起。
//fold对相同的这些"event"调用方法。
/*
template<typename Sequence
,typename State
,typename ForwardOp
>struct fold
{
typedef unspecified type;
};
描述持续调用二元 ForwardOp,
以上一次调用 ForwardOp 所得结果(第一次调用时使用 State)和区间
[begin<Sequence>::type, end<Sequence>::type) 的每个元素为参数,
返回最终的结果。
*/

template<class Table, class Event>
struct generate_dispatcher
: mpl::fold<
mpl::filter_view< // select rows triggered by Event
Table
, is_same_event<Event>
>
, default_event_dispatcher
, event_dispatcher<_2,_1>
>
{};
//全例子最难的就是这个算法调用。上面的调用经过扩展,当参数是
//open_close()的时候
//event_dispatcher<state_machine<player>::row<4,open_close,1,&player::stop_and_open>,
// event_dispatcher<state_machine<player>::row<3,open_close,1,&player::stop_and_open>,
// event_dispatcher<state_machine<player>::row<0,open_close,1,&player::open_drawer>,
// event_dispatcher<state_machine<player>::row<2,open_close,1,&player::open_drawer>,default_event_dispatcher>>>>
//可以利用新建对象的方法来跟踪其类型。这是一个诀窍。

struct play {};
struct open_close {};
struct cd_detected {
cd_detected(char const*, std::vector<clock_t> const&) {}
};
#ifdef __GNUC__ // in which pause seems to have a predefined meaning
# define pause pause_
#endif
struct pause {};
struct stop {};


// concrete FSM implementation
class player : public state_machine<player>
{
public:
// the list of FSM states
enum states {
Empty, Open, Stopped, Playing, Paused
, initial_state = Empty
};


#ifdef __MWERKS__
public: // Codewarrior bug workaround. Tested at 0x3202
#endif

static void start_playback(player&, play const&);
static void open_drawer(player&, open_close const&);
static void close_drawer(player&, open_close const&);
static void store_cd_info(player&, cd_detected const&);
static void stop_playback(player&, stop const&);
static void pause_playback(player&, pause const&);
static void resume_playback(player&, play const&);
static void stop_and_open(player&, open_close const&);


#ifdef __MWERKS__
private:
#endif
friend class state_machine<player>;
typedef player p; // makes transition table cleaner

// transition table
struct transition_table : mpl::vector<

// Start Event Next Action
// +---------+-------------+---------+------------------+
row < Stopped , play , Playing , &start_playback >,
row < Stopped , open_close , Open , &open_drawer >,
// +---------+-------------+---------+------------------+
row < Open , open_close , Empty , &close_drawer >,
// +---------+-------------+---------+------------------+
row < Empty , open_close , Open , &open_drawer >,
row < Empty , cd_detected , Stopped , &store_cd_info >,
// +---------+-------------+---------+------------------+
row < Playing , stop , Stopped , &stop_playback >,
row < Playing , pause , Paused , &pause_playback >,
row < Playing , open_close , Open , &stop_and_open >,
// +---------+-------------+---------+------------------+
row < Paused , play , Playing , &resume_playback >,
row < Paused , stop , Stopped , &stop_playback >,
row < Paused , open_close , Open , &stop_and_open >
// +---------+-------------+---------+------------------+

> {};
typedef

event_dispatcher<
row<Stopped, play const, Playing, &start_playback>
, event_dispatcher<
row<Paused, play const, Playing, &resume_playback>
, default_event_dispatcher
>
>
dummy;
};

void player::start_playback(player&, play const&)
{
std::cout<<"start_playback "<< std::endl;
}

void player::open_drawer(player&, open_close const&)
{
std::cout<<"open_drawer "<< std::endl;
}

void player::close_drawer(player&, open_close const&)
{
std::cout<<"close_drawer "<< std::endl;
}
void player::store_cd_info(player&, cd_detected const&)
{
std::cout<<"store_cd_info "<< std::endl;
}

void player::stop_playback(player&, stop const&)
{
std::cout<<"stop_playback "<< std::endl;
}

void player::pause_playback(player&, pause const&)
{
std::cout<<"pause_playback "<< std::endl;
}

void player::resume_playback(player&, play const&)
{
std::cout<<"resume_playback "<< std::endl;
}

void player::stop_and_open(player&, open_close const&)
{
std::cout<<"stop_and_open "<<std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
player p; // An instance of the FSM

p.process_event(open_close()); // user opens CD player
p.process_event(open_close()); // inserts CD and closes
p.process_event( // CD is detected
cd_detected(
"Louie, Louie"
, std::vector<clock_t>( /* track lengths */ )
)
);
p.process_event(play()); // etc.
p.process_event(pause());
p.process_event(play());
p.process_event(stop());

return 0;
}
...全文
425 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
云瑀 2010-09-30
  • 打赏
  • 举报
回复
多谢分享
herman~~ 2010-09-30
  • 打赏
  • 举报
回复
lz 呀,如果是一个状态机的功能麻烦考虑到后来维护的人的效率,用switch -case 来实现吧
BT六眼飞鱼 2010-09-30
  • 打赏
  • 举报
回复
学习一下~~~~
yshuise 2010-09-30
  • 打赏
  • 举报
回复
[Quote=引用 36 楼 healer_kx 的回复:]
引用 22 楼 yshuise 的回复:

引用 20 楼 code_99 的回复:
引用楼主 yshuise 的回复:
这是模板元编程书籍上的一段代码,很有意思。


C/C++ code
#include "stdafx.h"
#include <iostream>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/fil……
[/Quote]
有的。
healer_kx 2010-09-30
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 yshuise 的回复:]

引用 20 楼 code_99 的回复:
引用楼主 yshuise 的回复:
这是模板元编程书籍上的一段代码,很有意思。


C/C++ code
#include "stdafx.h"
#include <iostream>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/filter_view.hpp>
#include……
[/Quote]

这本书一直没有买到,我问了,不再刊印了。只有部分人看这个书能看到乐趣。
luciferisnotsatan 2010-09-30
  • 打赏
  • 举报
回复
学习了
xengine-qyt 2010-09-30
  • 打赏
  • 举报
回复
留名!!
冰岛男孩 2010-09-30
  • 打赏
  • 举报
回复
学习啦。。
24K純帥 2010-09-30
  • 打赏
  • 举报
回复
学习啦。。
fengbingchun 2010-09-30
  • 打赏
  • 举报
回复
...............
xxlovec 2010-09-30
  • 打赏
  • 举报
回复
也不说说干啥用的
colorfulcode 2010-09-30
  • 打赏
  • 举报
回复
观摩一下
cheng_fengming 2010-09-30
  • 打赏
  • 举报
回复
没怎么看懂,先mark一下,以后有用的着的时候在看。
gliterbin 2010-09-30
  • 打赏
  • 举报
回复
学习一下~~
hslinux 2010-09-30
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 freezezdj 的回复:]

向楼主学习,向所有的星星学习
[/Quote]
nkinuyasha 2010-09-30
  • 打赏
  • 举报
回复
学习一下
yshuise 2010-09-30
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 code_99 的回复:]
引用楼主 yshuise 的回复:
这是模板元编程书籍上的一段代码,很有意思。


C/C++ code
#include "stdafx.h"
#include <iostream>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/filter_view.hpp>
#include <boost/type_traits/is_……
[/Quote]
《c++模板元编程》
AAA20090987 2010-09-30
  • 打赏
  • 举报
回复
留个标记,等我变成牛人之后再看
code_99 2010-09-29
  • 打赏
  • 举报
回复
[Quote=引用楼主 yshuise 的回复:]
这是模板元编程书籍上的一段代码,很有意思。


C/C++ code
#include "stdafx.h"
#include <iostream>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/filter_view.hpp>
#include <boost/type_traits/is_same.hpp> ……
[/Quote]
请问楼主是什么书上的代码?
昵称很不好取 2010-09-29
  • 打赏
  • 举报
回复
支持下~~
加载更多回复(18)

64,685

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧