如何获得返回自身的boost :: function(或其他通用函数包装器)?

Man*_*agu 6 c++ gcc boost fsm

我最近迷恋于Erlang基于actor的并发模型的简单性,并且正在尝试用C++实现它的某些部分.沿着这些方向,我也喜欢将有限状态机实现为表示状态的函数集合的想法,其中通过从一个函数到下一个函数的尾调用来进行转换.

我想在C++中尝试类似的东西.但是这种天真的实现可能会遇到这样的事实,即在我的编译器(GCC 4.1 with -O0)中进行尾调用最终会导致堆栈溢出.所以不是,我想要做的就是让每个国家/函数返回一个仿函数(下一个状态进入),并具有潜在的循环刚刚依次调用一个函数对象,然后调用从而返回仿函数,然后调用函子因此返回,等等:

typedef ... context_t;

// A statefunctor is a functor which takes a context_t and 
// returns a statefunctor
//
// FIXME: of course, this typedef won't compile.
typedef boost::function<statefunctor (context_t& )> statefunctor;

// NULL boost::function<> represents the exit condition.
static const statefunctor EXIT_FSM;

// primary loop which runs the FSM
void run_fsm(context_t& ctx, statefunctor initial_state)
{
    while (initial_state)
    {
        initial_state=initial_state(boost::ref(ctx));
    }
}

// states 'foo', 'bar', and 'baz';
statefunctor foo(context_t& ctx);
statefunctor bar(context_t& ctx, int inval);
statefunctor baz(context_t& ctx);

// State 'foo'
statefunctor foo(context_t& ctx)
{
    // act somehow on the external context
    int magic_number_1=ctx.get_magic_number();
    int magic_number_2=ctx.get_magic_number();

    // Always transition to 'bar'
    return boost::bind(&bar, _1, magic_number_1-magic_number_2);
}

// State 'bar'
statefunctor bar(context_t& ctx, int inval)
{
    inval+=ctx.get_magic_number(); // Act on external context somehow

    // transition to foo or baz
    if (inval>0) { return &foo; }
    else { return &baz; }
}

// State 'baz'
statefunctor baz(context_t& ctx)
{
    // Transition to foo or exit
    if (ctx.get_magic_number()==5) {return EXIT_FSM;}
    else {return &foo;}
}

int main()
{
    context_t ctx;
    // start the state machine in state 'foo'
    run_fsm(ctx, &foo);
}
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是,我该如何定义statefunctor?特别是,我希望它能够保存任意仿函数(比如boost::bind(...)可能创建),而不仅仅是函数指针.

注:我使用boost::bind,boost::function,boost::ref而不是他们std::的同行,因为我坚持使用GCC 4.1,这对于C++ 11的支持.欢迎在C++ 03中有效的解决方案;-).

Xeo*_*Xeo 5

你不能通过a直接做到这一点typedef,但是你可以把它包装boost::function在一个struct/class中(感谢@ R.Martinho Fernandes让我有这个洞察力):

#include <boost/function.hpp>

typedef int context_t;

struct statefunctor
  : boost::function<statefunctor(context_t&)>
{
  typedef boost::function<statefunctor(context_t&)> base_type;
  statefunctor() : base_type(){}
  template<class F>
  statefunctor(F f) : base_type(f){}
};
Run Code Online (Sandbox Code Playgroud)

实例.