## 4.3 ロケールのファセットへのアクセス

ロケールオブジェクトは、コンテナやマップのようなものですが、正確に処理するために、コンパイル時に型によってインデックス付けされます。そのため、インデックス演算子は演算子 [] ではなく、テンプレート演算子 <> を使用します。ロケールオブジェクトのファセットオブジェクトにアクセスするには、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 月