OSDN Git Service

pointer_facade の < を訂正 & clonable_ptr のテストに < 比較を追加
[gintenlib/gintenlib.git] / gintenlib / pointer_facade.hpp
index 4465086..4d5af9f 100644 (file)
@@ -5,9 +5,9 @@
 
       <gintenlib/pointer_facade.hpp>
 
-  pointer_facade ¡§ ´Ê°×¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿À½ºî
+  pointer_facade : 簡易スマートポインタ製作
 
-  Àë¸À¡§
+  宣言:
     template< class Derived, typename T, typename Category = Derived >
     struct pointer_facade
     {
       typedef T* pointer;
       typedef T& reference;
       
-      // »²¾È³°¤·¤È¥Ý¥¤¥ó¥¿¼èÆÀ
+      // 参照外しとポインタ取得
       reference operator*() const;
       pointer operator->() const;
       friend pointer get_pointer( const Derived& target );
       
-      // bool Èæ³Ó
+      // bool 比較
       operator unspecified_bool_type() const;
       bool operator!() const;
     
     };
     
-    // ¥Æ¥ó¥×¥ì¡¼¥ÈÈÇÁê¸ßÈæ³Ó
-    // ¥«¥Æ¥´¥ê¤¬Æ±¤¸¤â¤Î¤Ê¤éÁê¸ßÈæ³Ó£Ï£Ë
+    // テンプレート版相互比較
+    // カテゴリが同じものなら相互比較OK
     template<typename T, typename U, typename D1, typename D2, typename C>
     inline bool operator==
       ( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs );
     inline bool operator<
       ( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs );
   
-  µ¡Ç½¡§
-    get() ¤µ¤¨¼ÂÁõ¤¹¤ì¤Ð¡¢¤½¤ì¤ò¸µ¤Ë¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤È¤·¤ÆɬÍפʤâ¤Î¤òÀ¸À®¤¹¤ë¥¯¥é¥¹¤Ç¤¹¡£
-    ¼ÂÁõ¤·¤Æ¤¯¤ì¤ë¤â¤Î¤Ï°Ê²¼¤ÎÄ̤ꡧ
-    ¡¡¡¦element_type, value_type, pointer, reference ¤Î·¿ÄêµÁ
-    ¡¡¡¦operator*, operator->, get_pointer() ¤Ë¤è¤ë¥Ý¥¤¥ó¥¿¼èÆÀ
-    ¡¡¡¦boolÃͤȤÎÈæ³Ó¡¢¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿Æ±»Î¤ÎÈæ³Ó
-    ¡¡¡¦°Û¤Ê¤ë·¿¤ò¼¨¤¹¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿Æ±»Î¤ÎÈæ³Ó¡ÊƱ¤¸¥«¥Æ¥´¥ê¤Ë°¤¹¤ë¤â¤Î¤Î¤ß¡Ë
+  機能:
+    get() さえ実装すれば、それを元にスマートポインタとして必要なものを生成するクラスです。
+    実装してくれるものは以下の通り:
+     ・element_type, value_type, pointer, reference の型定義
+     ・operator*, operator->, get_pointer() によるポインタ取得
+     ・bool値との比較、スマートポインタ同士の比較
+     ・異なる型を示すスマートポインタ同士の比較(同じカテゴリに属するもののみ)
     
-    »È¤¤Êý¤Ï bool_comparable ¤ÈƱ¤¸¡¢¡Ö¥Æ¥ó¥×¥ì¡¼¥È¤Ë¼«Ê¬¼«¿È¤Î·¿Ì¾¤òÆþ¤ì¤Æ·Ñ¾µ¡×¡£
-    ÂèÆó°ú¿ô¤Ï¥Ý¥¤¥ó¥¿¤ò³ÊǼ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Î·¿¤ò¼¨¤·¤Þ¤¹¡£
-    ¾Êά²Äǽ¤ÊÂè»°°ú¿ô¤Ï¥Ý¥¤¥ó¥¿¤Î¥«¥Æ¥´¥ê¡¢Âè»°°ú¿ô¤¬Æ±¤¸¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿Æ±»Î¤ÏÁê¸ßÈæ³Ó¤Ç¤­¤Þ¤¹¡£
-    ¾Êά¤·¤¿¾ì¹ç¡¢Â¾¤Î¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤È¤ÏÈæ³Ó¤¬½ÐÍè¤Þ¤»¤ó¡Ê¤Ç¤âÄ̾ï¤ÏÈæ³Ó¤Ç¤­¤¿Êý¤¬Îɤ¤¤Ç¤¹¤è¡©¡Ë¡£
-    ¤µ¤é¤Ë¾Ü¤·¤¯¤Ï¡¢²¼¤ÎÍó¤ä¡¢¶äÅ·¥é¥¤¥Ö¥é¥ê¤ÇÄêµÁ¤µ¤ì¤¿¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤Î¼ÂÁõ¤ò¤´Í÷¤¯¤À¤µ¤¤¡£
+    使い方は bool_comparable と同じ、「テンプレートに自分自身の型名を入れて継承」。
+    第二引数はポインタを格納するオブジェクトの型を示します。
+    省略可能な第三引数はポインタのカテゴリ、第三引数が同じスマートポインタ同士は相互比較できます。
+    省略した場合、他のスマートポインタとは比較が出来ません(でも通常は比較できた方が良いですよ?)。
+    さらに詳しくは、下の欄や、銀天ライブラリで定義されたスマートポインタの実装をご覧ください。
     
-  »È¤¤Êý¡§
-    // Ã±½ã¤Ê¥Ý¥¤¥ó¥¿¤Ø¤Î¥é¥Ã¥Ñ
+  使い方:
+    // 単純なポインタへのラッパ
     
-    // ¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤òºî¤ë¾ì¹ç¡¢¤Þ¤º¥«¥Æ¥´¥ê¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡£
-    // Æ±¤¸¼ïÎà¤Î¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤Ç¡¢Æ±¤¸¥«¥Æ¥´¥ê¤ò¶¦Í­¤¹¤ë¤³¤È¤Ç¡¢
-    // ¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿Æ±»Î¤ÎÁê¸ßÈæ³Ó¤¬¡ÊƱ¤¸¼ïÎà¤Î¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤Ë¸Â¤ê¡Ë²Äǽ¤Ë¤Ê¤ë¡£
-    struct trivial_ptr_category {}; // ¥«¥Æ¥´¥ê¥¯¥é¥¹¤Ï¥¿¥°¤Ê¤Î¤ÇŬÅö¤Ë
+    // スマートポインタを作る場合、まずカテゴリクラスを定義する。
+    // 同じ種類のスマートポインタで、同じカテゴリを共有することで、
+    // スマートポインタ同士の相互比較が(同じ種類のスマートポインタに限り)可能になる。
+    struct trivial_ptr_category {}; // カテゴリクラスはタグなので適当に
     
-    // ËÜÂΠ
+    // 本体 
     template<typename T>
     class trivial_ptr :
-      public gintenlib::pointer_facade< trivial_ptr<T>, T, trivial_ptr_category > // ¤³¤¦»È¤¦
+      public gintenlib::pointer_facade< trivial_ptr<T>, T, trivial_ptr_category > // こう使う
     {
      public:
       trivial_ptr() : p(0) {}
       explicit trivial_ptr( T* ptr ) : p( ptr ) {}
       
-      // ²òÊü½èÍý¤È¤«¹Ô¤ï¤Ê¤¤
+      // 解放処理とか行わない
       // ~trivial_ptr() throw () {}
       
-      // get() ¤µ¤¨¤¢¤ì¤ÐOK
+      // get() さえあればOK
       T* get() const { return p; }
       
-      // reset ¤È¤« swap ¤â¤¢¤ë¤ÈÎɤ¤¤±¤É¡¢´ðËܤϤ³¤ì¤Ç½ªÎ»¡ª
+      // reset とか swap もあると良いけど、基本はこれで終了!
       
      private:
       T* p;
@@ -89,8 +89,8 @@
     {
       trivial_ptr<int> p1( new int() );
       
-      // ¿§¡¹¤È¼«Æ°ÄêµÁ¤·¤Æ¤¯¤ì¤ë¤Î¤Ç
-      // ¤³¤ó¤Ê´¶¤¸¤Ë½ñ¤±¤ë
+      // 色々と自動定義してくれるので
+      // こんな感じに書ける
       if( p1 )  // OK
       {
         cout << *p1 << endl; // OK
       trivial_ptr<vector<int> > p2( new vector<int>() );
       cout << p2->size() << endl; // OK
       
-      trivial_ptr<void> p0; // void ¤Ø¤Î¥Ý¥¤¥ó¥¿¤âŬÀڤ˿¶¤êʬ¤±¤Æ¤¯¤ì¤ë
-      assert( p0 != p1 ); // ¤â¤Á¤í¤óÈæ³Ó¤Ç¤­¤ë
+      trivial_ptr<void> p0; // void へのポインタも適切に振り分けてくれる
+      assert( p0 != p1 ); // もちろん比較できる
       
       // todo: delete
     }
   
-  Ãí°Õ»ö¹à¡§
-    ¥Ý¥¤¥ó¥¿¤ËɬÍפʵ¡Ç½¤Ï¤¢¤é¤«¤¿ÍÑ°Õ¤·¤Æ¤¯¤ì¤ëÊØÍø¥¯¥é¥¹¤Ç¤¹¤¬¡¢
-    static_pointer_cast ¤ä¤é swap ¤ä¤é reset ¤ä¤é¤ÏÄêµÁ¤·¤Æ¤¯¤ì¤Þ¤»¤ó¡£Ëº¤ì¤Ê¤¤¤è¤¦¤Ë¡£
-    ¤Ê¤ª¡¢ friend ´Ø¿ô¤Î get_pointer ¤ä operator== ¤Ê¤ó¤«¤Ï¡¢gintenlib Ì¾Á°¶õ´ÖÆâ¤ËÄêµÁ¤µ¤ì¤Þ¤¹¡£
-    Ä̾ï¤Ï ADL ¤Ë¤è¤Ã¤Æ°Õ¼±¤¹¤ëɬÍפϤ¢¤ê¤Þ¤»¤ó¤¬¡¢¸Å¤¤¥³¥ó¥Ñ¥¤¥é¤Ç¤Ï°ú¤Ã¤«¤«¤ë¤«¤â¡£
+  注意事項:
+    ポインタに必要な機能はあらかた用意してくれる便利クラスですが、
+    static_pointer_cast やら swap やら reset やらは定義してくれません。忘れないように。
+    なお、 friend 関数の get_pointer や operator== なんかは、gintenlib 名前空間内に定義されます。
+    通常は ADL によって意識する必要はありませんが、古いコンパイラでは引っかかるかも。
 
 */
 
 #include "bool_comparable.hpp"
 
 #include <cassert>
+#include <functional> // for std::less
 #include <boost/type_traits/add_reference.hpp>
 
 namespace gintenlib
 {
   template< typename Derived, typename T, typename Category = Derived >
-  struct pointer_facade
-    : bool_comparable< pointer_facade< Derived, T, Category > >
+  class pointer_facade
+    : public bool_comparable< pointer_facade< Derived, T, Category > >
   {
-    // ¥¹¥Þ¡¼¥È¥Ý¥¤¥ó¥¿¤È¤·¤ÆɬÍפʤ¢¤ì¤³¤ì
+    typedef pointer_facade<Derived, T, Category> this_type;
+    
+   public:
+    // スマートポインタとして必要なあれこれ
     typedef T  element_type;
     typedef T  value_type;
     typedef T* pointer;
-    // reference ¤Ï void ·¿¤Ø¤ÎÂбþ¤Î¤¿¤áÆüì
+    // reference は void 型への対応のため特殊
     typedef typename boost::add_reference<T>::type reference;
     
-    // »²¾È³°¤·¤È¥Ý¥¤¥ó¥¿¼èÆÀ
+    // 参照外しとポインタ取得
     reference operator*() const
     {
       using namespace std;
@@ -150,20 +154,17 @@ namespace gintenlib
       return target.get();
     }
     
-    // bool ¤È¤ÎÈæ³Ó
+    // bool との比較
     bool operator!() const
     {
       return !get_();
     }
-    // operator safe_bool ¤Ï bool_comparable ¤Î´É³í
+    // operator safe_bool は bool_comparable の管轄
     
-    // ÅùÃÍÈæ³Ó¤Ê¤É¤Ï³°Éô¤Î¥Æ¥ó¥×¥ì¡¼¥È¤Ç¼ÂÁõ
-  
-   private:
-    template<typename D, typename U, typename C>
-    friend class pointer_facade;
+    // 相互比較は外部で定義する
     
-    // ÇÉÀ¸¥¯¥é¥¹¤Î get() ¤ò¸Æ¤Ó½Ð¤¹
+   private:
+    // 派生クラスの get() を呼び出す
     pointer get_() const
     {
       return static_cast<const Derived*>(this)->get();
@@ -175,8 +176,8 @@ namespace gintenlib
   
   };  // pointer_facade<Derived, T, Category>
   
-  // ¥Æ¥ó¥×¥ì¡¼¥ÈÈÇÁê¸ßÈæ³Ó
-  // ¥«¥Æ¥´¥ê¤¬Æ±¤¸¤â¤Î¤Ê¤éÁê¸ßÈæ³Ó£Ï£Ë
+  // 相互比較
+  // カテゴリが同じものなら相互比較OK
   template<typename T, typename U, typename D1, typename D2, typename C>
   inline bool operator==( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs )
   {
@@ -187,11 +188,18 @@ namespace gintenlib
   {
     return static_cast<const D1&>(lhs).get() != static_cast<const D2&>(rhs).get();
   }
+  
+  // < は、ポインタ型が同じ場合とそうでない場合で分ける
+  template<typename T, typename D, typename C>
+  inline bool operator< ( const pointer_facade<D, T, C>& lhs, const pointer_facade<D, T, C>& rhs )
+  {
+    // 同じポインタの比較は std::less で比較する
+    return std::less<T*>()( static_cast<const D&>(lhs).get(), static_cast<const D&>(rhs).get() );
+  }
   template<typename T, typename U, typename D1, typename D2, typename C>
   inline bool operator< ( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs )
   {
-    // °Û¤Ê¤ë¥Ý¥¤¥ó¥¿Æ±»Î¤ÎÈæ³Ó¤Ï¡¢
-    // boost::shared_ptr ¤Ç < ¤ò»È¤Ã¤Æ¤ë¤Î¤Ç¡¢¤³¤³¤Ç¤â < ¤ÇÈæ³Ó¤¹¤ë
+    // 異なるポインタ同士の比較は、仕方ないので < で比較する
     return static_cast<const D1&>(lhs).get() < static_cast<const D2&>(rhs).get();
   }