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



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

我想在C++中尝试一些类似的东西。但是,这方面的天真实现可能会遇到这样一个事实,即在我的编译器(带有-O0的GCC 4.1)中的尾部调用最终会导致堆栈溢出。因此,我想做的是让每个状态/函数返回一个函子(下一个要进入的状态),并有一个底层循环,它只是顺序地调用函子,然后调用返回的函子,再调用返回的函数,等等

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);
}

那么,我的问题是,如何定义statefunctor?特别是,我希望它能够容纳任意的函子(比如boost::bind(...)可能创建的),而不仅仅是函数指针。

注意:我使用boost::bindboost::functionboost::ref,而不是它们的对应std::,因为我一直在使用GCC 4.1,它不支持C++11。非常感谢C++03中有效的解决方案;-)。

你不能直接通过typedef来实现这一点,但你可以将boost::function封装在一个结构/类中(感谢@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){}
};

活生生的例子。

这是impossibru。类型将是无限的,并且问题与定义返回自身的函数指针时遇到的问题相同。唯一的方法是用运算符()手动编写自己的函数对象,这可以返回*this,并连锁()调用。您也可以以其他方式使用运算符链接,如std::cout中所示。

您不能。问题是,返回类型的定义必须是递归的,这是不可能的。

相关内容

最新更新