C++ ライブラリ・リファレンス

引数付きのマニピュレータの使用法

iomanip.h に入っているマニピュレータの 1 つに setfill があります。setfill は、フィールド幅に詰め合わせる文字を設定するマニピュレータで、次の例に示すように定義されています。

引数付きのマニュピュレータ


//ファイル setfill.cc
#include<iostream.h>
#include<iomanip.h>

//非公開のマニピュレータ
static ios& sfill(ios& i, int f) {
         i.fill(f);
         return i;
}

//公開の適用子
smanip_int setfill(int f) {
        return smanip_int(sfill, f);
}

引数付きマニピュレータは、2 つの部分から構成されます。

1 つはマニピュレータ部分で、これは引数を 1 つ追加します。この前の例では、int 型の第 2 引数があります。このような関数に対するシフト演算子は定義されていませんので、このマニピュレータ関数を入出力演算子シーケンスに入れることはできません。そこで、マニピュレータの代わりに補助関数 (適用子) を使用する必要があります。

もう 1 つは適用子で、これはマニピュレータを呼び出します。適用子は大域関数で、そのプロトタイプをヘッダーファイルに入れておきます。マニピュレータは通常、適用子の入っているソースコードファイル内に静的関数として作成します。マニピュレータは適用子からのみ呼び出されるので、静的関数にして、大域アドレス空間にマニピュレータ関数名を入れないようにします。

ヘッダーファイル iomanip.h には、さまざまなクラスが定義されています。各クラスには、マニピュレータ関数のアドレスと 1 つの引数の値が入っています。iomanip クラスについては、manip(3C++) のマニュアルページで説明しています。この前の例では、 smanip_int クラスを使用しており、ios で使用できます。ios で使用できるということは、 istream ostream でも使用できるということです。この例ではまた、int 型の第 2 引数を使用しています。

適用子は、クラスオブジェクトを作成してそれを返します。この前の例では、smanip_int というクラスオブジェクトが作成され、そこにマニピュレータと、適用子の int 型引数が入っています。ヘッダーファイル iomanip.h では、このクラスに対するシフト演算子が定義されています。入出力演算子シーケンスの中に適用子関数 setfill があると、その適用子関数が呼び出され、クラスが返されます。シフト演算子はそのクラスに対して働き、クラス内に入っている引数値を使用してマニピュレータ関数が呼び出されます。

下記の例では、マニピュレータ print_hex は次のことを行います。

  1. 出力ストリームを 16 進モードにします。

  2. long 型の値をストリームに挿入します。

  3. ストリームの変換モードを元に戻します。

この例は出力専用のため、omanip_long クラスが使用されています。また、int 型でなく long 型でデータを操作します。

マニピュレータ print_hex


#include <iostream.h>
#include <iomanip.h>
static ostream& xfield(ostream& os, long v) {
        long save = os.setf(ios::hex, ios::basefield);
        os << v;
        os.setf(save, ios::basefield);
        return os;
    }
omanip_long print_hex(long v) {
       return omanip_long(xfield, v);
   }