0

Here is simplified setup of my application:

class Engine {
    void run(); { // main program loop
        while (state != gameState::quit)
            step<state>(); // ERROR
    }

    template<gameState>
    void step() {} // empty default step function

    template<>
    void step<gameState::intro>() { /* do step for intro state*/ }
    template<>
    void step<gameState::menu>() { /* do step for menu state*/ }

    gameState state;
}

What I want to do is call the step function dependant on the current value in state member. In step() call, the state isn't a constant expression which is a problem. Is there a way to write this enum dependant function call without some big ugly switch?

(This is only a simplified example with one function and only 2 states).

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Maroš Beťko
  • 2,181
  • 2
  • 16
  • 42
  • Your step template is inherently a compile-time construct, and run() selection is inherently a runtime construct. You can't just mix the two. You can apply some metaprogramming to enumerate all the possible states in compile-time and generate some runtime switchboard. Or you can use one of the existing libraries which do that like Boost MSM. – Andrey Turkin Apr 15 '17 at 10:09
  • [This article](https://kfrlib.com/blog/how-c14-and-c17-help-to-write-faster-and-better-code-real-world-examples/) mentions a `cswitch` template that could propably be used for that. – zett42 Apr 15 '17 at 10:52

1 Answers1

2

No, you can't avoid using switch when using state which is not constexpr. This is the nature of state machines. All you can do is try to make it look less ugly:

void dispatch_state(gameState st) {
    switch(st) {
        case gameState::intro: handle_intro(); break;
        case gameState::menu:  handle_menu(); break;
        // etc...
    }
}

UPD: there are other dispatch techniques, e.g. storing an array of function pointers as @KonstantinL suggested, or having an std::map of std::functions, but each of them requires you to manually write down a table with enumerators and corresponding handlers. Among all of them I prefer the one with minimum indirection, which is plain old switch.

Oleg Andriyanov
  • 5,069
  • 1
  • 22
  • 36
  • Yeah I've tried to write it with array of functions but the array initialization in engine ctor was as long as using switch but much uglier – Maroš Beťko Apr 15 '17 at 10:55
  • Ok so I've wrapped all the state dependant functions that are called in the main program loop into a templated loop function, which I call just like you in your example inside the switch. Thanks for help. – Maroš Beťko Apr 15 '17 at 11:03