OSDN Git Service

今日の作業はここまで
authorSubaruG <subaru_g@users.sourceforge.jp>
Thu, 21 Jan 2010 18:40:37 +0000 (03:40 +0900)
committerSubaruG <subaru_g@users.sourceforge.jp>
Thu, 21 Jan 2010 18:40:37 +0000 (03:40 +0900)
gintenlib/bool_comparable.hpp
gintenlib/clonable_ptr.hpp
gintenlib/to_string.hpp
tests/clonable_ptr.cc
tests/to_string.cc [new file with mode: 0644]

index ee7a6d1..e975be1 100644 (file)
   #include <boost/type_traits/is_same.hpp>
 #endif
 
+#include "cast.hpp" // for gintenlib::cast
+
 namespace gintenlib
 {
   // ヘルパ構造体
@@ -229,25 +231,25 @@ namespace gintenlib
     friend typename enable_if<boost::is_same<U, bool>, bool>::type
       operator==( const Derived& lhs, U rhs )
     {
-      return static_cast<bool>(lhs) == rhs;
+      return cast<bool>(lhs) == rhs;
     }
     template<typename U>
     friend typename enable_if<boost::is_same<U, bool>, bool>::type
       operator==( U lhs, const Derived& rhs )
     {
-      return lhs == static_cast<bool>(rhs);
+      return lhs == cast<bool>(rhs);
     }
     template<typename U>
     friend typename enable_if<boost::is_same<U, bool>, bool>::type
       operator!=( const Derived& lhs, U rhs )
     {
-      return static_cast<bool>(lhs) != rhs;
+      return cast<bool>(lhs) != rhs;
     }
     template<typename U>
     friend typename enable_if<boost::is_same<U, bool>, bool>::type
       operator!=( U lhs, const Derived& rhs )
     {
-      return lhs != static_cast<bool>(rhs);
+      return lhs != cast<bool>(rhs);
     }
     
   #else   // #ifndef GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF
@@ -256,19 +258,19 @@ namespace gintenlib
     // この場合、 x == 1 のような表現が通ってしまうが仕方ないね
     friend bool operator==( const Derived& lhs, bool rhs )
     {
-      return static_cast<bool>(lhs) == rhs;
+      return cast<bool>(lhs) == rhs;
     }
     friend bool operator==( bool lhs, const Derived& rhs )
     {
-      return lhs == static_cast<bool>(rhs);
+      return lhs == cast<bool>(rhs);
     }
     friend bool operator!=( const Derived& lhs, bool rhs )
     {
-      return static_cast<bool>(lhs) != rhs;
+      return cast<bool>(lhs) != rhs;
     }
     friend bool operator!=( bool lhs, const Derived& rhs )
     {
-      return lhs != static_cast<bool>(rhs);
+      return lhs != cast<bool>(rhs);
     }
     
   #endif  // #ifndef GINTENLIB_BOOL_COMPARABLE_NO_ENABLE_IF
index 3bf7ed4..7dca567 100644 (file)
 
 #include "pointer_facade.hpp"
 #include "reference_counter.hpp"
+#include "shared_ptr.hpp" // for to_shared
 
 #include <boost/intrusive_ptr.hpp>
-#include <boost/shared_ptr.hpp>
 #include <boost/type_traits/remove_const.hpp>
 #include <utility>  // for std::pair
 
@@ -346,11 +346,11 @@ namespace gintenlib
       
     };
     // shared_ptr に変換
-    boost::shared_ptr<T> to_shared() const
+    shared_ptr<T> to_shared() const
     {
-      return p ? boost::shared_ptr<T>( p, to_shared_helper(count) ) : boost::shared_ptr<T>();
+      return p ? shared_ptr<T>( p, to_shared_helper(count) ) : shared_ptr<T>();
     }
-    friend boost::shared_ptr<T> to_shared( const this_type& target )
+    friend shared_ptr<T> to_shared( const this_type& target )
     {
       return target.to_shared();
     }
@@ -361,11 +361,13 @@ namespace gintenlib
     
     template<typename U> friend class clonable_ptr;
     
+    // 裏技コンストラクタ
     clonable_ptr( const clonable_count& count_, T* p_ )
       : p(p_), count(count_) {}
     explicit clonable_ptr( const clonable_count::cloned_type& pair )
       : p( static_cast<T*>( pair.second ) ), count( pair.first ) {}
     
+    // pointer casts
     template<typename T1, typename T2>
     friend clonable_ptr<T1> static_pointer_cast( const clonable_ptr<T2>& src );
     template<typename T1, typename T2>
@@ -375,7 +377,7 @@ namespace gintenlib
     
   };  // clonable_ptr<T>
   
-  // pointer casts
+  // xxx_pointer_cast
   template<typename T, typename S>
   inline clonable_ptr<T> static_pointer_cast( const clonable_ptr<S>& src )
   {
index 7c25e79..8f45f64 100644 (file)
@@ -8,14 +8,18 @@
   to_string : 文字列変換
   
   宣言:
-    template<typename T>
-    std::string to_str( const T& src );
+    // stringstream によって std::string に変換する
     template<typename T>
     std::string to_string( const T& src );
+    
+    // 同じ。ただしより適切な to_string がある場合にはそちらを呼ぶ
+    template<typename T>
+    std::string to_str( const T& src );
 
   機能:
     文字列に変換する。
-    lexical_castより(たぶん)高速
+    boost::lexical_castより(たぶん)高速
+    std::to_string ができるまでの繋ぎ
 
 */
 
@@ -33,14 +37,13 @@ namespace gintenlib
     
     return oss.str();
   }
+  
+  // ADL によって to_string を呼び出す
+  // いわゆる boost::swap 的なもの
   template<typename T>
   inline std::string to_str( const T& src )
   {
-    // さらに名前を短縮する
-    std::ostringstream oss;
-    oss << src;
-    
-    return oss.str();
+    return to_string( src );
   }
 
 }   // namespace gintenlib
index 0359331..cb91e33 100644 (file)
@@ -3,16 +3,58 @@
 // boost の単体テストフレームワーク
 #include <boost/test/minimal.hpp>
 
+// ポインタ自身のテスト
+template<typename T>
+void test_pointer( const gintenlib::clonable_ptr<T>& p )
+{
+  // まず get() と get_pointer() のチェック
+  BOOST_CHECK( p.get() == get_pointer(p) );
+  
+  // NULL でない場合
+  if( p )
+  {
+    // operator! のチェック
+    BOOST_CHECK( !p == false );
+    
+    // operator*, operator-> のチェック
+    BOOST_CHECK( p.get() == &*p );
+    BOOST_CHECK( p.get() == p.operator->() );
+    
+    // use_count と unique のチェック
+    BOOST_CHECK( ( p.use_count() == 1 ) == p.unique() );
+  }
+  else
+  {
+    // get() は NULLか
+    BOOST_CHECK( p.get() == 0 );
+    // operator! のチェック
+    BOOST_CHECK( !p );
+    
+    // use_count は 0 か?
+    BOOST_CHECK( p.use_count() == 0 );
+    // !unique() か?
+    BOOST_CHECK( !p.unique() );
+    
+  }
+}
+
+// 基本的なチェック
 template<typename T>
 void test1( const gintenlib::clonable_ptr<T>& p0 )
 {
-  typedef gintenlib::clonable_ptr<T> ptr_type;
+  using gintenlib::clonable_ptr;
+  
+  // まず p0 をテスト
+  test_pointer( p0 );
   
   // デフォルト構築
   {
-    ptr_type p1;
+    clonable_ptr<T> p1;
     // NULL にセットされているか?
-    BOOST_CHECK( p1.get() == 0 );
+    BOOST_CHECK( !p1 );
+    
+    // 他、もろもろはおk?
+    test_pointer( p1 );
   }
   
   // コピー
@@ -21,7 +63,9 @@ void test1( const gintenlib::clonable_ptr<T>& p0 )
     int count = p0.use_count();
     
     // コピーする
-    ptr_type p1 = p0;
+    clonable_ptr<T> p1 = p0;
+    // とりあえずテスト
+    test_pointer( p1 );
     // アドレスと参照カウントの両面で等しいことを確認
     BOOST_CHECK( p0 == p1 );
     BOOST_CHECK( p0.use_count() == p1.use_count() );
@@ -41,6 +85,8 @@ void test1( const gintenlib::clonable_ptr<T>& p0 )
     // リセットのテスト
     p1.reset();
     BOOST_CHECK( p1 == 0 );
+    // ふたたびテスト
+    test_pointer( p1 );
     
     // この時点で参照カウントは元に戻るはず
     BOOST_CHECK( p0.use_count() == count );
@@ -48,13 +94,24 @@ void test1( const gintenlib::clonable_ptr<T>& p0 )
   
   // 本題。clone のテスト
   {
-    ptr_type p1;
+    // まず参照カウントを調べる
+    int count = p0.use_count();
+    
+    // clone を作る
+    clonable_ptr<T> p1;
     p1 = p0.clone();
+    // とりあえずテスト
+    test_pointer( p1 );
+    
+    // clone() しても参照カウントは変わらない
+    BOOST_CHECK( p0.use_count() == count );
     
-    // また、コピーが出来た分、参照カウントは増えているはず
     if( p0 )
     {
-      BOOST_CHECK( p0.get() != p1.get() );
+      // clone で作られたオブジェクトは unique
+      BOOST_CHECK( p1.unique() );
+      // clone したため、別のオブジェクトが格納されてるはず
+      BOOST_CHECK( p0 != p1 );
     }
     else
     {
@@ -69,9 +126,13 @@ void test1( const gintenlib::clonable_ptr<T>& p0 )
     // unique のときは to_unique() を呼んでも何もしないはず
     p1.to_unique();
     BOOST_CHECK( p_ == p1.get() );
+    // 念のためテスト
+    test_pointer( p1 );
     
     // 次に p1 にふたたび p0 の値を入れる
     p1 = p0;
+    // 念のためテスト
+    test_pointer( p1 );
     // 生ポインタの値を更新
     p_ = p1.get();
     // これにより、NULL であるかユニークじゃないかの状態になった
@@ -80,6 +141,8 @@ void test1( const gintenlib::clonable_ptr<T>& p0 )
     p1.to_unique();
     BOOST_CHECK( p_ == p0.get() );
     BOOST_CHECK( !p1 || p_ != p1.get() );
+    // またまたテスト
+    test_pointer( p1 );
   }
   
   // おまけで to_shared
@@ -88,20 +151,52 @@ void test1( const gintenlib::clonable_ptr<T>& p0 )
     int count = p0.use_count();
     
     boost::shared_ptr<T> p1 = to_shared( p0 );
+    // アドレスは一緒
     BOOST_CHECK( p0.get() == p1.get() );
+    // カウントは一つ増える
+    BOOST_CHECK( !p0 || p0.use_count() == count+1 );
     
     // shared_ptr がリセットされた場合、ちゃんと参照カウントは減る?
     p1.reset();
     BOOST_CHECK( p0.use_count() == count );
   }
   
+  // const 関連
+  {
+    // T から const T への変換
+    clonable_ptr<const T> p1 = p0;
+    // 念のためテスト
+    test_pointer( p1 );
+    // アドレスとカウントが等しいことを確認
+    BOOST_CHECK( p0 == p1 );
+    BOOST_CHECK( p0.use_count() == p1.use_count() );
+    
+    // const T 型のポインタで reset してみる
+    p1.reset( static_cast<const T*>( new T() ) );
+    // reset 後は当然 unique()
+    BOOST_CHECK( p1 && p1.unique() );
+    // 念のため更にテスト
+    test_pointer( p1 );
+    
+    // const T => T の変換( clone すれば可能 )
+    clonable_ptr<T> p2 = p1.clone();
+    // clone しないと無理
+    // clonable_ptr<T> p2 = p1;
+    
+    // 念には念を入れてテスト
+    test_pointer( p2 );
+    // clone() 後なので当然 unique
+    BOOST_CHECK( p2 && p2.unique() );
+    BOOST_CHECK( p1 != p2 );
+  }
+  
   // おわり
 }
 
 int test_main( int argc, char* argv[] )
 {
   test1( gintenlib::clonable_ptr<int>( new int() ) );
-  test1( gintenlib::clonable_ptr<int>() );
+  test1( gintenlib::clonable_ptr<int>( static_cast<int*>(0) ) );
     
   return 0;
 }
diff --git a/tests/to_string.cc b/tests/to_string.cc
new file mode 100644 (file)
index 0000000..66f4a3b
--- /dev/null
@@ -0,0 +1,65 @@
+#include "../gintenlib/to_string.hpp"
+
+// boost の単体テストフレームワーク
+#include <boost/test/minimal.hpp>
+
+
+#include <iostream>
+using namespace std;
+
+// テストクラス(単純な例)
+struct hoge
+{
+  // これから to_string が定義される
+  friend ostream& operator<<( ostream& lhs, const hoge& )
+  {
+    return lhs << "hoge";
+  }
+  
+};
+
+// テストクラス2
+struct fuga
+{
+  // operator<< の他に
+  friend ostream& operator<<( ostream& lhs, const fuga& )
+  {
+    return lhs << "fuga::operator<<";
+  }
+  
+  // friend 関数 to_string を定義するとどうなる?
+  friend string to_string( const fuga& )
+  {
+    return "fuga::to_string";
+  }
+  
+};
+
+// テストしてみる
+int test_main( int argc, char* argv[] )
+{
+  using gintenlib::to_string;
+  
+  // まず組み込み型
+  BOOST_CHECK( gintenlib::to_string(23) == "23" );
+  BOOST_CHECK( to_string(42) == "42" ); // using してるので無修飾でも使える
+  BOOST_CHECK( gintenlib::to_str(108) == "108" ); // 短縮名
+  
+  // ユーザ定義型1
+  hoge h;
+  // 全て operator<< から定義される。簡単
+  BOOST_CHECK( gintenlib::to_string(h) == "hoge" );
+  BOOST_CHECK( to_string(h) == "hoge" );
+  BOOST_CHECK( gintenlib::to_str(h) == "hoge" );
+  
+  // ユーザ定義型で、 operator<< の他に to_string が定義されている場合
+  fuga f;
+  // gintenlib::to_string は operator<< から呼ばれる
+  BOOST_CHECK( gintenlib::to_string(f) == "fuga::operator<<" );
+  // 無修飾の to_string は ADL によって fuga に特化したバージョンが呼ばれる
+  BOOST_CHECK( to_string(f) == "fuga::to_string" );
+  // gintenlib::to_str は using 宣言してから無修飾で to_string したのと同じ効果になる
+  BOOST_CHECK( gintenlib::to_str(f) == "fuga::to_string" );
+  
+  return 0;
+}