## 15.3 データ書式設定文字列の別の側面

`iword()` と `pword()` を使用して、日付の書式設定文字列を、入出力ストリームの記憶領域に保存することにします。この場合、`date` オブジェクトの入出力演算では、書式設定文字列を呼び出して構文解析と書式設定を行うことができます。書式設定パラメータは、一般にマニピュレータで設定するため (7.3.2 節を参照)、日付の書式設定文字列を設定するマニピュレータを追加する必要があります。次のように指定します。

>     date today;
>     ofstream ostr;
>     //
>     ostr << setfmt("%D") << today;

次に、このようなマニピュレータの実装例を示します。

>     class setfmt : public smanip<const char*>
>     {
>      public:
>       setfmt(const char* fmt)
>       : smanip<const char*>(setfmt_,fmt) {}
>      private:
>       static const int datfmtIdx ;                                //1

>       static ios_base& setfmt_(ios_base& str, const char* fmt)
>       {
>         str.pword(datfmtIdx) = (void*) fmt;                       //2
>         return str;
>       }

>       template<class charT, class Traits>
>       friend basic_ostream<charT, Traits> &                       //3
>       operator << (
>       basic_ostream<charT, Traits >& os, const date& dat);
>     };

>     const int setfmt::datfmtIdx = ios_base::xalloc();             //4

マニピュレータの実装手法の詳細は、12.3 節の例 2 で説明していますが、このマニピュレータと入出力ストリームの記憶領域の非公開用途について、補足説明をします。

//1 | マニピュレータクラスは、書式設定文字列を保存する入出力ストリームの記憶領域に、要素のインデックスを保存します。`xalloc()` に対する呼び出しで、`//4` で初期化します。
//2 | マニピュレータでは、インデックス `datfmtIdx` を使用して配列 `pword()` にアクセスし、日付の書式設定文字列までのポインタを保存します。25 `pword()` が返す参照は、日付の書式設定文字列までのポインタの保存専用です。一般に、`iword()` や `pword()` が返す参照を保存しておき、それを利用して後で保存データにアクセスするのは正しい利用方法ではありません。配列の割り当て変更やコピーによって、これらの参照が無効になるためです (詳細は『標準 C++ クラスライブラリ・リファレンス』を参照してください)。
//3 | `date` オブジェクトの挿入子は、ポインタの配列に対するインデックスにアクセスする必要があります。これは、書式設定文字列を読み取り、使用するためです。 そのため、挿入子をフレンドとして宣言する必要があります。原則として、抽出子もフレンドである必要がありますが、標準 C++ ロケールは、標準 C 関数 `strptime()` で使用するような書式設定文字列をサポートしていません。そのため、日付の書式設定文字列をサポートする日付抽出子の実装は、ストリームのロケールを使用することのできる挿入子の実装に比べてはるかに複雑です。簡潔にするために抽出子は省略しました。
//4 | 書式設定文字列が保存される入力ストリームの記憶領域にある要素のインデックスを初期化します。

次に示す `date` オブジェクトの挿入子は、 11.5.1 節で説明したものとほぼ同じです。

>     template<class charT, class Traits>
>     basic_ostream<charT, Traits> &
>     operator << (basic_ostream<charT, Traits >& os, const date& dat)
>     {
>      ios_base::iostate err = 0;
>      char*  patt = 0;
>      int    len  = 0;
>      charT* fmt  = 0;

>      try {
>       typename basic_ostream<charT, Traits>::sentry opfx(os);

>       if(opfx)
>       {
>          patt = (char*) os.pword(setfmt.datfmtIdx);               //1
>          len  = strlen(patt);
>          fmt  = new charT[len];

>          use_facet<ctype<charT> >(os.getloc()).
>              widen(patt, patt+len, fmt);

>          if (use_facet<time_put<charT
>                       ,ostreambuf_iterator<charT,Traits> > >
>               (os.getloc())
>               .put(os,os,os.fill(),&dat.tm_date,fmt,fmt+len)      //2
>               .failed()
>             )
>               err = ios_base::badbit;
>          os.width(0);
>       }
>      } //実行
>      catch(...)
>      {
>         delete [] fmt;
>         bool flag = FALSE;
>         try {
>                os.setstate(ios_base::failbit);
>             }
>         catch( ios_base::failure ) { flag= TRUE; }
>         if ( flag ) throw;
>      }

>      delete [] fmt;
>      if ( err ) os.setstate(err);

>      return os;
>     }

前の挿入子と異なるのは、書式設定文字列が固定文字列 `"%x"` になる代わりに、(`//1` の) 入出力ストリームの記憶領域から読み取られる点です。次に (`//2` で) 書式設定文字列は、ロケールの時間の書式設定ファセットに与えられます。

Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。

OEM リリース, 1998 年 6 月