« MySQL の ORDER BY を高速化 | メイン | C++ で自動型変換 »

2008年06月25日

なんとなくリフレクション in C++

 C++ はとてもいい言語なのですが、リフレクションがありません。昨夜、1年ぶりくらいに C++ でリフレクションしたい熱に感染したのですが、ちょっとググった範囲では良いものが見つからなかったので、作ってみました (単に作りたかっただけという説も)。こんな感じで使います。

#include "reflection.hpp"

struct Foo {
  int i;
  std::string s;
};

// リフレクション情報を定義
namespace reflection {
  template <> struct def<Foo> : public def_base<Foo> {
    def() {
      REFLECTION(i);
      REFLECTION(s);
    }
  };
};

  // リフレクションを通してデータを読み込み
  // 変数が見つからない場合は reflection::name_not_found_error が、
  // キャストできない場合は std::bad_cast 例外が送出されます
  int t = reflection::get<int>(f, "i");
  cout << "i=" << t << endl;
  
  // リフレクションを通してデータを書き込み
  reflection::set(f, "s", string("hello world"));
  
  // リフレクション情報を iterate して表示
  for (reflection::def<Foo>::const_iterator i =
         reflection::def<Foo>::map.begin();
       i != reflection::def<Foo>::map.end();
       ++i)
    cout << i->first << " = "
      << i->second->get<std::string>(f) <<endl;

 このリフレクションライブラリの特徴は、以下のようなものになります。

type-safe
代入、参照時に自動的に型変換を行います (型変換ができない場合は std::bad_cast 例外を送出します) 間違った型を代入しようとするとエラーを返します
構造体の型が不変
リフレクションを導入しても構造体が肥大化したり、型のバイナリ互換性が損なわれることはありません
実行時のオーバーヘッドがゼロ
リフレクションに必要な情報は main() 関数の実行前の段階ですべて初期化されます

 ライブラリと言っても 50 行程度のコードです。CodeRepos (/lang/cplusplus/reflection) に置いてあるので、よろしければご覧ください。

11:39追記: GCC 拡張である typeof を追放しました。

12:13追記: rev. 14582 だと、GCC 4.0, 4.3, VC8, 9 で動作するようです。

6月30日追記: C++ で自動型変換を行うコードを導入し、API を変更しました。

投稿者 kazuho : 2008年06月25日 08:34 このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

トラックバック

このエントリーのトラックバックURL:
http://labs.cybozu.co.jp/cgi-bin/mt-admin/mt-tbp.cgi/1943