7

メンバーに動的にアクセスできるようにする構造体(または同様のもの)をC++で使用したいと思います。メンバー名を文字列として受け取り、ある種のバリアント型(eg boost::variant)を返す汎用のゲッターとセッターが必要です。

boost::fusion::map各メンバーの名前を表す文字列を追加し、文字列とgetterまたはsetter関数の間にSTLマップを作成することで、を使用して実装できると考えていました。車輪の再発明をしたくないので、似たようなものがすでに存在することを望んでいました。

どう思いますか?私のアイデアはうまくいくでしょうか?私の目標を達成するための他の方法を知っていますか?

4

3 に答える 3

7

融合はアプローチですが、ペイロードが...でstd::mapある、によってキー設定されたキーに「フィールド」を格納してみませんか。std::stringboost::variant

すなわち

struct generic
{
std::map<std::string, boost::variant<foo, bar, bob, int, double> > _impl;
};

次に、ゲッター/セッターでキーを検索するだけです...

一体、をラップするvariantと、optionalオプションのフィールドを持つことができます!

より複雑な例:

class foo
{
public:
  typedef boost::variant<int, double, float, string> f_t;
  typedef boost::optional<f_t&> return_value;
  typedef map<string, return_value> ref_map_t;

  foo() : f1(int()), f2(double()), f3(float()), f4(string()), f5(int()) 
  {
    // save the references..
    _refs["f1"] = return_value(f1);
    _refs["f2"] = return_value(f2);
    _refs["f3"] = return_value(f3);
    _refs["f4"] = return_value(f4);
    _refs["f5"] = return_value(f5);
  }

  int getf1() const { return boost::get<int>(f1); }
  double getf2() const { return boost::get<double>(f2); }
  float getf3() const { return boost::get<float>(f3); }
  string const& getf4() const { return boost::get<string>(f4); }
  int getf5() const { return boost::get<int>(f5); }

  // and setters..
  void setf1(int v) { f1 = v; }
  void setf2(double v) { f2 = v; }
  void setf3(float v) { f3 = v; }
  void setf4(std::string const& v) { f4 = v; }
  void setf5(int v) { f5 = v; }

  // key based
  return_value get(string const& key)
  {
    ref_map_t::iterator it = _refs.find(key);
    if (it != _refs.end())
      return it->second;
    return return_value();
  }

  template <typename VT>
  void set(string const& key, VT const& v)
  {
    ref_map_t::iterator it = _refs.find(key);
    if (it != _refs.end())
      *(it->second) = v;
  }

private:
  f_t f1;
  f_t f2;
  f_t f3;
  f_t f4;
  f_t f5;

  ref_map_t _refs;
};

int main(void)
{
  foo fancy;
  fancy.setf1(1);
  cout << "f1: " << fancy.getf1() << endl;

  fancy.set("f1", 10);
  cout << "f1: " << fancy.getf1() << endl;

  return 0;
}
于 2010-12-02T12:58:43.017 に答える
1

あなたはC++でのReflectionを求めていますが、これは利用できないと思います。あなたはあなた自身の何かを考え出さなければならないでしょう。

于 2010-12-02T12:53:11.417 に答える
1

私がこれのためにしたことは、私のメンバーとある種の説明を含むboost::consのようなタイプリストでした。次に、「連鎖」関数呼び出しによってメンバーを「メタ情報」データ構造に連続して追加することにより、このマッピングを構築します。全体は、boost.pythonでクラスを定義するのと非常によく似ています。実際にboost::consを使用する場合は、boost.fusionのシーケンスとしても機能するため、データを適切に反復処理できます。代わりにboost.fusionマップを使用して、実行時にlog(n)アクセス時間を取得できるかもしれませんが、可変個引数テンプレートが利用可能になるまで、そのサイズは制限されているようです。

于 2010-12-02T14:10:32.937 に答える