ここでは、いくつかの考慮事項があります。
ディスクからファイルを解析し、ディスク上のタイプに基づいてオブジェクトを作成するとします。これらのオブジェクトは、ほとんど区別できない方法で処理します。使用しているタイプの有限リストがあります。
これに使用する答えはboost::variant
、データを保存するためのものであり、map
(Matthiew の答えのように) タイプの名前をタイプのリーダー (またはパーサー) にマップするものです。次に、リーダーは a を返しますboost::variant<int, double, char, string, etc>
。
その後、コードは疑似均一な方法でバリアントと対話します。ヘルパー関数はブースト関数を使用してファンクターを呼び出し、 と対話しますvariant
。
つまり、次のようなものです。
typedef boost::variant<int, double> myVariant;
typedef std::function< myVariant( input_stream_type& ) > ValueParser;
ValueParser GetParser( std::string typename );
// ...
struct DoTypeSpecificWork
{
typedef void result_type;
void operator()( int ) { /* ... int code goes here */ }
void operator()( double ) { /* ... double code goes here */ }
};
ValueParser parser = GetParser( propType );
myVariant var = parser( input_stream );
boost::variant::apply_visitor( DoTypeSpecificWork(), var );
もう 1 つのオプションは、PropertyBase
型にとらわれない抽象インターフェイスを持つ基底クラスを持つことです。次にProperty<T>
、各型の抽象インターフェイスを実装する子クラス。これらの子クラスの作成Property<T>
は、直接 (パーサーにProperty
クラスを認識させる) または間接的に (つまり、 を取得しvariant
て適切な を生成しProperty<T>
、型の抽象化からコードの解析を切り離します) 行うことができます。
基本的に、複数の型を処理するには、型の消去、型の抽象化、およびテンプレート ベースのプログラミングのいずれかを決定する必要があります。それらにはすべて独自の利点があります。