comp.lang.c++ / C++ user community


T

tony_in_da_uk

I'm trying to get my head around this:

- Someone could post on here "how do I stream the symbolic identifier
associated with an enum?" and 20 people would leap on it merrily
saying "you can't", or proposing arcane, inconvenient hacks. Then go
on to discuss whether a semicolon or a comma is more appropriate at
some point in a footnote in the Standard.

- I say, "hey, here's a trick so you can say `ENUM(Colour, Red = 4,
Green = 39, Blue = Red|Green);' then "cout << some_colour;" will
actually print the identifier, and _nobody cares_. Not the people
who've been asking. Not the people who've been answering.

Despite having spent hundreds of hours answering questions on this
forum, I've lost my belief that the C++ "community" is worth providing
answers for... ...not that I expect anybody to care. So... goodbye.

Tony
 
Ad

Advertisements

Z

Zeppe

- Someone could post on here "how do I stream the symbolic identifier
associated with an enum?" and 20 people would leap on it merrily
saying "you can't", or proposing arcane, inconvenient hacks. Then go
on to discuss whether a semicolon or a comma is more appropriate at
some point in a footnote in the Standard.

Probably it's because you can't.
- I say, "hey, here's a trick so you can say `ENUM(Colour, Red = 4,
Green = 39, Blue = Red|Green);' then "cout << some_colour;" will
actually print the identifier, and _nobody cares_. Not the people
who've been asking. Not the people who've been answering.

Probably because it's a macro-workaround and not what intended in the
original question "how do I stream the symbolic identifier associated
with an enum", whose correct answer is "you can't". It's plenty of these
macro facilities in different libraries out there.
Despite having spent hundreds of hours answering questions on this
forum, I've lost my belief that the C++ "community" is worth providing
answers for... ...not that I expect anybody to care. So... goodbye.

We don't deserve you. Good luck.

Best wishes,

Zeppe
 
J

James Kanze

Probably it's because you can't.

You can't is pretty strong language. The standard doesn't
forbid extensions, so you could always write your own C++
compiler, with some sort of support for this as an extension.
(Let us know when you're finished.) Short of that, of course...
Probably because it's a macro-workaround and not what intended
in the original question "how do I stream the symbolic
identifier associated with an enum", whose correct answer is
"you can't". It's plenty of these macro facilities in
different libraries out there.

Yes, it's an ugly hack that no one would want to use. The
solution is a modified compiler, or failing that, an external
program which parses C++ and generates whatever is needed.

There's one at my site (kanze.james.neuf.fr/code-en.html -- the
program is called enumgen), for those who are interested,
although it's an early version, which generates code which
requires the use of my library (mainly Fallible). The version I
use has options for the generated code: returns Fallible,
returns a pointer, just generates an std::map (which means
dynamic initialization, rather than static), or uses a user
provided template (in the general English sense, not a C++
template). It also supports a number of transformations on the
symbolic name, which can be useful in specific contexts. (It
also can be used to generate an iterator over the enum, ++ and
-- operators or |, |=, & and &= operators.)

Of course, if you're not interested, I'm not going to cry about
it either. It's there, for those who are interested, and that's
it. (The up to date version will be uploaded one of these days.
Once I get things working under Windows again.)
 
C

coal

Probably it's because you can't.


Probably because it's a macro-workaround and not what intended in the
original question "how do I stream the symbolic identifier associated
with an enum", whose correct answer is "you can't". It's plenty of these
macro facilities in different libraries out there.

Right. I think what Kanze proposes is better but I'm not inclined
to use it either at this point.



It is a tough road developing useful software products and one
shouldn't
get discouraged by periods of rejection or apathy. Keep plugging and
eventually something you hope for will result. Also I don't
recommend
leaving unless you have some idea of where you are heading. The C++
community may have some problems, but I think others do as well.
In your particular case I think you have a lot of talent and some
interesting ideas.


Brian Wood
http://webEbenezer.net

"All the world is just a narrow bridge. The most important
thing is not to be afraid." Rebbe Nachman
 
Z

Zeppe

James said:
You can't is pretty strong language. The standard doesn't
forbid extensions, so you could always write your own C++
compiler, with some sort of support for this as an extension.
(Let us know when you're finished.) Short of that, of course...

Unfortunately in this case the effect is to have code that depends on a
specific compiler or utility, that is not guarantee to be portable and
makes the generation of code and the compliance to the good-practice of
"one-click build" rather complex. I'd prefer to avoid, sincerely.

My solution is, if you don't have thousands of enum to print, just to
provide for each enum two helper functions operator<< and operator>>,
that can be called explicitely or implicitely via a template

template <typename T>
std::string toString(const T& t)
{
std::eek:stringstream oss;
oss << t;
return oss.str();
}

and

template <typename T>
T stringTo(const std::string& s)
{
T t; // requires default empty constructor
std::isstringstream iss(s);
iss >> t;
return t;
}

The resulting code is very easy to read and not too slow to produce
(even though, I agree, much of it could be avoided).

Best wishes,

Zeppe
 
J

James Kanze

Unfortunately in this case the effect is to have code that
depends on a specific compiler or utility, that is not
guarantee to be portable and makes the generation of code and
the compliance to the good-practice of "one-click build"
rather complex. I'd prefer to avoid, sincerely.

My suggestion was meant more or less humoristically. If you're
capable of writing a complete C++ compiler in a reasonable time
for most projects, you don't need any suggestions from me.
Implementing things like templates just so you can output a
couple of enum values is not really the most efficient use of
your time.
My solution is, if you don't have thousands of enum to print,
just to provide for each enum two helper functions operator<<
and operator>>, that can be called explicitely or implicitely
via a template
template <typename T>
std::string toString(const T& t)
{
std::eek:stringstream oss;
oss << t;
return oss.str();
}

template <typename T>
T stringTo(const std::string& s)
{
T t; // requires default empty constructor
std::isstringstream iss(s);
iss >> t;
return t;
}
The resulting code is very easy to read and not too slow to produce
(even though, I agree, much of it could be avoided).

Well, I do practically the opposite: I provide toString and
fromString functions. Generated automatically, of course; no
point it writing this all out by hand yourself.
 
Ad

Advertisements

Z

Zeppe

James said:
Well, I do practically the opposite: I provide toString and
fromString functions. Generated automatically, of course; no
point it writing this all out by hand yourself.

Ah! Now everything's clear! I though you were suggesting scripts that
acted as a sort of pre-preprocessor of the code, rather than a one-shot
utility to copy and paste automatically generated code into your source
files. Right then, I agree with your approach!

On whether to automate operator<< or toString, I'd say no much
difference is involved. Maybe providing operator<< you may have more
freedom while using custom streambuffers or things like that, and avoid
a double conversion when using formatted output.

Best wishes,

Zeppe
 
J

James Kanze

Ah! Now everything's clear! I though you were suggesting scripts that
acted as a sort of pre-preprocessor of the code, rather than a one-shot
utility to copy and paste automatically generated code into your source
files. Right then, I agree with your approach!

No copy/paste, even. Given a file Toto.hh, with an enum (or
more than one) in it, the program generates two files,
TotoMap.hh and TotoMap.cc, with mappings for all of the enum's
in Toto.hh. The current version (not the one on line) supports
various ways to implement the mappings, and various ways of
transforming the strings.
On whether to automate operator<< or toString, I'd say no much
difference is involved.

Very little, in fact. My choice of toString and fromString is
probably more because of historical considerations. (An option
Maybe providing operator<< you may have more freedom while
using custom streambuffers or things like that, and avoid a
double conversion when using formatted output.

That's a possibility. You could probably design it so that
various mappings could be controlled by manipulators, as well.
On the other hand, the basics of my implementation are just a
char const* const[], which does have the advantage of
simplicity; the toString and fromString functions are only a
couple of lines. (One of the options uses std::map, but
generally speaking, I prefer the char const* const[], because it
uses static initialization, and is thus free from order of
initialization issues. And I really can't imagine an enum with
enough values so that the cost of a linear search is
unacceptable.)
 
Ad

Advertisements

T

tony_in_da_uk

Right. I think what Kanze proposes is better but I'm not inclined
to use it either at this point.

There are plenty of other macro hacks, and if I knew of one that
provided equivalent convenience , correctness, and approximation of
real enum declaration notation, then I wouldn't expect much interest
in BENUM. AFAIK, BENUM is the first to:

- requiring an #include but no changes to the build process
- correctly capturing arbitrary enumeration values (i.e. not just
default/incrementing)
- needing no additional manual per-enum support code
- not need every single enumeration identifier/value wrapped in an
additional macro
- allow annotations for modeling masks, bit-flags and disambiguating
desired streaming output

To my mind, that's a new level of usability.
It is a tough road developing useful software products and one
shouldn't
get discouraged by periods of rejection or apathy. Keep plugging and
eventually something you hope for will result. Also I don't
recommend
leaving unless you have some idea of where you are heading. The C++
community may have some problems, but I think others do as well.
In your particular case I think you have a lot of talent and some
interesting ideas.

Brian Wood http://webEbenezer.net

Thanks for the encouragement, Brian. I don't have any answers re
"where...heading". I guess I'll try to push BENUM through Boost
review, possibly adding support for inheritance and additional values
- mentioned by some colleagues.

More importantly to me, my rewritten introspective preprocessor is now
functional and can easily generate code like enum streaming
functions. While a dedicated enum-streaming-only preprocessor is
rarely worth the effort of deployment, I believe generalised tools
will soon precipitate a major shift in common enterprise-level C++
usage. But then, perhaps I'll be surprised again by a similar lack of
interest... *shrug*.

Regards,
Tony
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top