From 0e060b77578dd7d8b9a17031133cc6a163b38289 Mon Sep 17 00:00:00 2001 From: SubaruG Date: Thu, 1 Apr 2010 02:13:59 +0900 Subject: [PATCH] =?utf8?q?clonable=5Fptr,=20to=5Fshared=20=E3=81=AE=20oper?= =?utf8?q?ator()=20=E3=82=92=E5=A4=89=E6=9B=B4=EF=BC=88=20weak=5Fptr=20?= =?utf8?q?=E3=81=8C=E5=AD=98=E5=9C=A8=E3=81=97=E3=81=9F=E5=A0=B4=E5=90=88?= =?utf8?q?=E3=81=AB=E5=8D=B3=E5=BA=A7=E3=81=AB=E8=A7=A3=E6=94=BE=E3=81=95?= =?utf8?q?=E3=82=8C=E3=81=AA=E3=81=84=E3=83=90=E3=82=B0=E3=82=92=E4=BF=AE?= =?utf8?q?=E6=AD=A3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- gintenlib/clonable_ptr.hpp | 8 ++++- gintenlib/to_shared.hpp | 28 +++++++++++------- tests/to_shared.cc | 74 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 94 insertions(+), 16 deletions(-) diff --git a/gintenlib/clonable_ptr.hpp b/gintenlib/clonable_ptr.hpp index 54116d7..d98a1c5 100644 --- a/gintenlib/clonable_ptr.hpp +++ b/gintenlib/clonable_ptr.hpp @@ -339,7 +339,13 @@ namespace gintenlib // デストラクタで適宜やってくれるので // operator() では何も行わない - void operator()( T* ) const {} + // と思いきや、 weak_ptr を使った場合はデストラクタ呼び出しまで + // 時間がかかるので、きっちり operator() で削除しなきゃダメ + void operator()( T* ) + { + // count を破棄する + clonable_count().swap( count ); + } private: clonable_count count; diff --git a/gintenlib/to_shared.hpp b/gintenlib/to_shared.hpp index b3a54e5..dda5087 100644 --- a/gintenlib/to_shared.hpp +++ b/gintenlib/to_shared.hpp @@ -28,7 +28,15 @@ 機能: 各種スマートポインタを shared_ptr に変換します。 - 名前空間の自動紹介は行わない事になりました。代わりに using gintenlib::to_shared としてください。 + 名前空間の自動照会は行わない事になりました。代わりに using gintenlib::to_shared としてください。 + + 要求: + 一般の P に対する要求は、以下の通り: + element_type を持つ。 + P::element_type get() const; メンバ関数を持つ。 + デフォルトコンストラクタを呼び出せる。例外を投げない。 + copy constructable である。その際、内部に格納されているポインタのアドレスが変化してもいい。 + swap( p1, p2 ) が例外を投げない。 */ @@ -85,7 +93,7 @@ namespace gintenlib // これを実行すると、このオブジェクトは NULL に再設定される shared_t to_shared() { - using namespace std; // for assert() + using namespace std; // for assert, swap T* p = pt.get(); // いったん仮の to_shared_holder を使って shared_ptr を作る @@ -97,7 +105,7 @@ namespace gintenlib // これは例外を投げない to_shared_holder* holder = boost::get_deleter< to_shared_holder >( temp ); - // 作ったばかりの holder の型が不一致なわけない + // 作ったばかりの holder の型が不一致なわけないが、一応チェック assert( holder != 0 ); // これも大丈夫 @@ -118,17 +126,15 @@ namespace gintenlib return temp; } - // 一番大事なはずの削除関数・・・だが - // やってることは特に無し + // 削除関数 typedef void result_type; - void operator()( T* target ) throw () + void operator()( T* ) { - // 一応、正しいターゲットを削除しているかどうか、チェックする - using namespace std; - assert( !pt.get() || pt.get() == target ); + // ポインタを破棄する + Pointer p0; - // これが呼ばれた後に shared_ptr の働きでこのオブジェクトが破棄され、 - // 同時に pt の有効期限も切れるので、ここでは何もしない + using namespace std; + swap( pt, p0 ); } private: diff --git a/tests/to_shared.cc b/tests/to_shared.cc index 660ea07..346e33a 100644 --- a/tests/to_shared.cc +++ b/tests/to_shared.cc @@ -26,6 +26,7 @@ struct hoge } hoge( const hoge& ) + : gintenlib::reference_counter() { cout << "hoge::hoge( const hoge& );\n"; } @@ -38,11 +39,60 @@ struct hoge }; // 適当な俺俺スマートポインタを作る -template -struct oreore_ptr - : gintenlib::pointer_facade< oreore_ptr, T > + +// 深いコピーを行っても格納出来ることを示すため、 +// 簡易版 deep_ptr で試してみる( gintenlib::deep_ptr は専用の to_shared が呼ばれるので) +#include +#include +template< typename T > +struct my_deep_ptr + : gintenlib::pointer_facade< my_deep_ptr, T > { -}; + // デフォルトコンストラクタ + my_deep_ptr() : p() {} + + // ポインタから作るコンストラクタ + explicit my_deep_ptr( T* p_ ) + : p( p_ ) {} + + // コピーコンストラクタ + my_deep_ptr( const my_deep_ptr& src ) + : p( src.p ? new T( *src.p ) : 0 ) {} + + // デストラクタ + // scoped_ptr() のおかげで何もしなくていい + // ~my_deep_ptr(){} + + // nothrow swap ( for operator= ) + void swap( my_deep_ptr& other ) + { + p.swap( other.p ); + } + friend void swap( my_deep_ptr& one, my_deep_ptr& another ) + { + one.swap( another ); + } + + // 代入演算は copy して swap + my_deep_ptr& operator=( const my_deep_ptr& src ) + { + my_deep_ptr( src ).swap( *this ); + return *this; + } + + void reset( T* p_ = 0 ) + { + my_deep_ptr( p_ ).swap( *this ); + } + + // get pointer + // これと pointer_facade からいろいろと自動生成 + T* get() const { return p.get(); } + + private: + boost::scoped_ptr p; + +}; // class my_deep_ptr // 汎用版はまだテストしない。 intrusive, auto をチェック int main() @@ -86,6 +136,22 @@ int main() cout << "scope out: p1, p2\n"; } + // ユーザ定義クラス + { + my_deep_ptr p1; + PRINT_AND_EXECUTE( p1.reset( new hoge() ) ); + PRINT_EXPR( p1.get() ); + boost::shared_ptr p2; + PRINT_AND_EXECUTE( p2 = gintenlib::to_shared(p1) ); + + // ちゃんと深いコピーできているかチェック + PRINT_EXPR( p1.get() ); + PRINT_EXPR( p2.get() ); + + // 抜けます + cout << "scope out: p1, p2\n"; + } + return 0; } -- 2.11.0