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 汎用版は大部分のスマートポインタを変換してくれるはずですが、今のところ動作保障はできません。
32 動作保障の出来ない汎用版をわざわざ残している理由は、名前空間の自動照会を行えるようにです。
33 Boost.Swap ( http://www.boost.org/doc/libs/1_41_0/libs/utility/swap.html ) と同じように、
34 gintenlib::to_shared( pt ) と記述された場合、 gintenlib 名前空間だけでなく、
35 pt のクラスが定義されている名前空間からも to_shared 関数を探してくれます。
39 #include "shared_ptr.hpp"
40 #include "intrusive_to_shared.hpp"
47 namespace gintenlib_to_shared_impl_
49 using gintenlib::shared_ptr;
51 // いわゆる「スマートポインタ」を保持するホルダ
52 // shared_ptr のコンストラクタの第二引数として渡す削除子として使える
53 template<typename Pointer>
54 struct to_shared_holder
56 typedef typename Pointer::element_type T;
57 typedef shared_ptr<T> shared_t;
62 to_shared_holder( const Pointer& pt_ )
66 static shared_t to_shared( const Pointer& pt_ )
68 // まず null pointer に対する最適化
70 if( !p ){ return shared_t(); }
73 return to_shared_holder(pt_).to_shared();
76 // これを実行すると、このオブジェクトは NULL に再設定される
79 using namespace std; // for assert()
82 // いったん仮の to_shared_holder を使って shared_ptr を作る
83 // ここで例外が投げられた場合、何も行われず抜けるので安全
84 shared_t temp( p, to_shared_holder() );
86 // 作られた shared_ptr の中身をいじる
87 // ポイントは、ここから仮の to_shared_holder が正しく設定されるまで、例外が投げられないこと
90 to_shared_holder* holder = boost::get_deleter< to_shared_holder >( temp );
91 // 作ったばかりの holder の型が不一致なわけない
92 assert( holder != 0 );
95 Pointer& pt_ = holder->pt;
96 // これが一番の山場。普通は swap は nothrow と信じる
99 // これで to_shared_pointer の中身が正しく設定された
102 assert( pt.get() == 0 && pt_.get() == p );
104 // 何故こんな面倒なことをしているかというと、
105 // 深いコピーを行うタイプのスマートポインタも問題なく保持できるようにしたいため。
106 // Pointer p2 = p1; の処理をした後に、 p1.get() == p2.get() である保証はないのです
108 // 完成した shared_ptr を返す
114 typedef void result_type;
115 void operator()( T* target ) throw ()
117 // 一応、正しいターゲットを削除しているかどうか、チェックする
119 assert( !pt.get() || pt.get() == target );
121 // これが呼ばれた後に shared_ptr の働きでこのオブジェクトが破棄され、
122 // 同時に pt の有効期限も切れるので、ここでは何もしない
126 // メンバとして Pointer を保持するので
130 }; // to_shared_holder<Pointer>
134 inline shared_ptr<typename P::element_type> to_shared( const P& pt )
136 return to_shared_holder<P>::to_shared( pt );
139 } // namespace gintenlib_to_shared_impl_
143 namespace gintenlib_to_shared_impl
147 inline gintenlib::shared_ptr<typename P::element_type> to_shared_impl( const P& pt )
149 using namespace gintenlib_to_shared_impl_;
150 return to_shared( pt );
153 } // namespace gintenlib_to_shared_impl_
160 inline shared_ptr<typename P::element_type> to_shared( const P& pt )
162 return ::gintenlib_to_shared_impl::to_shared_impl( pt );
165 // std::auto_ptr version
168 inline shared_ptr<T> to_shared( std::auto_ptr<T> pt )
170 return shared_ptr<T>( pt.release() );
175 inline shared_ptr<T> to_shared( const shared_ptr<T>& pt )
180 } // namespace gintenlib
182 #endif // #ifndef GINTENLIB_INCLUDED_TO_SHARED_HPP_