2017-04-15 9 views
0

は自分のアプリケーションのセットアップを簡素化されます。列挙値に依存する関数呼び出し

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

は、私は何をしたい状態のメンバーの現在の値に依存ステップ関数を呼び出しています。 step()呼び出しでは、状態は定数式ではなく、問題になります。いくつかの大きな醜いスイッチなしでこの列挙型の関数呼び出しを書く方法はありますか?

(これは1つの機能と2つの状態のみの簡略化された例です)。

+0

ステップテンプレートは本質的にコンパイル時の構造体であり、run()選択は本質的にランタイム構造体です。あなたは2つを混ぜ合わせることはできません。いくつかのメタプログラミングを適用して、コンパイル時にすべての可能な状態を列挙し、ランタイムスイッチボードを生成することができます。あるいは、Boost MSMのような既存のライブラリを使用することもできます。 –

+0

[この記事](https://kfrlib.com/blog/how-c14-and-c17-help-to-write-faster-and-better-code-real-world-examples/)には、「cswitch」そのために適切に使用することができるテンプレート。 – zett42

答えて

2

いいえ、constexprでない状態を使用している場合は、switchを使用することは避けられません。これは状態機械の性質です。あなたがすることができるすべてはそれがあまり醜く見えるようにしようとしている。

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

UPD:他の発送方法があり、例えば@ ConstantinLのように関数ポインタの配列を格納するか、std::mapstd::functionに設定しますが、列挙子と対応するハンドラを持つテーブルを手動で書き留める必要があります。それらのすべての中で、私は間接的な差異が最小のものを好みます。これは普通の古いものですswitch

+0

ええ、私は関数の配列でそれを書こうとしましたが、エンジンctorの配列の初期化はスイッチを使用していたが、ずっと醜いです。 –

+0

これで、メインプログラムループで呼び出されるすべての状態依存関数をラップしましたテンプレート化されたループ関数です。これは、スイッチの中のあなたの例のように呼びます。手伝ってくれてありがとう。 –

関連する問題