OSDN Git Service

日本語コミットメッセージのテスト
[gintenlib/gintenlib.git] / gintenlib / optional_storage.hpp
1 #ifndef GINTENLIB_INCLUDED_OPTIONAL_STORAGE_HPP_
2 #define GINTENLIB_INCLUDED_OPTIONAL_STORAGE_HPP_
3
4 /*
5
6       <gintenlib/optional_storage.hpp>
7
8   optional_storage : 後から初期化できるメモリ領域
9
10   宣言:
11     template<typename T>
12     struct optional_storage
13       : private boost::noncopyable
14     {
15       typedef T element_type;
16       typedef T value_type;
17       
18       // 構築/破棄
19       optional_storage();
20       ~optional_storage() throw ();
21       
22       // 中のデータを破棄する
23       void destory();
24       // カスタムデストラクタを使ってデータを破棄する
25       template<typename Destructor>
26       void destory( Destructor d );
27       
28       // storage の生アドレスを得る
29       void* address();
30       const void* address() const;
31       
32       // 初期化ずみか否か
33       bool initialized() const;
34       // 初期化ずみマークをつける
35       void set_initialized();
36       
37       // 構築済みなら、構築されたオブジェクトのアドレスを取得する
38       T* get();
39       const T* get() const;
40       // アロー演算
41       T* operator->();
42       const T* operator->() const;
43       // 参照外し
44       T& operator*();
45       const T& operator*() const;
46       
47     };  // optional_storage<T>
48
49   機能:
50     予めメモリ領域を確保して云々、という、少し汚い処理を行いたい場合ってのが時々あります。
51     そういうときに、ある程度安心して処理を行えるようにする為のクラステンプレートです。
52     予めメモリ領域を確保して何かしらの処理をしてから、 address() で未初期化メモリのアドレスを取得。
53     そのアドレスに placement new でオブジェクトを作ったら set_initialized() を呼ぶ。
54     この一連の動作さえ行えば、後の破棄や何やらは、全て optional_storage<T> がやってくれます。
55     boost::optional<T> でも似たようなことは出来ますが、未初期化アドレスを直接得られません。
56     
57     また、optional_storage<T> を使って構築済みオブジェクトを破棄する場合には、
58     普通のデストラクタだけでなく、カスタムデストラクタを指定することもできます。
59     そういう場合は明示的に destory を呼び出し、その引数にカスタムデストラクタを渡しましょう。
60
61   使用例:
62     // とりあえず領域だけ確保して
63     gintenlib::optional_storage<hoge> storage;
64     
65     // storage が必要な何かしらの処理
66     
67     // placement new で構築
68     ::new ( storage.address() ) hoge( args );
69     // 構築したよマークをつける
70     storage.set_initialized();
71     
72     // めんどいので参照変数で以降のアクセスを簡略化
73     hoge& h = *storage;
74     
75     // 以降、 h は普通の hoge オブジェクトとして扱える
76     // storage の有効期限が切れると、自動でデストラクトされるので安心
77
78   補足:
79     ・placement new を呼んだら、即 set_initialized() を呼び出しましょう。
80     ・それさえ守れば、非常に安全性は高い筈です。
81
82 */
83
84 #include <cassert>
85 #include <boost/noncopyable.hpp>
86
87 #include "destructor.hpp"
88 #include "storage.hpp"
89
90 namespace gintenlib
91 {
92   // ちょっと安全性の低い boost::optional
93   template<typename T>
94   struct optional_storage
95     : private boost::noncopyable
96   {
97     typedef       T     element_type;
98     typedef       T       value_type;
99     typedef       T*         pointer;
100     typedef const T*   const_pointer;
101     typedef       T&       reference;
102     typedef const T& const_reference;
103     
104     // 構築/破棄
105     optional_storage()
106       : initialized_( false ) {}
107     
108     ~optional_storage() throw ()
109     {
110       destory();
111     }
112     
113     // 中のデータを破棄する
114     void destory()
115     {
116       destory( destructor() );
117     }
118     // カスタムデストラクタを使ってデータを破棄する
119     template<typename Destructor>
120     void destory( Destructor d )
121     {
122       if( initialized_ )
123       {
124         d( get() );
125         initialized_ = false;
126       }
127     }
128     
129     // storage の生アドレスを得る
130     void* address(){ return storage_.address(); }
131     const void* address() const { return storage_.address(); }
132     
133     // 初期化ずみか否か
134     bool initialized() const { return initialized_; }
135     
136     // 初期化ずみマークをつける
137     void set_initialized() { initialized_ = true; }
138     
139     
140     // 構築済みなら、構築されたオブジェクトのアドレスを取得する
141     T* get(){ return initialized() ? static_cast<T*>( address() ) : 0; }
142     const T* get() const { return initialized() ? static_cast<const T*>( address() ) : 0; }
143     
144     // アロー演算
145     T* operator->()
146     {
147       using namespace std;
148       assert( initialized() );
149       return get();
150     }
151     const T* operator->() const
152     {
153       using namespace std;
154       assert( initialized() );
155       return get();
156     }
157     // 参照外し
158     T& operator*()
159     {
160       using namespace std;
161       assert( initialized() );
162       return *get();
163     }
164     const T& operator*() const
165     {
166       using namespace std;
167       assert( initialized() );
168       return *get();
169     }
170     
171    private:
172     bool initialized_;
173     typedef storage<T> storage_type;
174     storage_type storage_;
175     
176   };  // optional_storage<T>
177
178 }   // namespace gintenlib
179
180
181 #endif  // #ifndef GINTENLIB_INCLUDED_OPTIONAL_STORAGE_HPP_