0

C++ テンプレート クラスを作成しましたが、クラスをインスタンス化する型がありません。型は文字列形式で格納されます。だから私はこのようなことをしなければなりません:

if ( propType == "char") {
   Property<char> pChar = ...
} else if ( propType == "int") {
   Property<int> pChar = ...
} if ( propType == "double") {
   Property<double> pChar = ...
} 

私はこのif-else-ループが好きではありません。これを回避する方法、またはそのような問題に対する他の解決策はありますか?

4

2 に答える 2

4

多くの方法がありますが、特定のケースでどのように使用するかを知らずに、適切なものを選択することは不可能です.

デモンストレーションとして:

  • Property<T>すべてのクラスがから継承すると仮定しましょうPropertyBase
  • 文字列から型を解析して初期化するとします。

次に、いくつかのコードを示します。

using PropertyPtr = std::unique_ptr<PropertyBase>;
using Parser = std::function<PropertyPtr(std::string const&, std::string const&)>;

template <typename T>
PropertyPtr parse(std::string const& type, std::string const& value) {
    T v = boost::lexical_cast<T>(value);
    return PropertyPtr(new Property<T>(std::move(v)));
}

std::map<std::string, Parser> const parsers = {
    std::make_pair("char", parse<char>),
    std::make_pair("int", parse<int>),
    std::make_pair("double", parse<double>)
};

void dummy(std::string const& type, std::string const& value) {
    auto const it = parsers.find(type);
    assert(it == parsers.end() && "No parser");

    auto const& parser = it->second;
    PropertyPtr property = parser(type, value);

    // do something with property
}

お役に立てれば。

于 2012-11-10T17:46:47.043 に答える
1

ここでは、いくつかの考慮事項があります。

ディスクからファイルを解析し、ディスク上のタイプに基づいてオブジェクトを作成するとします。これらのオブジェクトは、ほとんど区別できない方法で処理します。使用しているタイプの有限リストがあります。

これに使用する答えは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>、型の抽象化からコードの解析を切り離します) 行うことができます。

基本的に、複数の型を処理するには、型の消去、型の抽象化、およびテンプレート ベースのプログラミングのいずれかを決定する必要があります。それらにはすべて独自の利点があります。

于 2012-11-10T18:22:46.193 に答える