From: Lorri on
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
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
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! ]