3

独自のオブジェクトを STL ストリームに出力したいのですが、フォーマットはカスタマイズされています。私はこのようなものを思いつきましたが、ロケールとインビューを使用したことがないので、これが理にかなっているかどうか、MyFacet と operator<< を実装する方法がわかりません。

私の質問は次のとおりです:これは理にかなっていますか? MyFacet と operator<< を実装する方法は?

以下は、私がやりたいことを示す簡単な例です。

struct MyObject
{
  int i;
  std::string s;
};

std::ostream &operator<<(std::ostream &os, const MyObject &obj)
{
    if (????)
    {
        os << obj.i;
    }
    else
    {
        os << obj.s;
    }
}

MyObject o;
o.i = 1;
o.s = "hello";

std::cout.imbue(locale("", new MyFacet(MyFacet::UseInt)));
std::cout << o << std::endl;    // prints "1"

std::cout.imbue(locale("", new MyFacet(MyFacet::UseString)));
std::cout << o << std::endl;    // prints "hello"
4

2 に答える 2

4

トレース用に独自の演算子 << を実装することは、一般的には良い考えです。ただし、ロケールを吹き込む必要はありません。しかし、私はそれを試してみましたが、うまくいきました。これが私がしたことです:

class my_facet : public std::locale::facet
{
public:
    enum option{
        use_string,
        use_numeric
    };
    //Unique id for facet family, no locale can contain two
    //facets with same id.
    static std::locale::id id; 
    my_facet(option o=use_numeric):
    facet(0),
        _option(o)
    {//Initialize reference count to zero so that the memory
     //management will be handled by locale
    };
    option get_option() const {return _option;};
protected:
    option _option;
};
std::locale::id my_facet::id(123456); //Facet family unique id

std::ostream& operator<<(std::ostream& os, const myobj& o)
{
    std::locale const& l = os.getloc();
    if( std::has_facet<my_facet>(l) ){
        my_facet const& f =  std::use_facet<my_facet>(l);
        switch(f.get_option()){
        case my_facet::use_numeric:
            os << "Using numeric! ";
            break;
        case my_facet::use_string:
            os << "Using string! ";
            break;
        default:
            os << "Unhandled case.. ";
            break;
        }
        return os;
    }
    os << "Default case when no facet has been set";
    return os;
}

次に、ロケールにファセットを吹き込みます。

std::locale mylocale(locale("US"), new my_facet(my_facet::use_numeric));
std::cout.imbue(mylocale);

ただし、より洗練された方法は、同じファセット ファミリのさまざまなファセットを実装して、ロケールで置き換えることです。

于 2009-07-08T07:12:38.890 に答える
1

ロケールは一般に、存在するローカル (実際には指定されたロケール) の書式設定に基づいて、同じオブジェクトの異なる出力/入力書式設定を許可するために使用されます。これに関する優れた記事については、http: //www.cantrip.org/locale.htmlを参照してください。上記の例が非常に単純化されているためかもしれませんが、私には、オブジェクトの一部を印刷するか別の部分を印刷するかを切り替える賢い方法を考え出そうとしているように見えます。その場合は、タイプごとにストリーム演算子をオーバーロードし、外部で if スイッチを使用する方が簡単かもしれません。

とにかく、私がファセットとロケールの専門家であるふりをするつもりはありませんが、その記事を見てください。かなり徹底的で、私よりも優れた説明を提供します!

于 2009-07-08T06:15:07.710 に答える