Can a function return a pointer to its own type?

I implemented a very minimal end machine in the class, and my initial approach was to try the following:

class Widget { public: void update(float time_interval){ current_state = current_state_(time_interval); } private: std::function< ?? > off_(float); std::function< ?? > standby_(float); std::function< ?? > locked_(float); std::function< ?? > current_state_; // initialised to off_ }; 

Each state is a function that returns a state. But I cannot decide how to declare a function whose return type includes its return type. Is there a way to break recursion?

Instead, I used the enum class and the ugly switch .

+5
source share
2 answers

If I understand correctly, do you want to return a function link to the next function in the state chain and that all functions of the state step have the same signature?

I see that the problem is that the return type is the function itself, so declaring the type of the function calls a recursive type definition.

So you want to write RetType fn_(float) form functions, but RetType type (basically) RetType fn_(float) . So now we have (RetType (*)(float)) fn_(float) or something like that, but no matter how hard we try, we can't get rid of RetType.

You cannot disable this recursion without forwardly declaring something. We can forward declaration classes and use them, so let's write a simple class wrapper for your function pointer, which may have hinted at @Jarod. Now std :: function is a class sort for your function, but this requires an explicit type declaration, which we do not have.

 class Widget; class StateFn; class StateFn { Widget * THIS; StateFn (Widget::*Fn)(float); public: /// Or you could rely on POD construction StateFn(Widget * THIS, StateFn (Widget::*Fn)(float)) : THIS(THIS), Fn(Fn) {} StateFn operator()(float f) { return THIS->*fn(f); } }; 

So now the recursive definition is broken, our state functions can return StateFn objects, and we can call them.

+4
source

I found a solution - using std::unordered_map to replace the ugly switch :

 class Widget { public: enum class State { Off, Standby, Locked }; void update(float time_interval) { current_state_ = (this->*state_fn_.at(state_))(time_interval); } private: State off_(float) {return ::has_power() ? State::Standby : State::Off;} State standby_(float); State locked_(float); const std::unordered_map<State, State(Widget::*)(float)> state_fn_{ {State::Off, &Widget::off_}, {State::Standby, &Widget::standby_}, {State::Locked, &Widget::locked_}}; State current_state_{State::Off}; }; 

This is only 1 + 3n lines of code worse than the perfect code I put in the question - I am pleased with that!

0
source

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


All Articles