boost/io/ios_state.hpp は、C++の入出力ストリームシステムにおけるオブジェクトのストリーム状態を保持する ことを保証する。
時々、ある値が制限されたスコープ内でのみ変化しなければならない時がある。セーバー クラス群は、オブジェクトの現在の状態(またはオブジェクトの様相)のコピーを保持し、 デストラクト時にスコープ内で発生した変更を全て元通りにして、そのオブジェクトの状 態を回復する。
セーバークラスの戦略は、入出力ストリームオブジェクトを使う時に有効である。マ ニピュレータオブジェクトは、入力または出力時のストリームの様相を変更できる。普通 マニピュレータによって入出力ストリームの状態を変更すると、処理が終わった後の次の 値に対しても影響が残ってしまう。これは、マニピュレータを外面的にはストリームの状 態を変更しないと仮定している関数の中で使う場合に問題になるかもしれない。
#include <ostream> #include <ios> void hex_my_byte( std::ostream &os, char byte ) { os << std::hex << static_cast<unsigned>(byte); }
os ストリームは、hex_my_byte
を呼んだ後も16進表記モー
ドを保持し続ける。ストリームの表記モードは、ストリームの状態を調べたり、変更する
ためのメンバー関数を手動で呼び出すことで変更されたり、元に戻されたりする。この手
動による方法は、メインとなる関数の性質が複雑、且つ/または例外安全である必要があ
る場合には扱いにくいものになってしまう。セーバークラスを使うことで、「リソースの
確保は初期化時に」というより優れた戦略を採ることができるようになる。
セーバークラスを使ったより優れたコードの例 を下の方に示す。
#include <iosfwd> // for std::char_traits (declaration) namespace boost { namespace io { class ios_flags_saver; class ios_precision_saver; class ios_width_saver; class ios_base_all_saver; template < typename Ch, class Tr = ::std::char_traits<Ch> > class basic_ios_iostate_saver; template < typename Ch, class Tr = ::std::char_traits<Ch> > class basic_ios_exception_saver; template < typename Ch, class Tr = ::std::char_traits<Ch> > class basic_ios_tie_saver; template < typename Ch, class Tr = ::std::char_traits<Ch> > class basic_ios_rdbuf_saver; template < typename Ch, class Tr = ::std::char_traits<Ch> > class basic_ios_fill_saver; template < typename Ch, class Tr = ::std::char_traits<Ch> > class basic_ios_locale_saver; template < typename Ch, class Tr = ::std::char_traits<Ch> > class basic_ios_all_saver; typedef basic_ios_iostate_saver<char> ios_iostate_saver; typedef basic_ios_iostate_saver<wchar_t> wios_iostate_saver; typedef basic_ios_exception_saver<char> ios_exception_saver; typedef basic_ios_exception_saver<wchar_t> wios_exception_saver; typedef basic_ios_tie_saver<char> ios_tie_saver; typedef basic_ios_tie_saver<wchar_t> wios_tie_saver; typedef basic_ios_rdbuf_saver<char> ios_rdbuf_saver; typedef basic_ios_rdbuf_saver<wchar_t> wios_rdbuf_saver; typedef basic_ios_fill_saver<char> ios_fill_saver; typedef basic_ios_fill_saver<wchar_t> wios_fill_saver; typedef basic_ios_locale_saver<char> ios_locale_saver; typedef basic_ios_locale_saver<wchar_t> wios_locale_saver; typedef basic_ios_all_saver<char> ios_all_saver; typedef basic_ios_all_saver<wchar_t> wios_all_saver; class ios_iword_saver; class ios_pword_saver; class ios_all_word_saver; } }
基本セーバークラスは、次のようなフォーマットを持っている。:
class saver_class { typedef std::ios_base state_type; typedef implementation_defined aspect_type; explicit saver_class( state_type &s ); saver_class( state_type &s, aspect_type const &new_value ); ~saver_class(); };
state_typeは、入出力ストリーム基本クラスのstd::ios_base
のことである。ユーザーは普通、実際の入力や出力、または基本ク
ラスオブジェクトではない混合されたストリームオブジェクトをstate-type
パラメータに置くかもしれない。最初のコンストラクタは、ストリームオブジェ
クトを1つ取り、そのストリームへの参照とストリーム固有の属性とを保持する。2番目
のコンストラクタは一つ目のと同様に働くが、さらにそれに加えて第2引数に新しい
aspect_typeを指定することでストリームの属性を変更できる。デストラクタ
はストリームの属性を保持しておいた状態に戻す。
Class | Saved Attribute | Attribute Type | Reading Method | Writing Method |
---|---|---|---|---|
boost::io::ios_flags_saver |
Format control flags | std::ios_base::fmtflags |
flags |
flags |
boost::io::ios_precision_saver |
Number of digits to print after decimal point | std::streamsize |
precision |
precision |
boost::io::ios_width_saver |
Minimum field width for printing objects | std::streamsize |
width |
width |
セーバークラステンプレートは次のようなフォーマットを持つ:
template < typename Ch, class Tr > class saver_class { typedef std::basic_ios<Ch, Tr> state_type; typedef implementation_defined aspect_type; explicit saver_class( state_type &s ); saver_class( state_type &s, aspect_type const &new_value ); ~saver_class(); };
state_typeは、入出力ストリーム基本クラステンプレート
std::basic_ios<Ch, Tr>
のことである。ここで Ch
は、
文字タイプ、Tr
は文字特性のことである。ユーザー
は普通、実際の入力や出力、または基本クラスオブジェクトではない混合されたストリー
ムオブジェクトをstate-typeパラメータに置くかもしれない。最初の
コンストラクタは、ストリームオブジェクトを1つ取り、そのストリームへの参照とスト
リーム固有の属性とを保持する。2番目のコンストラクタは一つ目のと同様に働くが、さ
らにそれに加えて第2引数に新しいaspect_typeを指定することでストリーム
の属性を変更できる。デストラクタはストリームの属性を保持しておいた状態に戻す。
Class Template | Saved Attribute | Attribute Type | Reading Method | Writing Method |
---|---|---|---|---|
boost::io::basic_ios_iostate_saver<Ch, Tr> |
Failure state of the stream [1] | std::ios_base::iostate |
rdstate |
clear |
boost::io::basic_ios_exception_saver<Ch, Tr> |
Which failure states trigger an exception [1] | std::ios_base::iostate |
exceptions |
exceptions |
boost::io::basic_ios_tie_saver<Ch, Tr> |
Output stream synchronized with the stream | std::basic_ostream<Ch, Tr> * |
tie |
tie |
boost::io::basic_ios_rdbuf_saver<Ch, Tr> |
Stream buffer associated with the stream [2] | std::basic_streambuf<Ch, Tr> * |
rdbuf |
rdbuf |
boost::io::basic_ios_fill_saver<Ch, Tr> |
Character used to pad oversized field widths | Ch |
fill |
fill |
boost::io::basic_ios_locale_saver<Ch, Tr> |
Locale information associated with the stream [3] | std::locale |
getloc (from std::ios_base ) |
imbue (from std::basic_ios<Ch, Tr> ) |
std::ios_base
の関数
をロケール情報を取り出すために使用できたかもしれないが、そうはせずに
std::basic_ios<Ch, Tr>
クラスを使用して情報を取り出し
ている。この問題は、basic_ios
の中の必要とするメンバ関数
が多態的にbasic_ios
のそれに結びついていないためである。セー
バークラスと共に使用されるストリームクラスは継承によってそれらに最も近い
メンバ関数を使用するべきである。ユーザー定義の情報の為のセーバークラスは、次のようなフォーマットを持つ。
#include <iosfwd> // for std::ios_base (declaration) class saver_class { typedef std::ios_base state_type; typedef int index_type; typedef implementation_defined aspect_type; explicit saver_class( state_type &s, index_type i ); saver_class( state_type &s, index_type i, aspect_type const &new_value ); ~saver_class(); };
インデックス i は、ユーザー定義の属性を区別するのに使用される。
インデックスは、実行時にのみ決定できる。(それはおそらく静的
メンバ関数std::ios_base::xalloc
と同時だろう。)
state_type は、入出力ストリームシステムの基本クラス
std::ios_base
である。ユーザー
は普通、実際の入力や出力、または基本クラスオブジェクトではない混合されたストリー
ムオブジェクトをstate-typeパラメータに置くかもしれない。最初の
コンストラクタは、ストリームオブジェクトを1つ取り、そのストリームへの参照とスト
リーム固有の属性とを保持する。2番目のコンストラクタは一つ目のと同様に働くが、さ
らにそれに加えて第3引数に新しいaspect_typeを指定することでストリーム
の属性を変更できる。デストラクタはストリームの属性を保持しておいた状態に戻す。
Class | Saved Attribute | Attribute Type | Reference Method |
---|---|---|---|
boost::io::ios_iword_saver |
Numeric user-defined format flag | long |
iword |
boost::io::ios_pword_saver |
Pointer user-defined format flag | void * |
pword |
属性セーバークラスを統合するために3つのクラス(テンプレート)がある。
boost:io::ios_base_all_saver
セーバークラスは、全ての基本属性セーバ
ークラスの機能を統合している。このクラスには引数に状態を保持させたいストリームを
取ることのできるコンストラクタが一つある。
boost::io::basic_ios_all_saver
セーバークラスは、全ての高等属性セー
バークラステンプレートの機能と基本属性セーバークラスを統合している。このクラスに
は引数に状態を保持させたいストリームを取ることのできるコンストラクタが一つある。
boost::io::ios_all_word_saver
セーバークラスは、ユーザー定義の情報を
保持するクラスを結合する。このコンストラクタは、属性を保持させたいストリームと
ユーザーが定義した属性のインデックスを引数に取る。
rationale で使用したコードは2つの点で改善できる。 表示出力関数は書式設定状態を変更するコードの周りでセーバーを使えるかもしれない。 または関数の呼び出し側でその関数の周りをセーバーで囲むこともできる。または両方を 偏執症患者のために行うこともできる。
#include <boost/io/ios_state.hpp> #include <ios> #include <iostream> #include <ostream> void new_hex_my_byte( std::ostream &os, char byte ) { boost::io::ios_flags_saver ifs( os ); os << std::hex << static_cast<unsigned>(byte); } int main() { using std::cout; //... { boost::io::ios_all_saver ias( cout ); new_hex_my_byte( cout, 'A' ); } //... }
Revised: 13 March 2002
Copyright c Daryle Walker 2002. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.
Japanese Translation Copyright (C) 2003 MINAMI Takeshi. オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の 複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」 に提供されており、いかなる明示的、暗黙的保証も行わない。また、 いかなる目的に対しても、その利用が適していることを関知しない。