マニュアルページ manip.3
名前
manip - 入出力ストリーム用マニピュレータ
形式
#include <iostream.h>
#include <iomanip.h>
#define IOMANIPdeclare(typ) 以下の定義に展開 ...
class SMANIP(typ) {
public:
SMANIP(typ)(ios& (*)(ios&, typ), typ);
friend istream& operator>>(istream&, SMANIP(typ)&);
friend ostream& operator<<(ostream&, SMANIP(typ)&);
};
class SAPP(typ) {
public:
SAPP(typ)(ios& (*)(ios&, typ));
SMANIP(typ) operator()(typ);
};
class IMANIP(typ) {
public:
IMANIP(typ)(istream& (*)(istream&, typ), typ);
friend istream& operator>>(istream&, IMANIP(typ)&);
};
class IAPP(typ) {
public:
IAPP(typ)(istream& (*)(istream&, typ));
IMANIP(typ) operator()(typ);
};
class OMANIP(typ) {
public:
OMANIP(typ)(ostream& (*)(ostream&, typ), typ);
friend ostream& operator<<(ostream&, OMANIP(typ)&);
};
class OAPP(typ) {
public:
OAPP(typ)(ostream& (*)(ostream&, typ));
OMANIP(typ) operator()(typ);
};
class IOMANIP(typ) {
public:
IOMANIP(typ)(iostream& (*)(iostream&, typ), typ);
friend istream& operator>>(iostream&, IOMANIP(typ)&);
friend ostream& operator<<(iostream&, IOMANIP(typ)&);
};
class IOAPP(typ) {
public:
IOAPP(typ)(iostream& (*)(iostream&, typ));
IOMANIP(typ) operator()(typ);
};
IOMANIPdeclare(int);
IOMANIPdeclare(long);
smanip_long resetiosflags(long);
smanip_int setbase(int);
smanip_int setfill(int);
smanip_long setiosflags(long);
smanip_int setprecision(int);
smanip_int setw(int);
機能説明
「マニピュレータ」は外見上、ストリームに挿入されたオブジェク
ト、またはストリームから抽出されたオブジェクトのように見えま
す。しかし、その多くはストリームの状態を変更するだけです。マ
ニピュレータの実際の目的は、挿入シーケンスや抽出シーケンスに
組み込むことで関数呼び出しによって行う操作を簡略化することに
あります。たとえば、次のようなコードがあるとします。
cout.width(8);
cout << val1 << " ";
cout.width(4);
cout << val2 << '\n';
cout.flush();
このコードは次のように変更できます :
cout << setw(8) << val1 <<
ios(3CC4)、 istream(3CC4)、 ostream(3CC4) で説明されているよ
う な定義済みのマニピュレータがいくつかあります。 flush や上
の例の endl などは、引数を持たない簡単なものです。上の 例 の
setw のようなマニピュレータは引数を持ちます。ヘッダファイル
<iomanip.h> には、このようなマニピュレータのいくつかが定義さ
れているほか、プログラマが独自のマニピュレータを作成するのに
必要な定義が含まれています。
論理上、マニピュレータはテンプレートとして定義されま す が、
C++ 言 語では、テンプレートが利用可能になる前に導入されまし
た。したがって、マニピュレータはテンプレートをシミュレートす
る マクロとして定義されます。マクロ IOMANIPdeclare(typ) は、
typ 型の引数を持つマニピュレータのすべての定義に展開さ れ ま
す。マクロの性質上、型を指定するパラメタは単純な型名 (識別子
だけ) であることが必要です。ヘッダには、 int 型およ び long
型の展開された定義が含まれています。
パラメタを持たない
マニピュレータ
引数を持たないマニピュレータは、「ストリームへの参照」型の引
数 を 1 つ持つ関数で、同じ型の値を返します。ストリームには、
そのような関数をパラメタに持つ多重定義演算子があらかじめ定義
されています。マニピュレータは、ストリーム引数で必要なすべて
の操作を行い、同じストリームを返します。たとえば、マ ニ ピュ
レータ tab のコードは次のようになります。
ostream& tab(ostream& s)
{
s << '\t';
return s;
}
式 cout<<tab の中で、多重定義された演算子
ostream& operator<< (ostream& (*)(ostream&))
が選択され、マニピュレータ関数を呼び出します。呼び出されたマ
ニ ピュレータは、出力ストリーム (ostream) にタブ文字を挿入し
ます。
パラメタを持つ
マニピュレータ
パラメタを持つマニピュレータは、2 つの部分から構成されます。
- 操作部 : ストリームと引数 typ から、そのストリームを返 す
関数。
- 適用部 : 操作部によって呼び出される関数で、状態の変更や他
の操作を適用します。
指定された型 typ に対し、マクロ IOMANIPdeclare によってす べ
て の 部分が宣言されます。これについて、以下で詳しく説明しま
す。
以下の説明では、次の宣言を想定しています。
typ - 何らかの型名
n - int 型
l - long 型
s - ios 型
i - istream 型
o - ostream 型
io - iostream 型
f - ios& (*) (ios&) 型
if - istream& (*) (istream&) 型
of - ostream& (*) (ostream&) 型
iof - iostream& (*) (iostream&) 型
s << SMANIP(typ)(f, t)
s << SAPP(typ)(f)(t)
s >> SMANIP(typ)(f, t)
s >> SAPP(typ)(f)(t)
f(s,t) を返します。ストリーム s は、他のストリーム型 (
i 、 o 、 io ) のいずれかになることがあります。
i >> IMANIP(typ)(if, t)
i >> IAPP(typ)(if)(t)
if(i,t) を返します。
o << OMANIP(typ)(of, t)
o << OAPP(typ)(of)(t)
of(o,t) を返します。
io << IOMANIP(typ)(iof, t)
io << IOAPP(typ)(iof)(t)
io >> IOMANIP(typ)(iof, t)
io >> IOAPP(typ)(iof)(t)
iof(io,t) を返します。
ヘッダ <iomanip.h> には、 int 型または long 型の引数 (上記の
typ を持つマニピュレータの定義が含まれています。定義済みのマ
ニピュレータはすべて、次のようにストリームの状態を変更するた
めに使用されます。
o << setw(n)
i >> setw(n)
ストリーム i または o のフィールド幅を n に設定します。
次の書式つき挿入または抽出では、この幅が 0 に再設定され
るので注意が必要です。
o << setfill(n)
i >> setfill(n)
ストリーム i または o のパディング文字を n に設定 し ま
す。
o << setprecision(n)
i >> setprecision(n)
ストリーム i または o の精度変数 (小数部の有効桁数) を
n に設定します。
o << setiosflags(l)
i >> setiosflags(l)
ストリーム i または o の ios フラグのうち、 l でセッ ト
されているビットに対応するものをオンにします。
o << resetiosflags(l)
i >> resetiosflags(l)
ストリーム i または o の ios フラグのうち、 l でセッ ト
されているビットに対応するものをオフにします。
引数を持つマニピュレータを独自に作成するには、まず「操作」関
数を宣言した後、「操作」関数と「適用」関数の両方を実装する必
要があります。マニピュレータが typ 型の引数を持つようにす る
には、同じ型の引数を 1 つ持ち、 X manip_typ 型のオブジェクト
を返す「操作」関数を宣言する必要があります。ここで、操作しよ
う とするオブジェクトの型が ios、istream、 ostream、iostream
である場合にはそれぞれ、 X を s、i、 o、io に置き換えてく だ
さ い。 また、 typ は実際の型名に置き換えます。 int 型または
long 型の場合、すべての宣言はすでに整えられています。他の 型
の場合は、「テンプレート」である IOMANIPdeclare ( typ ) を呼
び出す必要があります。
適用関数は操作関数からしか呼び出されないため、通常は静的にし
ます。適用関数は、操作対象のストリームの型への参照を返し、同
じ型を第 1 パラメタに持ち、型 typ を第 2 パラメタに持つよ う
に定義してください。
例として、 setiosflags というマニピュレータを考えます。こ の
マ ニピュレータは ios 上で動作し、 long 型の引数を持つため、
smanip_long 型の値を返すように宣言されています。このパラメタ
が ostream 上で動作し、 int 型のパラメタを持つのであれば、
omanip_int 型の値を返すように宣言されます。したがって、こ の
パラメタ (操作関数) は、ヘッダで次のように宣言されています。
smanip_long setiosflags(long);
適用関数はユーザーコードから直接呼び出されることはないため、
ヘッダには宣言されません。実装モジュールでは、これらの関数の
コードは次のようになっています。
// b に設定されているビットに従ってフラグ bitvector を設定
static ios& sios(ios& i, long b) // 非公開適用関数
{
i.setf(b);
return i;
}
smanip_long setiosflags(long b) // 公開操作関数
{
return smanip_long(sios, b);
}
関連項目
ios.intro(3CC4)、 ios(3CC4)、 istream(3CC4)、
ostream(3CC4)、『C++ ライブラリ・リファレンスマニュアル』の
第 3 章「iostream ライブラリ」