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 // いわゆる「スマートポインタ」を保持するホルダ
50 // shared_ptr のコンストラクタの第二引数として渡す削除子として使える
51 template<typename Pointer>
52 struct to_shared_holder
54 typedef typename Pointer::element_type T;
55 typedef boost::shared_ptr<T> shared_t;
60 to_shared_holder( const Pointer& pt_ )
64 static shared_t to_shared( const Pointer& pt_ )
66 // まず null pointer に対する最適化
68 if( !p ){ return shared_t(); }
71 return to_shared_holder(pt_).to_shared();
74 // これを実行すると、このオブジェクトは NULL に再設定される
77 using namespace std; // for assert()
80 // いったん仮の to_shared_holder を使って shared_ptr を作る
81 // ここで例外が投げられた場合、何も行われず抜けるので安全
82 shared_t temp( p, to_shared_holder() );
84 // 作られた shared_ptr の中身をいじる
85 // ポイントは、ここから仮の to_shared_holder が正しく設定されるまで、例外が投げられないこと
88 to_shared_holder* holder = boost::get_deleter< to_shared_holder >( temp );
89 // 作ったばかりの holder の型が不一致なわけない
90 assert( holder != 0 );
93 Pointer& pt_ = holder->pt;
94 // これが一番の山場。普通は swap は nothrow と信じる
97 // これで to_shared_pointer の中身が正しく設定された
100 assert( pt.get() == 0 && pt_.get() == p );
102 // 何故こんな面倒なことをしているかというと、
103 // 深いコピーを行うタイプのスマートポインタも問題なく保持できるようにしたいため。
104 // Pointer p2 = p1; の処理をした後に、 p1.get() == p2.get() である保証はないのです
106 // 完成した shared_ptr を返す
112 typedef void result_type;
113 void operator()( T* target ) throw ()
115 // 一応、正しいターゲットを削除しているかどうか、チェックする
117 assert( !pt.get() || pt.get() == target );
119 // これが呼ばれた後に shared_ptr の働きでこのオブジェクトが破棄され、
120 // 同時に pt の有効期限も切れるので、ここでは何もしない
124 // メンバとして Pointer を保持するので
128 }; // to_shared_holder<Pointer>
132 inline boost::shared_ptr<typename P::element_type> to_shared( const P& pt )
134 return to_shared_holder<P>::to_shared( pt );
137 } // namespace gintenlib_to_shared_impl_
141 namespace gintenlib_to_shared_impl
145 inline boost::shared_ptr<typename P::element_type> to_shared_impl( const P& pt )
147 using namespace gintenlib_to_shared_impl_;
148 return to_shared( pt );
151 } // namespace gintenlib_to_shared_impl_
158 inline shared_ptr<typename P::element_type> to_shared( const P& pt )
160 return ::gintenlib_to_shared_impl::to_shared_impl( pt );
163 // std::auto_ptr version
165 inline shared_ptr<T> to_shared( std::auto_ptr<T> pt )
167 return shared_ptr<T>( pt.release() );
172 inline shared_ptr<T> to_shared( const shared_ptr<T>& pt )
177 } // namespace gintenlib
179 #endif // #ifndef GINTENLIB_INCLUDED_TO_SHARED_HPP_