ロケールオブジェクトは、コンテナやマップのようなものですが、正確に処理するために、コンパイル時に型によってインデックス付けされます。そのため、インデックス演算子は演算子 [] ではなく、テンプレート演算子 <> を使用します。ロケールオブジェクトのファセットオブジェクトにアクセスするには、2 つのメンバー関数テンプレート use_facet と has_facet を使用します。
template <class Facet> const Facet& use_facet(const locale&); template <class Facet> bool has_facet(const locale&);
以下のコードは、その使用方法を示したものです。これは ctype ファセットの利用方法の例です。文字列の中で、標準入力ストリームから読み取った文字列の大文字は小文字に変換され、標準出力ストリームに書き込まれます。
string in; cin >> in; if (has_facet< ctype<char> >(locale())) //1 { cout << use_facet< ctype<char> >(locale()) //2 .tolower(in.begin(),in.end()); //3 }
//1 | has_facet<...>() に対する呼び出しで、テンプレート引数により基底ファセットクラスを指定します。ロケールオブジェクトにこの型のファセットがない場合は、偽が返ります。 |
//2 | 関数テンプレート use_facet<>() は、指定した基底ファセット型のロケールのファセットオブジェクトを返します。ロケールオブジェクトは不変なので、このロケールオブジェクトの寿命が続く限り参照は有効です。指定した型のファセットがロケールにない場合は、use_facet により runtime_error 例外の送出が返ります。 |
//3 | ファセットオブジェクトのメンバー関数 tolower() を呼び出します。これは C 関数 tolower() の機能です。文字列の大文字をすべて小文字に変換します。 |
この例では、ctype<char> は標準ファセットなので、has_facet に対する呼び出しは実際には必要ありません。各ロケールには、常に標準ファセットがすべて含まれるため、has_facet<ctype<char> > では常に true が返ります。ただし、has_facet() に対する呼び出しは、この章で前述した mythical ファセットなど、すべてのロケールにあるとは限らない非標準ファセットの処理に有用です。
use_facet 呼び出しと has_facet 呼び出しのコーディングでは、テンプレートパラメータのファセット型には、必ず基底ファセット型を指定してください。派生ファセット型は指定しないでください。次のコードはエラーになります。
locale loc; const numpunct_byname<char> &np = // エラー、基底ファセット型ではなく use_facet<numpunct_byname<char> >(loc); // インスタンス化された // use_facet
ファセット型や使用するコンパイラにもよって異なりますが、このコードは、おそらくコンパイル時エラーになります。エラーにならない場合には、予想外の実行時動作が発生することがあります。use_facet 呼び出しでは、numpunct_byname<char> 型 のスロットを占めるファセットが返ります。しかし、実際には先にも説明たように、これは基底ファセット型 numpunct<char> のスロットの場合も同じです。したがって、上記のコードでは、np は、実際には型が numpunct_byname<char> ではないオブジェクトに対する参照として初期化されます。
このようなエラーを防ぐには、 use_facet と has_face だけを基底ファセット型で、すなわち、静的 locale::id メンバーを含むファセット型でインスタンス化してください。
locale loc; const numpunct<char> &np = // 正しい use_facet<numpunct<char> >(loc);
Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。
OEM リリース, 1998 年 6 月