OSDN Git Service

memberwise_swap を追加
[gintenlib/gintenlib.git] / gintenlib / intrusive_to_shared.hpp
1 #ifndef GINTENLIB_INCLUDED_INTRUSIVE_TO_SHARED_HPP_
2 #define GINTENLIB_INCLUDED_INTRUSIVE_TO_SHARED_HPP_
3
4 /*
5
6       <gintenlib/intrusive_to_shared.hpp>
7
8   intrusive_to_shared : intrusive_ptr を shared_ptr に変換
9
10   宣言:
11     template<typename T>
12     shared_ptr<T> intrusive_to_shared( const boost::intrusive_ptr<T>& p );
13     
14     template<typename T>
15     shared_ptr<T> intrusive_to_shared( T* p, bool add_ref = true );
16     
17     template<typename T>
18     shared_ptr<T> to_shared( const boost::intrusive_ptr<T>& p );
19
20   機能:
21     intrusive_ptr を shared_ptr に変換します。
22     intrusive_ptr_add_ref や intrusive_ptr_release のコストが高い場合や、
23     あるいは単に shared_ptr としての値が欲しい場合などに使えます。
24     なおヘッダ名は intrusive_to_shared ですが、省略名である to_shared でも使えます。
25     むしろ <gintenlib/to_shared.hpp> との兼ね合いから、こちらを使うことを推奨しています。
26
27 */
28
29 #include "shared_ptr.hpp"
30
31 #include <cassert>
32 #include <boost/intrusive_ptr.hpp>
33
34 namespace gintenlib
35 {
36   // deleter として使う補助ファンクタ
37   struct intrusive_ptr_releaser
38   {
39     typedef void result_type;
40     
41     // ptr をリリースする
42     template<typename T>
43     void operator()( T* ptr ) const
44     {
45       using namespace std;
46       using namespace boost;  // for intrusive_ptr_release
47       
48       assert( ptr != 0 );
49       intrusive_ptr_release(ptr);
50     }
51   
52   };  // class intrusive_ptr_releaser
53   
54   // 本体
55   // intrusive_ptr 版
56   template<typename T>
57   inline shared_ptr<T> intrusive_to_shared( const boost::intrusive_ptr<T>& p )
58   {
59     // 生ポインタ版に単純に転送するだけ
60     return intrusive_to_shared( p.get(), true );
61   }
62   // 生ポインタ版
63   template<typename T>
64   inline shared_ptr<T> intrusive_to_shared( T* p, bool add_ref = true )
65   {
66     using namespace boost;  // for intrusive_ptr_add_ref
67     
68     if(p)
69     {
70       // 参照カウント増やしてから shared_ptr に突っ込む
71       // boost::shared_ptr はコンストラクタで例外を投げうるが、その場合でも
72       // ちゃんと削除ファンクタを呼び出してくれるので問題ない
73       if( add_ref ){ intrusive_ptr_add_ref( p ); }
74       return shared_ptr<T>( p, intrusive_ptr_releaser() );
75     }
76     
77     // NULL の場合は空の shared_ptr を返す
78     return shared_ptr<T>();
79   }
80   
81   // 省略名称
82   // 他の場所で to_shared の一般的なスマートポインタに対する定義もあるが、
83   // intrusive_ptr に関してはこちらの方が効率が良い。
84   template<typename T>
85   inline shared_ptr<T> to_shared( const boost::intrusive_ptr<T>& p )
86   {
87     // 単純に転送するだけ
88     return intrusive_to_shared( p );
89   }
90
91 }   // namespace gintenlib
92
93 #endif  // #ifndef GINTENLIB_INCLUDED_INTRUSIVE_TO_SHARED_HPP_