c++boost.gif (8819 bytes)Header <boost/io/ios_state.hpp >

boost/io/ios_state.hpp は、C++の入出力ストリームシステムにおけるオブジェクトのストリーム状態を保持する ことを保証する。

Contents

  1. Contents
  2. Rationale
  3. Header Synopsis
  4. Savers for Basic Standard Attributes
  5. Savers for Advanced Standard Attributes
  6. Savers for User-Defined Attributes
  7. Savers for Combined Attributes
  8. Example
  9. References
  10. Credits

Rationale

時々、ある値が制限されたスコープ内でのみ変化しなければならない時がある。セーバー クラス群は、オブジェクトの現在の状態(またはオブジェクトの様相)のコピーを保持し、 デストラクト時にスコープ内で発生した変更を全て元通りにして、そのオブジェクトの状 態を回復する。

セーバークラスの戦略は、入出力ストリームオブジェクトを使う時に有効である。マ ニピュレータオブジェクトは、入力または出力時のストリームの様相を変更できる。普通 マニピュレータによって入出力ストリームの状態を変更すると、処理が終わった後の次の 値に対しても影響が残ってしまう。これは、マニピュレータを外面的にはストリームの状 態を変更しないと仮定している関数の中で使う場合に問題になるかもしれない。

#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進表記モー ドを保持し続ける。ストリームの表記モードは、ストリームの状態を調べたり、変更する ためのメンバー関数を手動で呼び出すことで変更されたり、元に戻されたりする。この手 動による方法は、メインとなる関数の性質が複雑、且つ/または例外安全である必要があ る場合には扱いにくいものになってしまう。セーバークラスを使うことで、「リソースの 確保は初期化時に」というより優れた戦略を採ることができるようになる。

セーバークラスを使ったより優れたコードの を下の方に示す。

Header Synopsis

#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;

}
}

Savers for Basic Standard Attributes

基本セーバークラスは、次のようなフォーマットを持っている。:

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を指定することでストリームの属性を変更できる。デストラクタ はストリームの属性を保持しておいた状態に戻す。

Basic IOStreams State Saver Classes
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

Savers for Advanced Standard Attributes

セーバークラステンプレートは次のようなフォーマットを持つ:

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を指定することでストリーム の属性を変更できる。デストラクタはストリームの属性を保持しておいた状態に戻す。

Advanced IOStreams State Saver Class Templates
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>)

Notes

  1. 失敗状態フラグとフラグを監視している失敗状態例外の両方またはどちらかが変 化した場合、もし2つのフラグが一致したら例外が投げられる。これは、 これらのクラステンプレートのコンストラクタまたはデストラクタが例外を投げ ることを意味するかもしれない。
  2. 関連ストリームバッファが変化した場合、もし指定したストリームバッファのア ドレスがNULLでないならばストリームの失敗状態は"good"にリセットされるが、 NULLだった場合には"bad"失敗状態がセットされる。NULLストリームバッファアド レスを指定した場合、もし"bad"失敗状態が監視されていると例外が投げられる。 これは、このクラステンプレートのコンストラクタまたはデス トラクタが例外を投げることを意味するかもしれない。
  3. ロケール用のセーバーは、std::ios_baseの関数 をロケール情報を取り出すために使用できたかもしれないが、そうはせずに std::basic_ios<Ch, Tr>クラスを使用して情報を取り出し ている。この問題は、basic_iosの中の必要とするメンバ関数 が多態的にbasic_iosのそれに結びついていないためである。セー バークラスと共に使用されるストリームクラスは継承によってそれらに最も近い メンバ関数を使用するべきである。

Savers for User-Defined Attributes

ユーザー定義の情報の為のセーバークラスは、次のようなフォーマットを持つ。

#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を指定することでストリーム の属性を変更できる。デストラクタはストリームの属性を保持しておいた状態に戻す。

IOStream User-Defined State Saver Classes
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

Savers for Combined Attributes

属性セーバークラスを統合するために3つのクラス(テンプレート)がある。 boost:io::ios_base_all_saver セーバークラスは、全ての基本属性セーバ ークラスの機能を統合している。このクラスには引数に状態を保持させたいストリームを 取ることのできるコンストラクタが一つある。 boost::io::basic_ios_all_saver セーバークラスは、全ての高等属性セー バークラステンプレートの機能と基本属性セーバークラスを統合している。このクラスに は引数に状態を保持させたいストリームを取ることのできるコンストラクタが一つある。 boost::io::ios_all_word_saver セーバークラスは、ユーザー定義の情報を 保持するクラスを結合する。このコンストラクタは、属性を保持させたいストリームと ユーザーが定義した属性のインデックスを引数に取る。

Example

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' );
    }

    //...
}

References

Credits

Contributors

Daryle Walker
このライブラリを開始した。フォーマットフラグ、精度、幅、そしてユーザー定 義のフォーマットフラグを保持するクラスの初期バージョンに貢献した。成功状 態、成功状態例外フラグ、出力ストリームタイ、ストリームバッファ、文字埋め、 そしてロケールをセーブするクラステンプレートの初期バージョンに貢献した。 属性クラスとクラステンプレートを統合するのに貢献した。テストファイル ios_state_test.cpp に貢献した。

History

13 Mar 2002, Daryle Walker
Initial version

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. オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の 複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」 に提供されており、いかなる明示的、暗黙的保証も行わない。また、 いかなる目的に対しても、その利用が適していることを関知しない。