OSDN Git Service

memberwise_swap を追加
[gintenlib/gintenlib.git] / gintenlib / list_formatter.hpp
index 6d119d0..b22f968 100644 (file)
@@ -5,9 +5,9 @@
 
       <gintenlib/list_formatter.hpp>
 
-  list_formatter ¡§ ¥Õ¥¡¥ó¥¯¥¿ÈÇ list_format¡Êconst char* ÈÇ¡Ë
+  list_formatter : ファンクタ版 list_format(const char* 版)
 
-  Àë¸À¡§
+  宣言:
   template< typename Elem >
   struct basic_list_formatter
   {
       );
 
     typedef gintenlib_value_t(Elem) element_type;
-    // ¥á¥ó¥Ð¡ÖÊÑ¿ô¡×¡¢¼«Í³¤Ë³°Éô¤«¤é¥¢¥¯¥»¥¹¤Ç¤­¤ë
+    // メンバ「変数」、自由に外部からアクセスできる
     element_type pre, delim, post;
 
-    // ½ÐÎÏÈϰϤò»ØÄꤷ¡¢¥¹¥È¥ê¡¼¥à¤Ëή¤»¤ë¤è¤¦¤Ë¤¹¤ë
+    // 出力範囲を指定し、ストリームに流せるようにする
     template< typename InIte >
       list_format_impl_< InIte, Elem, Elem, Elem >
     operator()( const InIte& begin, const InIte& end ) const;
 
-    // ½ÐÎÏÈϰϤò range ¤Ç»ØÄê
+    // 出力範囲を range で指定
     template< typename Range >
       list_format_impl_< gintenlib_const_ite_of(Range), Elem, Elem, Elem >
     operator()( const Range& src ) const;
 
-    // ostream_iterator ¤Î¤è¤¦¤Ë¿¶Éñ¤¦¥¤¥Æ¥ì¡¼¥¿¤òÀ½ºî¡£
-    // ¥¤¥Æ¥ì¡¼¥¿¤¬´û¤ËÀ½ºî¤µ¤ì¤Æ¤¤¤¿¾ì¹ç¤Ï¡¢¤¤¤Ã¤¿¤ó¥ê¥¹¥È¤¬ÊĤ¸¤é¤ì¤ë
+    // ostream_iterator のように振舞うイテレータを製作。
+    // イテレータが既に製作されていた場合は、いったんリストが閉じられる
     template< typename Stream >
     iterator<Stream> make_iterator( Stream& os ) const;
 
 
   typedef basic_list_formatter<const char*> list_formatter;
 
-  µ¡Ç½¡§
-    list_format(v) ¤ä list_format( begin, end ) ¤È»È¤¦Éôʬ¤Ç¡¢Âå¤ï¤ê¤Ë»ÈÍѤǤ­¤ë¥Õ¥¡¥ó¥¯¥¿¡£
+  機能:
+    list_format(v) や list_format( begin, end ) と使う部分で、代わりに使用できるファンクタ。
 
     list_formatter formatter( pre, delim, post );
     cout << formatter(v) << endl;
 
-    ¤³¤Î¥³¡¼¥É¤Î¼Â¹Ô·ë²Ì¤Ï cout << list_format( v, pre, delim, post ) << endl; ¤ÈÅù²Á¡£
-    Í½¤á pre, delim, post ¤ÎÀßÄê¤ò¤·¤Æ¤ª¤¤¤Æ»È¤¤¤Þ¤ï¤·¤¿¤¤¾ì¹ç¤Ë»ÈÍѤǤ­¤ë¡£
+    このコードの実行結果は cout << list_format( v, pre, delim, post ) << endl; と等価。
+    予め pre, delim, post の設定をしておいて使いまわしたい場合に使用できる。
 
-    ¤â¤¦°ì¤Ä¤Îµ¡Ç½¤È¤·¤Æ¡¢make_iterator() ¥á¥ó¥Ð´Ø¿ô¤ò¸Æ¤Ö¤³¤È¤Ç½ÐÎÏ¥¤¥Æ¥ì¡¼¥¿¤ò¹½ÃۤǤ­¤ëµ¡Ç½¤â¤¢¤ê¡¢
+    もう一つの機能として、make_iterator() メンバ関数を呼ぶことで出力イテレータを構築できる機能もあり、
 
     cout << formatter(v);
     cout << formatter( v.begin(), v.end() );
     copy( v.begin(), v.end(), formatter.make_iterator(cout) );
 
-    ¤³¤Î»°¤Ä¤Îʸ¤Î¼Â¹Ô·ë²Ì¤Ï¡¢¤É¤ì¤âÅù¤·¤¤¡£
+    この三つの文の実行結果は、どれも等しい。
 
-  »ÈÍÑÎ㡧
-    // ¹½ÃÛ¤·¤Æ
+  使用例:
+    // 構築して
     gintenlib::list_formatter formatter( "[ ", " | ", " ]\n" );
 
-    // Ç¤°Õ¤Î¥³¥ó¥Æ¥Ê v ¤ËÂФ·¡¢Å¬ÍѤ¹¤ë
+    // 任意のコンテナ v に対し、適用する
     cout << formatter(v);
-    // µÕ½ç¤Ëɽ¼¨¤ò¤·¤Æ¤ß¤ë
+    // 逆順に表示をしてみる
     cout << formatter( v.rbegin(), v.rend() );
-    // µÕ½ç¤Ëɽ¼¨¤¹¤ë¤Ë¤Ï¡¢¤³¤¦½ñ¤¤¤Æ¤â¤è¤¤
+    // 逆順に表示するには、こう書いてもよい
     reverse_copy( v.begin(), v.end(), formatter.ite(cout) );
 
-  Êä­¡§
-    ¡¦pre, delim, post ¤Ï const char* ¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
-      Ç¤°ÕÍ×ÁǤò³ÊǼ¤·¤¿¤¤¾ì¹ç¤Ï¡¢list_formatter_ex ¤òÍѤ¤¤ë¡£
-    ¡¦operator() ¤ÎŬÍÑ·ë²Ì¤Î¼è¤ê°·¤¤¤Ï¡¢ list_format ´Ø¿ô¤ÎÌá¤êÃͤÈƱ¤¸¤è¤¦¤Ë°·¤¦¡£
-    ¡¦½ÐÎÏ¥¤¥Æ¥ì¡¼¥¿¤ò»ÈÍѤ¹¤ë¾ì¹ç¤ÎÃí°Õ»ö¹à¡§
-      ¡¦pre Í×ÁǤϡֺǽé¤ÎÍ×ÁǤ¬¼ÂºÝ¤Ë½ÐÎϤµ¤ì¤ëľÁ°¡×¤Ë½ÐÎϤµ¤ì¤ë¡£
-      ¡¦delim Í×ÁǤϡÖÆó²óÌܰʹߤÎÍ×ÁǤ¬½ÐÎϤµ¤ì¤ëľÁ°¡×¤Ë½ÐÎϤµ¤ì¤ë¡£
-      ¡¦post Í×ÁǤϡ֥³¥Ô¡¼¤ò´Þ¤á¡¢Á´¤Æ¤Î¥¤¥Æ¥ì¡¼¥¿¤¬ÇË´þ¤µ¤ì¤¿¤È¤­¡×¤Ë½ÐÎϤµ¤ì¤ë¡£
-        ¤¿¤À¤·¡¢Ì¤¤À pre ¤¬½ÐÎϤµ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¡¢post ¤â½ÐÎϤµ¤ì¤Ê¤¤¡£
-      ¡¦¤â¤·Á´¤Æ¤Î¥¤¥Æ¥ì¡¼¥¿¤¬ÇË´þ¤µ¤ì¤ëÁ°¤Ë¿·¤¿¤Ê¥¤¥Æ¥ì¡¼¥¿¤òÀ½ºî¤·¤¿¾ì¹ç¡¢
-        ¤½¤Î»þÅÀ¤Ç post Í×ÁǤ¬½ÐÎϤµ¤ì¡¢¡Ö²¿¤â½ÐÎϤµ¤ì¤Æ¤¤¤Ê¤¤¡×¾õÂ֤ˤʤ롣
+  補足:
+    ・pre, delim, post は const char* でなければならない。
+      任意要素を格納したい場合は、list_formatter_ex を用いる。
+    ・operator() の適用結果の取り扱いは、 list_format 関数の戻り値と同じように扱う。
+    ・出力イテレータを使用する場合の注意事項:
+      ・pre 要素は「最初の要素が実際に出力される直前」に出力される。
+      ・delim 要素は「二回目以降の要素が出力される直前」に出力される。
+      ・post 要素は「コピーを含め、全てのイテレータが破棄されたとき」に出力される。
+        ただし、未だ pre が出力されていなければ、post も出力されない。
+      ・もし全てのイテレータが破棄される前に新たなイテレータを製作した場合、
+        その時点で post 要素が出力され、「何も出力されていない」状態になる。
 
 */
 
+// operator() で使う
+#include "list_format.hpp"
+// タイプ数削減のための using 宣言
+#include "call_traits.hpp"
+
 #include <iterator>
 #include <cassert>
 #include <algorithm>  // for swap()
 
 #include <boost/range.hpp>
-#include <boost/call_traits.hpp>
 
-#include "list_format.hpp"
 
 namespace gintenlib
 {
   template< typename Elem >
   class basic_list_formatter
   {
-    typedef typename boost::call_traits<Elem>::param_type param_type;
+    typedef typename call_traits<Elem>::param_type param_type;
 
    public:
-    typedef typename boost::call_traits<Elem>::value_type element_type;
+    typedef typename call_traits<Elem>::value_type element_type;
 
     basic_list_formatter()
       : pre("( "), delim(", "), post(" )"), iterator_count_(0) {}
@@ -132,17 +135,17 @@ namespace gintenlib
       ( param_type pre_, param_type delim_, param_type post_ )
        : pre(pre_), delim(delim_), post(post_), iterator_count_(0) {}
 
-    // ¥á¥ó¥ÐÊÑ¿ô¤Ê¤Î¤Ç¡¢¼«Í³¤Ë¥¢¥¯¥»¥¹¤Ç¤­¤ë¡£
+    // メンバ変数なので、自由にアクセスできる。
     element_type pre, delim, post;
 
-    // ½ÐÎÏÈϰϤò¥¤¥Æ¥ì¡¼¥¿¤Ç»ØÄꤷ¤Æ¡¢¥¹¥È¥ê¡¼¥à¤Ëή¤»¤ë¤è¤¦¤Ë
+    // 出力範囲をイテレータで指定して、ストリームに流せるように
     template< typename InIte >
       list_format_impl_< InIte, Elem, Elem, Elem >
     operator()( const InIte& begin, const InIte& end ) const
     {
       return list_format_impl_< InIte, Elem, Elem, Elem >( begin, end, pre, delim, post );
     }
-    // ½ÐÎÏÈϰϤò range ¤Ç»ØÄꤷ¤Æ¡¢¥¹¥È¥ê¡¼¥à¤Ëή¤»¤ë¤è¤¦¤Ë
+    // 出力範囲を range で指定して、ストリームに流せるように
     template< typename Range >
       list_format_impl_< typename boost::range_iterator<const Range>::type, Elem, Elem, Elem >
     operator()( const Range& src ) const
@@ -151,24 +154,27 @@ namespace gintenlib
           ( boost::begin(src), boost::end(src), pre, delim, post );
     }
 
-    // ¥¤¥Æ¥ì¡¼¥¿
+    // ã\82¤ã\83\86ã\83¬ã\83¼ã\82¿
     template< typename Stream >
     struct iterator
       : std::iterator< std::output_iterator_tag, void, void, void, void >
     {
+      // イテレータを制作する
       iterator( const basic_list_formatter& formatter, Stream& os )
         : formatter_(&formatter), os_(&os)
       {
-        // ½ÐÎϤ¬¡ÖÊĤ¸¤Æ¡×¤Ê¤¤¤Ê¤é¡¢ÊĤ¸¤ë
+        // 出力が「閉じて」ないなら、閉じる
         close();
 
-        // ¤³¤Î»þÅÀ¤Ç¥«¥¦¥ó¥È¤ÏÉé
+        // この時点でカウントは負
         --formatter_->iterator_count_;
       }
-
+      
+      // コピーコンストラクタ
       iterator( const iterator& src )
         : formatter_(src.formatter_), os_(src.os_)
       {
+        // イテレータカウントを変更する
         if( formatter_->iterator_count_ > 0 )
         {
           ++formatter_->iterator_count_;
@@ -179,7 +185,7 @@ namespace gintenlib
         }
         else
         {
-          assert( !"basic_list_formatter::iterator::iterator(const iterator&) : sould not get here." );
+          assert( !"sould not get here." );
         }
       }
 
@@ -187,27 +193,28 @@ namespace gintenlib
       {
         if( formatter_->iterator_count_ > 0 )
         {
-          // count ¤¬Àµ <==> ´û¤Ë²¿¤«½ÐÎϤµ¤ì¤Æ¤¤¤ë
+          // count が正 <==> 既に何か出力されている
           if( --formatter_->iterator_count_ == 0 )
           {
-            // count ¤¬ 0 ¤Ë¤Ê¤Ã¤¿ <==> ¤â¤¦Â¾¤Î¥¤¥Æ¥ì¡¼¥¿¤Ï̵¤¤
+            // count が 0 になった <==> もう他のイテレータは無い
             *os_ << formatter_->post;
           }
         }
         else if( formatter_->iterator_count_ < 0 )
         {
+          // count が負 <==> 閉じる必要はない
           ++formatter_->iterator_count_;
         }
         else
         {
-          assert( !"basic_list_formatter::iterator::~iterator() : sould not get here." );
+          assert( !"sould not get here." );
         }
       }
 
+      // 代入演算
       iterator& operator=( const iterator& src )
       {
-        iterator temp(src);
-        swap(temp);
+        iterator(src).swap(*this);
         return *this;
       }
       void swap( iterator& other )
@@ -221,42 +228,59 @@ namespace gintenlib
         one.swap(other);
       }
 
-      // ¼ÂºÝ¤Î½ÐÎÏ
+      // 実際の出力
       template< typename T >
-      iterator& operator=( const T& val )
+      void output( const T& val ) const
       {
         if( formatter_->iterator_count_ > 0 )
         {
+          // 既に何かが出力された
           *os_ << formatter_->delim << val;
         }
         else if( formatter_->iterator_count_ < 0 )
         {
+          // まだなにも出力されてない
           *os_ << formatter_->pre << val;
           formatter_->iterator_count_ = -formatter_->iterator_count_;
         }
         else
         {
-          assert( !"basic_list_formatter::iterator::operator=(const T&) : sould not get here." );
+          assert( !"sould not get here." );
         }
-        return *this;
       }
 
-      // ¡Ö½ÐÎϤòÊĤ¸¤ë¡×
+      // 「出力を閉じる」
       iterator& close()
       {
-        // ¥«¥¦¥ó¥È¤¬Àµ <==> ½ÐÎϤ¬¡ÖÊĤ¸¤Æ¡×¤Ê¤¤
+        // カウントが正 <==> 出力が「閉じて」ない
         if( formatter_->iterator_count_ > 0 )
         {
-          // ÊĤ¸¤ë
+          // 閉じる
           *os_ << formatter_->post;
-          // ¡Ö̤½ÐÎϡפؤÈÀßÄê
+          // 「未出力」へと設定
           formatter_->iterator_count_ = -formatter_->iterator_count_;
         }
         return *this;
       }
 
-      // »²¾È³°¤·¤â¡¢Á°ÃÖ¡¿¸åÃÖ¥¤¥ó¥¯¥ê¥á¥ó¥È¤â¡¢²¿¤â¤·¤Ê¤¤
-      iterator& operator*(){ return *this; }
+      // 参照を外した場合、出力用プロキシを作って返す
+      struct output_proxy
+      {
+        const iterator* p;
+        explicit output_proxy( const iterator* p_ )
+          : p( p_ ){}
+        
+        // 出力操作
+        template<typename T>
+        output_proxy& operator=( const T& val )
+        {
+          p->output( val );
+          return *this;
+        }
+      };
+      output_proxy operator*() const { return output_proxy(this); }
+      
+      // 前置/後置インクリメントは何もしない
       iterator& operator++(){ return *this; }
       iterator& operator++(int){ return *this; }
 
@@ -269,12 +293,17 @@ namespace gintenlib
     template< typename Stream >
     friend struct iterator;
 
-    // ½ÐÎÏ¥¤¥Æ¥ì¡¼¥¿¤òºî¤ë
+    // 出力イテレータを作る
     template< typename Stream >
     iterator<Stream> make_iterator( Stream& os ) const
     {
       return iterator<Stream>( *this, os );
     }
+    template< typename Stream >
+    friend iterator<Stream> make_iterator( const basic_list_formatter& fmt, Stream& os )
+    {
+      return iterator<Stream>( fmt, os );
+    }
 
   private:
     mutable int iterator_count_;