Pergunta

Eu quero saída de meu próprio objeto para um fluxo STL mas com formatação personalizada. Eu vim com algo assim, mas desde que eu nunca usei local e imbuir antes de eu não tenho idéia se isso faz sentido e como implementar MyFacet e operador <<.

Então, minhas perguntas são: isso faz sentido e como implementar MyFacet e operador <<

?

A seguir é um exemplo simplificado que mostra o que eu quero fazer.

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"
Foi útil?

Solução

Bem, uma localidade é geralmente usada para permitir a saída diferente / formatação do mesmo objecto com base no local de entrada (o local especificado nas fato) de formatação que está presente. Para um bom artigo sobre este see: http://www.cantrip.org/locale.html. Agora, talvez a sua porque o seu exemplo acima é bastante simplificado, mas para mim parece que você está tentando chegar a uma maneira inteligente para alternar entre a impressão de uma parte de um objeto ou de outra. Se for esse o caso, pode ser mais simples basta sobrecarregar o operador de fluxo para cada tipo e usar o interruptor se externamente.

De qualquer forma, eu não vou fingir que sou um especialista em facetas e locais, mas ter um olhar para esse artigo, o seu muito completa e vai lhe dar uma explicação melhor do que eu vou!

Outras dicas

A implementação de seu próprio operador << para rastreamento é geralmente uma boa idéia. No entanto, eu nunca precisei para locais imbuir. No entanto, eu tentei e funcionou muito bem. Aqui está o que eu fiz:

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

Depois de imbuir um local com a faceta:

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

No entanto, uma maneira mais elegante seria implementar diferentes facetas de uma mesma família faceta que pode ser substituído na localidade.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top