Prev: How unique is the anonymous namespace?
Next: How can I alter how a user-defined type/enum is displayed? (facet/locale?)
From: Lorri on 1 Jul 2010 00:02 Hi folks For a given user-defined type or enum: eg: enum blah { FOO, BAR }; extern std::ostream& operator<<(std::ostream &out, const blah in); extern const char* const prt(const blah in, const bool full = false); How can I alter how the operator<< displays my blah enum? (in some cases I want the full english name, whereas in other cases I want just a single char) At the moment I'm sort of getting what I want by using prt(my_blah, true) or prt(my_blah, false) eg: const char* const prt(const blah in, const bool full) { switch (in) { case FOO: return full ? "FOO" : "F"; case BAR: return full ? "BAR" : "B"; default: break; } return full ? "UNKNOWN" : "?"; } However, for operator<< I can't change how to print my blah enum value. eg: std::ostream& operator<<(std::ostream &out, const blah in) { out << prt(in); return out; } >From what I've read online, I use a facet right? Then I have to imbue the facet into std::ostream's locale or something? I have no idea how to do this. Can someone give me an example of a facet for a user-defined type, and also how you then use it for std::cout or whatever? TIA Steve -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Johannes Schaub (litb) on 2 Jul 2010 05:44 Lorri wrote: > Hi folks > > For a given user-defined type or enum: > > eg: > enum blah > { > FOO, > BAR > }; > extern std::ostream& operator<<(std::ostream &out, const blah in); > extern const char* const prt(const blah in, const bool full = false); > > How can I alter how the operator<< displays my blah enum? (in some > cases I want the full english name, whereas in other cases I want just > a single char) > > At the moment I'm sort of getting what I want by using prt(my_blah, > true) or prt(my_blah, false) > eg: > const char* const prt(const blah in, const bool full) > { > switch (in) > { > case FOO: return full ? "FOO" : "F"; > case BAR: return full ? "BAR" : "B"; > default: break; > } > return full ? "UNKNOWN" : "?"; > } > > However, for operator<< I can't change how to print my blah enum > value. > > eg: > std::ostream& operator<<(std::ostream &out, const blah in) > { > out << prt(in); > return out; > } > >>From what I've read online, I use a facet right? Then I have to imbue > the facet into std::ostream's locale or something? I have no idea how > to do this. > > Can someone give me an example of a facet for a user-defined type, and > also how you then use it for std::cout or whatever? > This doesn't need a facet - it however needs a way to store state in the streams. Here is an example: http://stackoverflow.com/questions/799599/c- custom-stream-manipulator-that-changes-next-item-on-stream/799877#799877 . You can test for the flag using "f.iword(geti())" in your operator<<. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 2 Jul 2010 06:08
On 1 Jul., 17:02, Lorri <steve.lori...(a)gmail.com> wrote: > For a given user-defined type or enum: > > eg: > enum blah > { > FOO, > BAR}; > > extern std::ostream& operator<<(std::ostream &out, const blah in); > extern const char* const prt(const blah in, const bool full = false); > > How can I alter how the operator<< displays my blah enum? (in some > cases I want the full english name, whereas in other cases I want just > a single char) > > At the moment I'm sort of getting what I want by using prt(my_blah, > true) or prt(my_blah, false) > eg: > const char* const prt(const blah in, const bool full) > { > switch (in) > { > case FOO: return full ? "FOO" : "F"; > case BAR: return full ? "BAR" : "B"; > default: break; > } > return full ? "UNKNOWN" : "?"; > } > > However, for operator<< I can't change how to print my blah enum > value. > > eg: > std::ostream& operator<<(std::ostream &out, const blah in) > { > out << prt(in); > return out; > > } > >From what I've read online, I use a facet right? Then I have to imbue > > the facet into std::ostream's locale or something? I have no idea how > to do this. > > Can someone give me an example of a facet for a user-defined type, and > also how you then use it for std::cout or whatever? First, your use-case description makes rather clear, that you don't want to define a facet. Facets are used to express locale-specific differences, but that is not what you describe. What you want is so-called manipulator. Manipulators are helper types that introduce an indirection between a type and it's output (or input) format. To realize a manipulator, you will typically define a helper type which is opaque for the user and a helper function or functor that creates the helper type. In your example it would be very easy to start with something like this: // Helper type struct blah_manip_t { blah value; const char* foo_name; const char* bar_name; const char* err_name; blah_manip_t(blah value, const char* foo_name, const char* bar_name, const char* err_name) : value(value), foo_name(foo_name), bar_name(bar_name), err_name(err_name) {} }; std::ostream& operator<<(std::ostream &out, blah_manip_t in) { switch (in.value) { case FOO: out << in.foo_name; break; case BAR: out << in.bar_name; break; default: out << in.err_name; break; } return out; } blah_manip_t full(blah value) { return blah_manip_t(value, "FOO", "BAR", "UNKNOWN"); } blah_manip_t short(blah value) { return blah_manip_t(value, "F", "B", "?"); } // Usage: int main() { blah val = ...; std::cout << full(val) << " - " << short(val); } If you want to provide some default output, that is very easy: std::ostream& operator<<(std::ostream &out, blah in) { // Default output is full format: return out << full(in); } More advanced ideas are possible, especially, if your enum has much more enumerators, e.g. take advantage of polymorphic manipulators: class blah_manip_base_t { blah value; public: explicit blah_manip_base_t(blah value) : value(value) {} blah get_value() const { return value; } virtual ~blah_manip_base_t(){} virtual std::string get_name(blah) const = 0; }; and define std::ostream& operator<<(std::ostream &out, const blah_manip_base_t& in) { return out << in.get_name(in.value()); } Or, if you want to reuse your approach via an existing output function, you could keep a function pointer as state within the manipulator, etc.. The last example just reuses your existing function prt within a manipulator: // Helper type struct blah_manip_2_t { blah value; bool full; blah_manip_2_t(blah value, bool full) : value(value), full(full) {} }; std::ostream& operator<<(std::ostream& out, blah_manip_2_t in) { return out << prt(in.value, in.full); } blah_manip_2_t full(blah value) { return blah_manip_2_t(value, true); } blah_manip_2_t short(blah value) { return blah_manip_2_t(value, false); } HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |