1 #ifndef GINTENLIB_INCLUDED_TO_SHARED_HPP_
2 #define GINTENLIB_INCLUDED_TO_SHARED_HPP_
6 <gintenlib/to_shared.hpp>
8 to_shared : 任意のポインタを shared_ptr に変換
13 shared_ptr<typename P::element_type> to_shared( const P& pt );
17 shared_ptr<T> to_shared( std::auto_ptr<T> p );
19 // trivial ですが shared_ptr からも
21 shared_ptr<T> to_shared( const shared_ptr<T>& p );
23 // これは intrusive_to_shared.hpp 内で定義
25 shared_ptr<T> to_shared( const boost::intrusive_ptr<T>& p );
27 // そのほか、銀天ライブラリの各スマートポインタに対し適切な to_shared が定義されている
30 各種スマートポインタを shared_ptr に変換します。
31 名前空間の自動紹介は行わない事になりました。代わりに using gintenlib::to_shared としてください。
35 #include "shared_ptr.hpp"
36 #include "intrusive_to_shared.hpp"
43 // std::auto_ptr version
46 inline shared_ptr<T> to_shared( std::auto_ptr<T> pt )
48 return shared_ptr<T>( pt.release() );
53 inline shared_ptr<T> to_shared( const shared_ptr<T>& pt )
60 // いわゆる「スマートポインタ」を保持するホルダ
61 // shared_ptr のコンストラクタの第二引数として渡す削除子として使える
62 template<typename Pointer>
63 struct to_shared_holder
65 typedef typename Pointer::element_type T;
66 typedef shared_ptr<T> shared_t;
71 to_shared_holder( const Pointer& pt_ )
75 static shared_t to_shared( const Pointer& pt_ )
77 // まず null pointer に対する最適化
79 if( !p ){ return shared_t(); }
82 return to_shared_holder(pt_).to_shared();
85 // これを実行すると、このオブジェクトは NULL に再設定される
88 using namespace std; // for assert()
91 // いったん仮の to_shared_holder を使って shared_ptr を作る
92 // ここで例外が投げられた場合、何も行われず抜けるので安全
93 shared_t temp( p, to_shared_holder() );
95 // 作られた shared_ptr の中身をいじる
96 // ポイントは、ここから仮の to_shared_holder が正しく設定されるまで、例外が投げられないこと
99 to_shared_holder* holder = boost::get_deleter< to_shared_holder >( temp );
100 // 作ったばかりの holder の型が不一致なわけない
101 assert( holder != 0 );
104 Pointer& pt_ = holder->pt;
105 // これが一番の山場。普通は swap は nothrow と信じる
108 // これで to_shared_pointer の中身が正しく設定された
111 assert( pt.get() == 0 && pt_.get() == p );
113 // 何故こんな面倒なことをしているかというと、
114 // 深いコピーを行うタイプのスマートポインタも問題なく保持できるようにしたいため。
115 // Pointer p2 = p1; の処理をした後に、 p1.get() == p2.get() である保証はないのです
117 // 完成した shared_ptr を返す
123 typedef void result_type;
124 void operator()( T* target ) throw ()
126 // 一応、正しいターゲットを削除しているかどうか、チェックする
128 assert( !pt.get() || pt.get() == target );
130 // これが呼ばれた後に shared_ptr の働きでこのオブジェクトが破棄され、
131 // 同時に pt の有効期限も切れるので、ここでは何もしない
135 // メンバとして Pointer を保持する
138 }; // to_shared_holder<Pointer>
142 inline shared_ptr<typename P::element_type> to_shared( const P& pt )
144 return to_shared_holder<P>::to_shared( pt );
147 } // namespace gintenlib
149 #endif // #ifndef GINTENLIB_INCLUDED_TO_SHARED_HPP_