Boost :: Variantを使用してモデルの状態を記述する

データモデルでは、多くの場合、いくつかのスイッチング状態を保存する必要があります。 C ++でこれを行う古典的な方法は、enum列挙型を使用することです。



たとえば、プログラムでユーザーが2つの画面を切り替えることができる場合、enum screen {screen_one、screen_two}を開始します。 および変数screen cur_screen_。 レンダラーは、モデルから「現在選択されている画面」を取得してから描画し、この特定の画面に関連する追加データをモデルに要求します。 次のようなもの:



switch (model.cur_screen())

{

case screen_one:

model.get_screen_one_elements();

...

case screen_two:

model.get_screen_two_elements();

...

}









このモデルを使用すると、プログラマーは現在の状態とはまったく関係のないデータを要求できます。 たとえば、get_screen_two_elements()メソッドを呼び出して、現在の画面が最初の画面である場合に2番目の画面の要素のリストを取得します。 画面固有のメソッドでASSERTアサーション(cur_screen_ == screen_one)を使用することをお勧めします。 これにより、ランタイム制御が提供されます。



ただし、boost :: variantを使用して、コンパイル時の制御とより明確な状態分離を提供する方法があります。





このアプローチでは、screen_oneとscreen_twoは列挙型要素ではなく、完全なクラスです。 そして、この状態に依存するすべてのデータとメソッドは、状態クラスに入ります。



メインモデルにはget_screen_one_elements()メソッドはなくなりました。screen_oneクラスにはget_elements()メソッドがあります。 現在選択されている画面は、boost :: variant <screen_one、screen_two>型の変数に保存されます。



class screen_one

{

public :

const std :: vector < screen_one_elements >& get_elements() const

{

return ...;

}

};



class screen_two

{

public :

const std :: vector < screen_two_elements >& get_elements() const

{

return ...;

}

};



class cool_data_model

{

public :

typedef boost :: variant < screen_one, screen_two > screen;



template < typename NewScreenType >

void change_screen( const NewScreenType & new_val)

{

cur_screen_ = new_val;

}



template < typename VisitorType >

VisitorType :: result_type apply_visitor( const VisitorType & visitor)

{

return boost :: apply_visitor(visitor, cur_screen_);

}

private :

screen cur_screen_;

};









このようなモデルを知覚(描画)するには、ビジターメカニズムを使用する必要があります。 これは、バリアントの各要素の括弧演算子を定義する特別なファンクターです。 私たちの場合、各州に対して。



class painter : public boost :: static_visitor <>

{

public :

void operator ()( const screen_one & val_screen)

{

// ,

val_screen.get_elements();

...

}

void operator ()( const screen_two & val_screen)

{

// ,

val_screen.get_elements();

...

}

};



model.apply_visitor(painter());









状態クラスは、画面が「選択された状態」にある時間に必要なデータを保存し、すべての特定の機能を提供します。 最初の画面が現在の画面として選択されている場合、2番目の画面の機能は使用できません。



一般的に、訪問者の概念は、物理学の「測定」の操作に精神的に非常に似ています。 特定のシステムがあり、それに測定器を適用します。 結果を取得し、システムの状態を変更します。



さらに、訪問者を言語コンパイラに使用すると非常に便利です。 分析によってAST(要素のツリー)を取得し、分析、最適化、および結果の出力のためにさまざまなツールを適用します。



All Articles