2010年7月10日土曜日

リフレクション実装を改善してみた。

7月8日のポストで提示したサンプルコードには、ひどい仕様があったため
新しいバージョンのソースをアップします(7月8日の記事へジャンプする)

[サンプルソースをダウンロード]
*このソースを利用した事による一切の現象について責任を負いかねます。

具体的な問題を解説するとクラス要素をリフレクトする際に間違った型で
受けても無理矢理キャストが成立してしまい、結果非常にまずい動作を引き
起こしてしまう可能性がありました。

この対処のために動的な型チェックを行うようにしました。
型チェックはRTTIを使わず独自に実装しています。

class MyObj : public Object
{
  CLASS_DECL( MyObj );
  //...
};

Objectクラスを継承しクラス宣言にマクロ CLASS_DECL(<クラス名>)
配置すれば型チェック機能が有効になります。もちろん、Refelectable
Objectを継承しています。

2010年7月8日木曜日

リフレクションを実装してみた。

リフレクションをC++で実装してみました。
ただし、名前によるメンバ変数へのアクセスを提供するのみで
本来リフレクションという言葉で定義される全てを満しません。

[サンプルソースのダウンロード]
サンプルソースを更新しました。内容と新しいソースについては
7月10日の記事を確認してください。その記事へジャンプ

ZIPアーカイブにはVisual Studio 2008のプロジェクトファイルと
ソースコードが含まれています。

サンプルはBoost ver.1.43.0を利用しますのでメイクする際には
Boostを落として[ツール >> オプション]あたりでインクルードパスを
通しておいて下さい。

なお、サンプルによって生じたいかなる現象についても責任を
負いかねますのでご了承下さい(単純なソースですけどね)。

以下利用方法を解説します。

まずReflectableクラスを継承したクラスを宣言します。
名前アクセスを行いたいメンバ変数(リフレクト要素)を追加していきます。
class MyObj : public Reflectable
{
public :
  Sample() { registerElements(); }
  ~Sample() {}

private :
  void registerElements();// 解説後述

private :
  Element<int> m_number;// 整数値要素
  Element<Child> m_obj;// 静的配置クラス要素
  Element<Child*> m_pObj;// クラスポインタ要素
};
要素としてクラスを格納する際はそのクラス(この場合はChild)も
Reflectableを継承していなければなりません。

宣言された要素はコンストラクトのタイミングで要素を登録します。
登録はマクロ経由の関数コールで行います。
void Sample::registerElements()
{
  // 以下のマクロは
  // Reflectable::registerElementをコールする
  REGISTER_ELEM( m_number );
  REGISTER_ELEM( m_obj );
  REGISTER_ELEM( m_pObj );
}
あとは次のような記述で名前アクセスが可能です。
Sample sample;
int& n = sample.reflect( "m_number" );// 参照の取得