OSDN Git Service

optional_storage に construct 関数を追加
authorSubaruG <subaru_g@users.sourceforge.jp>
Wed, 2 Jun 2010 14:53:57 +0000 (23:53 +0900)
committerSubaruG <subaru_g@users.sourceforge.jp>
Wed, 2 Jun 2010 14:53:57 +0000 (23:53 +0900)
gintenlib/optional_storage.hpp

index d32d80c..e9386f9 100644 (file)
   宣言:
     template<typename T>
     struct optional_storage
-      : private boost::noncopyable
     {
       typedef T element_type;
       typedef T value_type;
       
       // 構築/破棄
       optional_storage();
+      
+      template<typename Constructor>
+      explicit optional_storage( Constructor ctor );
+      
       ~optional_storage() throw ();
       
       // 中のデータを破棄する
       T& operator*();
       const T& operator*() const;
       
+     private:
+      optional_storage( optional_storage const& ) = delete;
+      void operator=( optional_storage const& ) = delete;
+      
     };  // optional_storage<T>
 
   機能:
     また、optional_storage<T> を使って構築済みオブジェクトを破棄する場合には、
     普通のデストラクタだけでなく、カスタムデストラクタを指定することもできます。
     そういう場合は明示的に destory を呼び出し、その引数にカスタムデストラクタを渡しましょう。
+    
+    (追記)
+    「指定したアドレスに対して関数を呼び出し、 set_initialized() する」
+    という construct 関数を新しく作りました。
+    こちらの方がより安全なので、今後はこちらを使いましょう。
+    set_initialized は近々削除予定です。
 
   使用例:
     // とりあえず領域だけ確保して
     // storage の有効期限が切れると、自動でデストラクトされるので安心
 
   補足:
-    ・placement new を呼んだら、即 set_initialized() を呼び出しましょう。
-    ・それさえ守れば、非常に安全性は高い筈です。
+    ・set_initialized ではなく construct を使いましょう。
 
 */
 
 #include <cassert>
-#include <boost/noncopyable.hpp>
 
 #include "destructor.hpp"
 #include "storage.hpp"
@@ -92,7 +103,6 @@ namespace gintenlib
   // ちょっと安全性の低い boost::optional
   template<typename T>
   struct optional_storage
-    : private boost::noncopyable
   {
     typedef       T     element_type;
     typedef       T       value_type;
@@ -105,6 +115,13 @@ namespace gintenlib
     optional_storage()
       : initialized_( false ) {}
     
+    template<typename Constructor>
+    explicit optional_storage( Constructor ctor )
+      : initialized_( false )
+    {
+      construct_( ctor );
+    }
+    
     ~optional_storage() throw ()
     {
       destory();
@@ -133,8 +150,20 @@ namespace gintenlib
     // 初期化ずみか否か
     bool initialized() const { return initialized_; }
     
-    // 初期化ずみマークをつける
-    void set_initialized() { initialized_ = true; }
+    // 初期化ずみマークをつける(非推奨)
+    void set_initialized() throw () { initialized_ = true; }
+    
+    // 関数を使って初期化する
+    // 初期化済みの場合は破棄してから初期化する
+    template<typename Constructor>
+    T* construct( Constructor ctor )
+    {
+      if( initialized() ){ destory(); }
+      
+      construct_();
+      
+      return static_cast<T*>( address() );
+    }
     
     
     // 構築済みなら、構築されたオブジェクトのアドレスを取得する
@@ -173,6 +202,16 @@ namespace gintenlib
     typedef storage<T> storage_type;
     storage_type storage_;
     
+    // 実装用関数
+    
+    // initialized_ によらずオブジェクトを構築する( unsafe ) 
+    template<typename Ctor>
+    void construct_( Ctor ctor )
+    {
+      ctor( address() );
+      initialized_ = true;
+    }
+    
   };  // optional_storage<T>
 
 }   // namespace gintenlib