How can I get boost :: function (or another common shell of functions) that returns itself?

I recently fell in love with the simplicity of the concurrency model based on the Erlang action, and I play with ideas to implement some of its parts in C ++. Along these lines, I also like the idea of ​​implementing a finite state machine as a collection of functions representing states where transitions are performed by calling the tail from one function to the next.

I would like to try something similar in C ++. But a naive implementation of this is likely to run into the fact that the tail calling my compiler (GCC 4.1 with -O0 ) will eventually lead to a stack overflow. So instead, I want each state / function to return a functor (the next state to enter) and contain a base loop that just calls the functor, then calls the returned functor, then calls the functor returned this way, etc. Sort of:

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

So my question is: how to define a statefunctor ? In particular, I want it to contain arbitrary functors (for example, boost::bind(...) could create), and not just function pointers.

NOTE: I use boost::bind , boost::function , boost::ref instead of my std:: counterparts because I am stuck using GCC 4.1 which does not support C ++ 11. Solutions valid in C ++ 03 are evaluated :-).

+6
source share
3 answers

You cannot directly do this with typedef , but you can wrap boost::function in struct / class (thanks to @R. Martinho Fernandes for having this understanding):

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

Real-time example.

+5
source

It's impossible. The type will be infinite, and the problem will be identical to the one you will encounter with the definition of a function pointer that returns itself. The only way to do this is to manually write your own functional object using the () operator, this can return calls to *this and chain () . You can also use the chain of statements in other ways, as you can see in std::cout .

+3
source

You can not. The problem is that the definition of the return type must be recursive, and this is not possible.

0
source

Source: https://habr.com/ru/post/924762/


All Articles