Domanda

Voglio uscita il mio oggetto in un flusso di STL, ma con la formattazione personalizzata. Sono venuto con qualcosa di simile, ma dal momento che non ho mai usato locale e infondere prima che io ho idea se questo ha un senso e come implementare MyFacet e l'operatore <<.

Quindi le mie domande sono le seguenti: Ha senso e come implementare MyFacet e l'operatore <<

?

Il seguente è un esempio semplificato che mostra quello che voglio fare.

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"
È stato utile?

Soluzione

Bene, un locale viene generalmente utilizzato per consentire differente formattazione uscita / ingresso dello stesso oggetto basato sulla formattazione locale (il locale specificato appunto) che è presente. Per un buon articolo su questo vedi: http://www.cantrip.org/locale.html. Ora forse è perché il vostro esempio di cui sopra è molto semplificata, ma a me sembra che si sta cercando di trovare un modo intelligente per passare tra la stampa di una parte di un oggetto o di un altro. Se questo è il caso potrebbe essere più semplice si limitano a sovraccaricare l'operatore flusso per ciascun tipo e utilizzare l'interruttore se esternamente.

In ogni caso, non ho intenzione di far finta che io sia un esperto di sfaccettature e locali, ma dare un'occhiata a questo articolo, la sua abbastanza approfondita e vi darà una spiegazione migliore di quanto lo farò!

Altri suggerimenti

L'implementazione il proprio operatore << per il tracciato è generalmente una buona idea. Tuttavia non ho mai avuto bisogno di infondere locali. Comunque ho provato e ha funzionato bene. Ecco quello che ho fatto:

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;
}

Poi, per infondere un locale con la faccetta:

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

Tuttavia un modo più elegante sarebbe quello di implementare diverse sfaccettature di una stessa famiglia aspetto che può essere sostituito nel locale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top