2017-04-15 3 views
0

Hier wird Setup meiner Anwendung vereinfacht:Enum-Wert abhängiger Funktionsaufruf

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

Was ich will ist die Sprungfunktion zu tun, rufen Sie abhängig von dem aktuellen Wert im Zustand Mitglied. In Schritt() -Aufruf ist der Zustand kein konstanter Ausdruck, der ein Problem darstellt. Gibt es eine Möglichkeit, diesen enumabhängigen Funktionsaufruf ohne großen hässlichen Schalter zu schreiben?

(Dies ist nur ein vereinfachtes Beispiel mit einer Funktion und nur 2 Zuständen).

+0

Ihre Schrittvorlage ist inhärent ein Kompilierzeitkonstrukt, und die run() - Auswahl ist inhärent ein Laufzeitkonstrukt. Sie können nicht nur die zwei mischen. Sie können eine Metaprogrammierung anwenden, um alle möglichen Zustände in der Kompilierungszeit aufzuzählen und eine Runtime-Schalttafel zu erzeugen. Oder Sie können eine der vorhandenen Bibliotheken verwenden, die Boost MSM machen. –

+0

[Dieser Artikel] (https://kfrlib.com/blog/how-c14-and-c17-help-to-write-faster-and-better-code-real-world-examples/) erwähnt einen 'cswitch' Vorlage, die dafür wahrscheinlich verwendet werden könnte. – zett42

Antwort

2

Nein, Sie können die Verwendung von switch nicht vermeiden, wenn Sie den Status verwenden, der nicht constexpr ist. Dies ist die Natur von Staatsmaschinen. Alles, was Sie tun können, ist zu versuchen, es weniger hässlich aussehen zu lassen:

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

UPD: es andere Abfertigungstechniken sind z.B. Speichern eines Arrays von Funktionszeigern wie @KonstantinL vorgeschlagen oder mit std::map von std::function s, aber jeder von ihnen erfordert, dass Sie manuell eine Tabelle mit Enumeratoren und entsprechenden Handlern aufschreiben. Unter allen von ihnen bevorzuge ich die mit der geringsten Indirektion, die einfach alt ist switch.

+0

Ja, ich habe versucht, es mit Array von Funktionen zu schreiben, aber die Array-Initialisierung in Engine Ctor war so lange wie die Verwendung von Schalter, aber viel hässlicher –

+0

Ok, also habe ich alle zustandsabhängigen Funktionen, die in der Hauptschleife Programm aufgerufen werden eine Template-Loop-Funktion, die ich genau wie Sie in Ihrem Beispiel innerhalb des Switches rufe. Danke für die Hilfe. –

Verwandte Themen