boost.png (6897 bytes)Header <boost/io/ios_state.hpp >

頭文件 boost/io/ios_state.hpp 用於保存在 C++ IOStreams 系統中的對象的流狀態。

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原理

有時某個值需要限定於一定的代碼範圍內變化。Saver 保存器類保存了某個對象(或對象的外表)的當前狀態,並在析構時恢復該對象的狀態,恢復所有對該對像所做的改變。

保存器類的策略有助於使用 I/O 流對象。操縱子對像會在輸入或輸出時改變流的某些狀態。被操縱子改變了的狀態在I/O事務之後會保持新的值。如果操縱子是用在一個不期望流狀態的修改影響到外部的函數中時,這就會成為一個問題。

#include <ostream>
#include <ios>

void hex_my_byte( std::ostream &os, char byte )
{
os << std::hex << static_cast<unsigned>(byte);
}

在調用了 hex_my_byte 之後,os 流會保持其新的十六進制打印模式。通過通過手工調用流狀態的檢查成員函數和修改成員函數來保存和恢復流的打印模式。如果主程序的功能非常複雜和/或需要異常安全性,那麼這種手工的方法就太笨拙了。保存器類可以實現更好的"資源獲得即初始化"的策略。

更好的代碼請見以下 example例子, 使用了保存器類。

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();

void restore();
};

state_type 是 IOStreams 的基類 std::ios_base. 用戶通常會將一個真正的輸入、輸出或組合的流對像作為 state-type 參數,而不是用基類對象。第一個構造函數接受一個流對象,保存流的一個引用,以及特定的流屬性的當前值。第二個構造函數與第一個類似,但使用第二個參數來將流的屬性改變為給定的 aspect_type 值。析構函數將流的屬性恢復為保存的值。屬性恢復可以(且常常)使用 restore 成員函數提前執行。

基本 IOStreams 狀態保存器類
保存的屬性 屬性類型 讀方法 寫方法
boost::io::ios_flags_saver 格式控制標誌 std::ios_base::fmtflags flags flags
boost::io::ios_precision_saver 小數點後的打印位數 std::streamsize precision precision
boost::io::ios_width_saver 打印對象的最小字段寬度 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();

void restore();
};

state_type 是 IOStreams 的基類模板 std::basic_ios<Ch, Tr> 的一個版本,其中 Ch 是字符類型,Tr 是字符特性類。用戶通常會將一個真正的輸入、輸出或組合的流對像作為 state-type 參數,而不是用基類對象。第一個構造函數接受一個流對象,保存流的一個引用,以及特定的流屬性的當前值。第二個構造函數與第一個類似,但使用第二個參數來將流的屬性改變為給定的 aspect_type 值。析構函數將流的屬性恢復為保存的值。屬性恢復可以(且常常)使用 restore 成員函數提前執行。

增加 IOStreams 狀態保存類模板
類模板 保存的屬性 屬性類型 讀方法 寫方法
boost::io::basic_ios_iostate_saver<Ch, Tr> 流的失敗狀態[1], [2] std::ios_base::iostate rdstate clear
boost::io::basic_ios_exception_saver<Ch, Tr> 哪一個失敗狀態引發了異常 [1] std::ios_base::iostate exceptions exceptions
boost::io::basic_ios_tie_saver<Ch, Tr> 流所同步的輸出流同步 std::basic_ostream<Ch, Tr> * tie tie
boost::io::basic_ios_rdbuf_saver<Ch, Tr> 流所關聯的流緩衝 [2] std::basic_streambuf<Ch, Tr> * rdbuf rdbuf
boost::io::basic_ios_fill_saver<Ch, Tr> 用於填充過寬字段的字符 Ch fill fill
boost::io::basic_ios_locale_saver<Ch, Tr> 流所關聯的Locale 信息 [3] std::locale getloc (from std::ios_base) imbue (from std::basic_ios<Ch, Tr>)

注意

  1. 當失敗狀態標誌與/或失敗狀態異常監視標誌被改變時,如果這兩組標誌間出現了匹配,將拋出一個異常。這意味著這些類模板的構造函數或析構函數有可能拋出異常。
  2. 當關聯的流緩衝被改變時,如果給定的流緩衝地址為非-NULL,則流的失敗狀態集將被重置為 "good",如果地址為NULL,則設置 "bad" 失敗狀態。這意味著一個 "good" 的已保存失敗狀態有可能被恢復為 "bad",如果該流被剝奪了相關聯的流緩衝。更糟的是,給定一個 NULL 的流緩衝地址,如果監測到 "bad" 失敗狀態,將會拋出一個異常。這意味著這些類模板的構造函數或析構函數有可能拋出異常。
  3. locale 的保存器使用 std::basic_ios<Ch, Tr> 類來取出它們的信息,雖然它可能使用了 std::ios_base 中的功能。問題是,在 ios_base 中所需的成員函數的版本並不是多態地關聯到 basic_ios 中。保存器類中要使用的流將使用繼承層次中最接近的成員函數,即 basic_ios 中的函數。

Savers of 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();

void restore();
};

索引 i 用於區分特定的用戶自定義格式化屬性。該索引只能在運行期確定(就像靜態成員函數 std::ios_base::xalloc)。

state_type 是 IOStreams 的基類 std::ios_base. 用戶通常會將一個真正的輸入、輸出或組合的流對像作為 state-type 參數,而不是用基類對象。第一個構造函數接受一個流對象,保存流的一個引用,以及特定的流屬性的當前值。第二個構造函數與第一個類似,但使用第二個參數來將流的屬性改變為給定的 aspect_type 值。析構函數將流的屬性恢復為保存的值。屬性恢復可以(且常常)使用 restore 成員函數提前執行。

IOStream 用戶自定義狀態保存器類
保存的屬性 屬性類型 引用方法
boost::io::ios_iword_saver 數字的用戶自定義格式標誌 long iword
boost::io::ios_pword_saver 指針的用戶自定義格式標誌 void * pword

Savers for Combined Attributes組合屬性的保存器

有三個類(模板)用作組合屬性的保存器。boost:io::ios_base_all_saver 保存器類組合了所有基本屬性保存器類的功能。它有一個構造函數,接受要保存狀態的流。boost::io::basic_ios_all_saver 組合了所有增強屬性保存器類模板以及組合基本屬性保存器類的功能。它有一個構造函數,接受要保存狀態的流。boost::io::ios_all_word_saver 保存器類組合了保存自定義格式化信息的保存器類。它的構造函數接受要保存屬性的流以及用戶自定義屬性的索引。每一個類的析構函數都恢復保存的狀態。屬性恢復可以(且常常)使用 restore 成員函數提前執行。

Example例子

rationale原理 一節中使用的代碼可以從兩個地方進行改進。打印函數可以在改變格式狀態的代碼的周圍使用一個保存器。或者在調用的函數中用一個保存器包圍這個調用。或者兩 者都做,尤其是在用戶不知道打印函數是否使用了狀態保存器時。如果用戶想要前後的一系列改變,而不想將每次改變都包在一個單獨的代碼塊中,則可以在每次嘗 試間調用 restore 成員函數。

#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;
using std::cerr;

//...

{
boost::io::ios_all_saver ias( cout );

new_hex_my_byte( cout, 'A' );
}

//...

{
boost::io::ios_all_saver ias( cerr );

new_hex_my_byte( cerr, 'b' );
ias.restore();
new_hex_my_byte( cerr, 'C' );
}

//...
}

References參考

Credits

Contributors

Daryle Walker
Started the library. Contributed the initial versions of the format flags, precision, width, and user-defined format flags saver classes. Contributed the initial versions of the success state, success state exception flags, output stream tie, stream buffer, character fill, and locale saver class templates. Contributed the combined attribute classes and class template. Contributed the test file ios_state_test.cpp.

History

28 Feb 2005, Daryle Walker
Added the restore member functions, based on suggestions by Gennadiy Rozental and Rob Stewart
13 Mar 2002, Daryle Walker
Initial version

Revised: 28 February 2005

Copyright 2002, 2005 Daryle Walker. Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)