OSDN Git Service

storage のインターフェイスを変更
authorSubaruG <subaru_g@users.sourceforge.jp>
Wed, 26 May 2010 03:28:57 +0000 (12:28 +0900)
committerSubaruG <subaru_g@users.sourceforge.jp>
Wed, 26 May 2010 03:28:57 +0000 (12:28 +0900)
gintenlib/storage.hpp
tests/ptr_fun.cc [new file with mode: 0644]
tests/storage.cc [new file with mode: 0644]

index a8825fd..2f0697d 100644 (file)
@@ -9,8 +9,33 @@
 
   宣言:
     template< typename T >
+    struct storage_of
+    {
+      typedef boost::aligned_storage< sizeof(T), boost::alignment_of<T>::value >::type type;
+    };
+    
+    template<typename T>
     struct storage
-      : boost::aligned_storage< sizeof(T), boost::alignment_of<T>::value > {};
+    {
+      // noncopyable にしてる都合上、必要
+      storage() {}
+      
+      // メタ関数
+      // 内部に格納されてるストレージの型
+      typedef typename storage_of<T>::type storage_type;
+      // メタ関数としても使えるように(互換性の為)。
+      typedef storage_type type;
+      
+      // アドレス取得
+      void* address();
+      void const* address() const;
+      
+     private:
+      // noncopyable
+      storage( storage const& );
+      storage& operator=( storage const& );
+      
+    };
 
   機能:
     T 型のクラスを格納できるだけのメモリ領域を確保したい場合、
 
 namespace gintenlib
 {
+  // storage_of<T>::type は T 型を格納できる POD 型
+  template<typename T>
+  struct storage_of
+  {
+    typedef typename boost::aligned_storage<
+      sizeof(T), boost::alignment_of<T>::value >::type type;
+  };
+  
   // T 型を収められるメモリ領域
+  // noncopyable で has_trivial_destructor
+  // boost::noncopyable を継承すると has_trivial_destructor にならないので
+  // 自前で代入とコピーを殺している
   template<typename T>
   struct storage
-    : boost::aligned_storage< sizeof(T), boost::alignment_of<T>::value > {};
+  {
+    // noncopyable にしてる都合上、必要
+    // = default 指定が欲しい。
+    storage() {}
+    
+    // メタ関数
+    // 内部に格納されてるストレージの型
+    typedef typename storage_of<T>::type storage_type;
+    // メタ関数としても使えるように(互換性の為)。
+    typedef storage_type type;
+    
+    // アドレス取得
+    void* address()             { return &data_; }
+    void const* address() const { return &data_; }
+    
+   private:
+    storage_type data_;
+    
+    // noncopyable
+    storage( storage const& );
+    storage& operator=( storage const& );
+    
+  };
   
 }   // namespace gintenlib
 
diff --git a/tests/ptr_fun.cc b/tests/ptr_fun.cc
new file mode 100644 (file)
index 0000000..4bcc66c
--- /dev/null
@@ -0,0 +1,71 @@
+#include "../gintenlib/ptr_fun.hpp"
+
+// boost の単体テストフレームワーク
+#include <boost/test/minimal.hpp>
+
+#include <boost/format.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+
+// テスト関数1
+// 任意の引数をカンマ区切りで文字列化する
+struct functor1
+  : private boost::noncopyable
+{
+  typedef std::string result_type;
+  
+  template<typename Arg1>
+  result_type operator()( const Arg1& arg1 )
+  {
+    return ( boost::format("%1%") % arg1 ).str();
+  }
+  template<typename Arg1, typename Arg2>
+  result_type operator()( const Arg1& arg1, const Arg2& arg2 )
+  {
+    return ( boost::format("%1%, %2%") % arg1 % arg2 ).str();
+  }
+};
+
+void test1()
+{
+  boost::shared_ptr<functor1> p = boost::make_shared<functor1>();
+  gintenlib::indirect_function< boost::shared_ptr<functor1> > f = gintenlib::ptr_fun(p);
+  
+  BOOST_CHECK( f.get_pointer() == p );
+  BOOST_CHECK( &f.get_function() == p.get() );
+  
+  BOOST_CHECK( f(1) == "1" );
+  BOOST_CHECK( f(1, "hoge") == "1, hoge" );
+}
+
+// テスト関数2(result_type なし)
+struct functor2
+  : private boost::noncopyable
+{
+  template<typename T>
+  T operator()( T x )
+  {
+    return ++x;
+  }
+};
+
+void test2()
+{
+  boost::shared_ptr<functor2> p = boost::make_shared<functor2>();
+  gintenlib::indirect_function< boost::shared_ptr<functor2>, int > f(p);
+  
+  BOOST_CHECK( f.get_pointer() == p );
+  BOOST_CHECK( &f.get_function() == p.get() );
+  
+  BOOST_CHECK( f(1) == 2 );
+}
+
+
+// テスト本体
+int test_main( int, char** )
+{
+  test1();
+  
+  return 0;
+}
diff --git a/tests/storage.cc b/tests/storage.cc
new file mode 100644 (file)
index 0000000..ccace1e
--- /dev/null
@@ -0,0 +1,52 @@
+// ヘッダ
+#include "../gintenlib/storage.hpp"
+
+// boost の単体テストフレームワーク
+#include <boost/test/minimal.hpp>
+
+#include <boost/type_traits.hpp>
+
+// テスト
+template<typename T>
+void test()
+{
+  // 型定義
+  typedef gintenlib::storage<T> storage_type;
+  typedef typename gintenlib::storage_of<T>::type raw_storage;
+  
+  // 型審査
+  BOOST_CHECK(( boost::is_same<typename storage_type::storage_type, raw_storage>::value ));
+  
+  // raw storage に対して
+  BOOST_CHECK(( sizeof( raw_storage ) == sizeof( T ) ));
+  BOOST_CHECK(( boost::is_pod<raw_storage>::value ));
+  
+  // storage に対して
+  BOOST_CHECK(( sizeof( storage_type ) == sizeof( T ) ));
+  BOOST_CHECK(( boost::has_trivial_destructor<storage_type>::value ));
+  
+  // アドレスのチェック
+  storage_type x;
+  BOOST_CHECK(( &x == x.address() ));
+}
+
+// 対象のクラス群
+struct empty_class {};
+
+struct virtual_class
+{
+  virtual ~virtual_class() {}
+  int member;
+};
+
+int test_main( int, char** )
+{
+  test<int>();
+  test<int const>();
+  test<int*>();
+  test<empty_class>();
+  test<virtual_class>();
+  
+  return 0;
+}
+