1 #ifndef GINTENLIB_INCLUDED_OPTIONAL_STORAGE_HPP_
2 #define GINTENLIB_INCLUDED_OPTIONAL_STORAGE_HPP_
6 <gintenlib/optional_storage.hpp>
8 optional_storage : 後から初期化できるメモリ領域
12 struct optional_storage
13 : private boost::noncopyable
15 typedef T element_type;
20 ~optional_storage() throw ();
24 // カスタムデストラクタを使ってデータを破棄する
25 template<typename Destructor>
26 void destory( Destructor d );
30 const void* address() const;
33 bool initialized() const;
35 void set_initialized();
37 // 構築済みなら、構築されたオブジェクトのアドレスを取得する
42 const T* operator->() const;
45 const T& operator*() const;
47 }; // optional_storage<T>
50 予めメモリ領域を確保して云々、という、少し汚い処理を行いたい場合ってのが時々あります。
51 そういうときに、ある程度安心して処理を行えるようにする為のクラステンプレートです。
52 予めメモリ領域を確保して何かしらの処理をしてから、 address() で未初期化メモリのアドレスを取得。
53 そのアドレスに placement new でオブジェクトを作ったら set_initialized() を呼ぶ。
54 この一連の動作さえ行えば、後の破棄や何やらは、全て optional_storage<T> がやってくれます。
55 boost::optional<T> でも似たようなことは出来ますが、未初期化アドレスを直接得られません。
57 また、optional_storage<T> を使って構築済みオブジェクトを破棄する場合には、
58 普通のデストラクタだけでなく、カスタムデストラクタを指定することもできます。
59 そういう場合は明示的に destory を呼び出し、その引数にカスタムデストラクタを渡しましょう。
63 gintenlib::optional_storage<hoge> storage;
65 // storage が必要な何かしらの処理
68 ::new ( storage.address() ) hoge( args );
70 storage.set_initialized();
72 // めんどいので参照変数で以降のアクセスを簡略化
75 // 以降、 h は普通の hoge オブジェクトとして扱える
76 // storage の有効期限が切れると、自動でデストラクトされるので安心
79 ・placement new を呼んだら、即 set_initialized() を呼び出しましょう。
80 ・それさえ守れば、非常に安全性は高い筈です。
85 #include <boost/noncopyable.hpp>
87 #include "destructor.hpp"
88 #include "storage.hpp"
92 // ちょっと安全性の低い boost::optional
94 struct optional_storage
95 : private boost::noncopyable
97 typedef T element_type;
100 typedef const T* const_pointer;
101 typedef T& reference;
102 typedef const T& const_reference;
106 : initialized_( false ) {}
108 ~optional_storage() throw ()
116 destory( destructor() );
118 // カスタムデストラクタを使ってデータを破棄する
119 template<typename Destructor>
120 void destory( Destructor d )
125 initialized_ = false;
130 void* address(){ return storage_.address(); }
131 const void* address() const { return storage_.address(); }
134 bool initialized() const { return initialized_; }
137 void set_initialized() { initialized_ = true; }
140 // 構築済みなら、構築されたオブジェクトのアドレスを取得する
141 T* get(){ return initialized() ? static_cast<T*>( address() ) : 0; }
142 const T* get() const { return initialized() ? static_cast<const T*>( address() ) : 0; }
148 assert( initialized() );
151 const T* operator->() const
154 assert( initialized() );
161 assert( initialized() );
164 const T& operator*() const
167 assert( initialized() );
173 typedef storage<T> storage_type;
174 storage_type storage_;
176 }; // optional_storage<T>
178 } // namespace gintenlib
181 #endif // #ifndef GINTENLIB_INCLUDED_OPTIONAL_STORAGE_HPP_