smart_this(4)
次は4番。private な _this へアクセスするための権限が無いという問題。
これは、_this への参照を返すようなクラスを作成し、そこから取得するようにすればいい。
template< class T > class SmartThisPtrGetter; template< class T > class smart_this{ ... friend class SmartThisPtrGetter< T >; }; template< class T > SmartThisPtrGetter{ private: smart_ptr< T >& operator()( smart_this< T >& s ){ return s._this; } friend class smart_this< T >; };
こうすれば、
s._this SmartThisPtrGetter()( s )
この2行は同じ意味になる。
そして2番。_this に代入する時点で、_this が初期化されていないという問題。
これは、4番と同じ方法で、_this を初期化してやればいい。
class SmartPtrInitializer; template< class T > class smart_ptr{ ... friend class SmartPtrInitializer; }; class SmartPtrInitializer{ public: template< class T > void operator()( smart_ptr< T >& s ){ // 参照カウンタオブジェクトへのポインタ s._refObj = null; // T型オブジェクトへのポインタ s._obj = null; } };
コンストラクタで行う処理を、SmartPtrInitializer が代行する。
これで、_this のコンストラクタを呼び出したのと同じ状態になる。
で、今までの1〜4を組み合わせると、こうなる。
template< class T > class smart_this{ public: static smart_ptr< T > create(){ smart_ptr< T > s = smart_ptr< T >( (T*)malloc( sizeof( T ) ) ); SmartPtrInitializer()( SmartThisPtrGetter()( *s ) ); SmartThisPtrGetter()( *s ) = s; s.dec_ref(); ::new( (void*)s.get() ) T(); return s; } protected: smart_this(){} private: smart_ptr< T > _this; };
メモリを確保し、それをスマートポインタにセットして、_this を初期化して、_this に s をセットして、参照数を減らして、コンストラクタを呼んでる。
これでいけるはずだ。
class Hoge : public smart_this< Hoge >{ };
smart_ptr< Hoge > hoge = smart_this< Hoge >::create();
一応コンパイルは通るはずだ。
しかし、hoge にセットされた時点で、_this の中身が null になっている。なぜだろう?
続く。