<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) {}
( 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
( 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_;
}
else
{
- assert( !"basic_list_formatter::iterator::iterator(const iterator&) : sould not get here." );
+ assert( !"sould not get here." );
}
}
{
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 )
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; }
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_;