smarter enums

P

Peter van Merkerk

Victor said:
Peter said:
Victor said:
Arijit wrote:

[...]
My main gripe is - the the symbolic names for my enum constants are
already in the program - why do I have to write them twice ?
But I guess thats not possible without using macros, and we all
know better than to use them.

Have you ever considered that there are plenty of "symbolic
names" around in the program that are NEVER available for UI
_unless_ you "write them twice"? Class names, variable names,
function names, and so on...

Actually class names are usually available as string via the typeid()
operator. Unfortunately the standard does not specify how that string
should look like; a complying but not very useful implementation could
return just empty strings. So it is really only useful as a debugging
aid.

Well, _usually_ doesn't really cut it, does it?

I don't know why Arijit wants this, so I leave up Arijit to answer this
question.
No guarantees only guarantees absence.

If there are no guarantees, absense is not guaranteed.
Function names are also often available but not
in the form I'd like (I mean that they exist in the OBJ files and in
the shared objects, or DLLs as they are often called, and I _could_
extract them if I wanted to)...

Like I said before other than for debugging purposes I have little or no
need to output identifier names no matter what form they are.
 
O

Old Wolf

My main gripe is - the the symbolic names for my enum constants are
already in the program - why do I have to write them twice ?

/* File e.cc */
#include <iostream>
#include "en.h"
#define WHATEVER
#include "en.h"

int main()
{
std::cout << Red << " = " << (int)Red << '\n';
}


/* File en.h */
#define OP_DEC std::eek:stream &operator<<(std::eek:stream &os, Colours c)

#ifdef WHATEVER
#define E(x) case x: ch = #x; break;
#define EE(x, n) E(x)
OP_DEC
{
char const *ch;
switch(c) {
#else
#define E(x) x,
#define EE(x, n) x = n,
;
enum Colours {
#endif

E(Green)
EE(Red, 3)
E(Blue)
E(Yellow)

#ifdef WHATEVER
default: return os << "Unknown colour " << (int)c;
}
return os << ch;
}
#else
};
OP_DEC;
#endif

#undef E
#undef EE
#undef OP_DEC
 
A

Arijit

Victor Bazarov said:
Arijit said:
[...]
My main gripe is - the the symbolic names for my enum constants are
already in the program - why do I have to write them twice ?
But I guess thats not possible without using macros, and we all
know better than to use them.

Have you ever considered that there are plenty of "symbolic
names" around in the program that are NEVER available for UI
_unless_ you "write them twice"? Class names, variable names,
function names, and so on...

You never need to output the names of your functions or classes
to the user, except, as Peter pointed out, for debugging. And even
in that case its seldom necessary if you have access to a debugger.
But it is quite possible that one might want to print the enum
name directly. For example:

#include <iostream>

using namespace std;

class Box
{
int height;
int width;
int length;

public:
enum color
{ red,green,blue }
clr;

Box(int h,int w,int l,color c):height(h),
width(w),length(l),clr(c)
{}

friend ostream& operator<<(ostream& ostr, Box b)
{
ostr << "Height:" << b.height << endl
<< "Width:" << b.width << endl
<< "Length:" << b.length << endl
<< "Color:" << b.clr << endl;
return ostr;
}
};

int main()
{
Box B(10,20,30,Box::red);
cout << B;

return 0;
}

The simple enum name would suffice in this case.

Writing a function separately is a trivial job, but its quite
monotonous for a large enum with 30-40 or even more elements.

Note that I am not saying that this feature is very useful or
that its absence is a major problem, but it would be nice
to have it. Its like using a calculator to multiply 254 and 382.
Sure I can do it, but the calculator will spare me a little trouble.

-Arijit
 
M

Mark A. Gibbs

i got a lot of replies during my hiatus, but unfortunately, none of them
seem to be thinking the same way as me with regards to what a smarter
enum type would be like.

Victor said:
mostly it prevents the enum member names [...]


Thank you for your explanation and your psychology (and not psychiatry)
lesson (do you know the difference? I probably don't, I only pretend
I do). However, I just wanted to point out that you may have started
with a wrong premise. Enums don't have members.

semantics. whatever you want to call them, i was clearly referring to
the constituent entities of an enumeration.

btw, you were incorrect, psychiatry was the correct term for what i was
doing. and yes, i am quite familiar with the difference. this may aid
you the next time you get confused: if a man says to a psychiatrist, "i
want to kill everyone i know", the psychiatrist will ask him to tell him
more, and in the course of their conversation help the man understand
why he feels so much anger, and help him work it out non-agressively.

if the same man were to say the same thing to a psychologist, the
psychologist would say, "wow, thanks for telling me that", and note it
in his journal.

I don't think that what you're trying to do is worth your time. My
understanding is that you are trying to design an enum that has some minor
added features over a standard enum. Basically, it's an enum that also
gives you the ability to define class functionality, such as methods and
operators.

no, that is incorrect, but that is my fault. i was more concerned with
musing out a potential starting point for a solution than explaining
what i was after. one of the things i am really hoping to prevent is this:

typedef enum { a, b, c } A;
typedef enum { x, y, z } Z;

A foo = a;
Z bar = x;

a == x; // will test true, though it is obviously not

and this:

// foo.hpp
typedef enum { a, b, c } foo_enum;
// changed to typedef enum { a, e, i } foo_enum;

// bar.hpp
typedef enum { d, e, f } bar_enum;
// changed to typedef enum { b, c, d } bar_enum;

// file.cpp
#include "foo.hpp"
#include "bar.hpp"
void func(foo_enum foo)
{
// will break silently with the changes
switch (foo)
{
case c: // it's a c
case b: // it's a b
default: // must be an a
}
}

i am not particularly interested in adding iteration to my enumerations,
and while printing the symbolic names of my enumerations would be nice,
it's not really necessary. really, i'm not interested in adding any
functionality at all - all i'm after is stricter type- and name-safety.
and even then, only in debug compile mode if i have to.

incidently, i had another look at that magazine, and the big trick was:

typedef enum { a, b = 1234, c = 0xFFFFFFFFU } enum_type;

cout << c;
cout << (b > c);

Thomas said:
This has been done before.
Use your favorite search engine and search for
"Dan Saks enumeration". You could also supplement
your search with "Scott Meyers enumeration"
and "Jim Hyslop enumeration". These folks have
worked out the conversion of an enumeration into
a type.

In today's world, your best effort should be spent
researching before designing. If its been done
before, either use it, tailor it, or improve it.

i really hate pointing out the obvious, but if i were going to go do it
all on my own, why would i be here *specifically* asking if anyone has
seen it done before?

as for the links, they may be exactly what i was looking for, but i
couldn't find anything relevant under hyslop or meyers (too much other
crap came up), and saks seemed more concerened with adding iteration to
enumerations, which i am not interested in. does anyone have more
specific information i could use to search? i suspect that hyslop has
dealt with what i'm after (based on his other work), but maybe meyers
has, too.

mark
 
V

Victor Bazarov

Mark said:
i got a lot of replies during my hiatus, but unfortunately, none of them
seem to be thinking the same way as me with regards to what a smarter
enum type would be like.

Victor said:
mostly it prevents the enum member names [...]



Thank you for your explanation and your psychology (and not psychiatry)
lesson (do you know the difference? I probably don't, I only pretend
I do). However, I just wanted to point out that you may have started
with a wrong premise. Enums don't have members.


semantics. whatever you want to call them, i was clearly referring to
the constituent entities of an enumeration.

They are not entities of an enumeration, and that's the whole point.
Each _enumerator_ (yes, that's what they are called) exist in the
same scope as the enumeration they are declared in. It has its own
type, yes. The same type as the other enumerators declared in the
same enum declaration. The difference between enum declarations is
designated by the _name_ of the enumeration.
btw, you were incorrect, psychiatry was the correct term for what i was
doing. and yes, i am quite familiar with the difference. this may aid
you the next time you get confused: if a man says to a psychiatrist, "i
want to kill everyone i know", the psychiatrist will ask him to tell him
more, and in the course of their conversation help the man understand
why he feels so much anger, and help him work it out non-agressively.

if the same man were to say the same thing to a psychologist, the
psychologist would say, "wow, thanks for telling me that", and note it
in his journal.

Nope. The difference is in what they treat and how they treat it.
By mentioning a psychiatrist you implied that low self-esteem is
a mental disease or disorder. By correcting you I implied that low
self-esteem is nothing more than a character trait. Diseases and
disorders are treated by psychiatrists, and treated with medication,
while psychologists help people understand and change character traits.

In most cases psychiatrists are also psychologists, i.e. they can talk
people into or out of something, but the inverse is not true, no
psychologist has a right to prescribe any drugs (unless he/she is also
a medical doctor).
[...] i was more concerned with
musing out a potential starting point for a solution than explaining
what i was after. one of the things i am really hoping to prevent is this:

typedef enum { a, b, c } A;
typedef enum { x, y, z } Z;

A foo = a;
Z bar = x;

a == x; // will test true, though it is obviously not

Why is it not? Both are declared right after the curly brace without
a special initialiser. Both are declared inside an enumeration with
the same name (no name is a unique name). Why shouldn't they compare
equal?

BTW, 'A' and 'Z' here are just two synonyms for the same type.
and this:

// foo.hpp
typedef enum { a, b, c } foo_enum;
// changed to typedef enum { a, e, i } foo_enum;

// bar.hpp
typedef enum { d, e, f } bar_enum;
// changed to typedef enum { b, c, d } bar_enum;

Again, 'foo_enum' and 'bar_enum' are but the same type, only two
different names for it. Drop the 'typedef' nonsense.
// file.cpp
#include "foo.hpp"
#include "bar.hpp"
void func(foo_enum foo)
{
// will break silently with the changes

And you propose that it should say what?
switch (foo)
{
case c: // it's a c
case b: // it's a b
default: // must be an a
}
}
[...]

Perhaps what you're trying to get to is this:

enum ABC { a,b,c };
enum XYZ { x,y,z };

int main()
{
ABC abc = a;
XYZ xyz = y;
return abc == xyz;
}

'abc' and 'xyz' should not just compare non-equal, but an attempt to
compare them should not compile since they are of two different types.

That's not [yet] how the language works. The comparison causes both
values to be promoted to ints. Perhaps they shouldn't, but that's
how it is, and to change that, go to comp.std.c++ and make your case.

BTW, you cannot assign 'xyz' to 'abc', they are of different types.
You can convert between them, though, a static_cast<> is enough.

Introducing a separate type to handle those things the way _you_ want
them handled is just fine. Call them "smart enums", I have no problem
with that. I am still not sure what you mean by "more in line with
the rest of the language", though. Prevention from inserting them
into the surrounding scope is definitely _not_ an improvement. Besides,
how many people have relied on the enumerators being in the scope? I
have no idea, but I'd guess, millions.

Try posting to (and talking to smart people in) comp.std.c++. See what
they say. That's "the rest of the language" crowd. They know more, and
they will pick up on what you are proposing quicker.

Victor
 
M

Mark A. Gibbs

Victor said:
They are not entities of an enumeration, and that's the whole point.
Each _enumerator_ (yes, that's what they are called) exist in the
same scope as the enumeration they are declared in. It has its own
type, yes. The same type as the other enumerators declared in the
same enum declaration. The difference between enum declarations is
designated by the _name_ of the enumeration.

ah, that i didn't realize. that is good to know.
Nope. The difference is in what they treat and how they treat it.
By mentioning a psychiatrist you implied that low self-esteem is
a mental disease or disorder. By correcting you I implied that low
self-esteem is nothing more than a character trait. Diseases and

that was really the point of the joke, that low self-esteem is a DSM4
disorder that should be treated. but i guess it doesn't matter now.
Again, 'foo_enum' and 'bar_enum' are but the same type, only two
different names for it. Drop the 'typedef' nonsense.



And you propose that it should say what?

i don't know, "comparing values of two different types" maybe? (i
realize now that they *are* the same type in the code as i wrote, but
assume that i had declared them properly as different types - the
problem still exists).
switch (foo)
{
case c: // it's a c
case b: // it's a b
default: // must be an a
}
}
[...]


Perhaps what you're trying to get to is this:

enum ABC { a,b,c };
enum XYZ { x,y,z };

int main()
{
ABC abc = a;
XYZ xyz = y;
return abc == xyz;
}

'abc' and 'xyz' should not just compare non-equal, but an attempt to
compare them should not compile since they are of two different types.

and that is one of the things i am trying to accomplish.
That's not [yet] how the language works. The comparison causes both
values to be promoted to ints. Perhaps they shouldn't, but that's
how it is, and to change that, go to comp.std.c++ and make your case.

no no no, i have no interest in changing the language. leave enums be.
what i asked for was a way to create something enum-like with certain
differences (that i referred to as improvements, but of course, you're
free to debate), using the current language. that is definitely the
domain of this group.
BTW, you cannot assign 'xyz' to 'abc', they are of different types.
You can convert between them, though, a static_cast<> is enough.

yes, and that much is good.
Introducing a separate type to handle those things the way _you_ want
them handled is just fine. Call them "smart enums", I have no problem
with that. I am still not sure what you mean by "more in line with
the rest of the language", though. Prevention from inserting them
into the surrounding scope is definitely _not_ an improvement. Besides,
how many people have relied on the enumerators being in the scope? I
have no idea, but I'd guess, millions.

the reason i said more in line with the rest of the language is because
the enum syntax makes a curious departure from the norm. as far as i
know, enum is the only c++ construct that allows you to declare a symbol
within braces, and have that symbol accessible in the surrounding scope,
without qualification. am i wrong?

i don't particularly care how many programmers rely on enumerators being
injected into the surrounding scope - that is not really relevant to
creating a something new, now is it? unless you are suggesting that
there is a good reason to insert enumerators into the surrounding scope,
besides backwards compatibility (which i would consider, but only after
everything else works). if there is, i would like to know it before i do
anything else.
Try posting to (and talking to smart people in) comp.std.c++. See what
they say. That's "the rest of the language" crowd. They know more, and
they will pick up on what you are proposing quicker.

as i mentioned above, i don't want to change the standard. i don't want
to improve enums, i want to make something that is an improved enum.
there are worlds of difference, and they ain't just semantic.

let me try again to specify what i'm trying to do. i am trying to create
some kind of analogue to enum. it would let me define typed symbolic
constants. the only differences between enum and what i would like are:
1.) the option of having no implicit conversion to int
2.) the ability to specify the type of the enumeration
3.) a new scope created for enumerators

and that's all. everything else (iteration, printing symbolic names,
etc.) can come later. you saw my initial attempt to do this with
templates and macros. i had hoped that someone out there has done
something similar already, but if not, i would appreciate some advice on
what i have done so far.

for the record, i have considered static constants already, but a
"static const int" is not the same as an integer constant.

if this is really a complete waste of time, i would like to hear some
arguments as to why. personally, i think this would be a very useful
addition to my programming playbook, especially if there was a simple
way to convert existing enums to the new format.

mark
 
M

Michael D. Borghardt

Hi try reading

Strongly Typed Enums by H. Sutter, D. Miller

http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/n1579.pdf

Mark A. Gibbs said:
i got a lot of replies during my hiatus, but unfortunately, none of them
seem to be thinking the same way as me with regards to what a smarter
enum type would be like.

Victor said:
mostly it prevents the enum member names [...]


Thank you for your explanation and your psychology (and not psychiatry)
lesson (do you know the difference? I probably don't, I only pretend
I do). However, I just wanted to point out that you may have started
with a wrong premise. Enums don't have members.

semantics. whatever you want to call them, i was clearly referring to
the constituent entities of an enumeration.

btw, you were incorrect, psychiatry was the correct term for what i was
doing. and yes, i am quite familiar with the difference. this may aid
you the next time you get confused: if a man says to a psychiatrist, "i
want to kill everyone i know", the psychiatrist will ask him to tell him
more, and in the course of their conversation help the man understand
why he feels so much anger, and help him work it out non-agressively.

if the same man were to say the same thing to a psychologist, the
psychologist would say, "wow, thanks for telling me that", and note it
in his journal.

I don't think that what you're trying to do is worth your time. My
understanding is that you are trying to design an enum that has some minor
added features over a standard enum. Basically, it's an enum that also
gives you the ability to define class functionality, such as methods and
operators.

no, that is incorrect, but that is my fault. i was more concerned with
musing out a potential starting point for a solution than explaining
what i was after. one of the things i am really hoping to prevent is this:

typedef enum { a, b, c } A;
typedef enum { x, y, z } Z;

A foo = a;
Z bar = x;

a == x; // will test true, though it is obviously not

and this:

// foo.hpp
typedef enum { a, b, c } foo_enum;
// changed to typedef enum { a, e, i } foo_enum;

// bar.hpp
typedef enum { d, e, f } bar_enum;
// changed to typedef enum { b, c, d } bar_enum;

// file.cpp
#include "foo.hpp"
#include "bar.hpp"
void func(foo_enum foo)
{
// will break silently with the changes
switch (foo)
{
case c: // it's a c
case b: // it's a b
default: // must be an a
}
}

i am not particularly interested in adding iteration to my enumerations,
and while printing the symbolic names of my enumerations would be nice,
it's not really necessary. really, i'm not interested in adding any
functionality at all - all i'm after is stricter type- and name-safety.
and even then, only in debug compile mode if i have to.

incidently, i had another look at that magazine, and the big trick was:

typedef enum { a, b = 1234, c = 0xFFFFFFFFU } enum_type;

cout << c;
cout << (b > c);

Thomas said:
This has been done before.
Use your favorite search engine and search for
"Dan Saks enumeration". You could also supplement
your search with "Scott Meyers enumeration"
and "Jim Hyslop enumeration". These folks have
worked out the conversion of an enumeration into
a type.

In today's world, your best effort should be spent
researching before designing. If its been done
before, either use it, tailor it, or improve it.

i really hate pointing out the obvious, but if i were going to go do it
all on my own, why would i be here *specifically* asking if anyone has
seen it done before?

as for the links, they may be exactly what i was looking for, but i
couldn't find anything relevant under hyslop or meyers (too much other
crap came up), and saks seemed more concerened with adding iteration to
enumerations, which i am not interested in. does anyone have more
specific information i could use to search? i suspect that hyslop has
dealt with what i'm after (based on his other work), but maybe meyers
has, too.

mark
 
M

Mark A. Gibbs

Michael said:
Hi try reading

Strongly Typed Enums by H. Sutter, D. Miller

http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/n1579.pdf

thank you for the reference. i was aware that something along these
lines was being discussed for standardization, though i have no idea
where it's at. is it likely to be included in any form? looks like it
was planned to be discussed in sydney, but i really don't understand the
whole process *that* well.

so it looks like the only practical way to implement the facilities
discussed in that paper is by use of a method similar to:

class colour
{
public:
enum colour_ { red_, green_, blue_ };

// one for each enumerator
static const colour red;
static const colour green;
static const colour blue;

colour(colour_ c) c_(c) {}

// operator==, member to_int(), etc.

private:
colour_ c_;
};

colour colour::red(colour::red_);
// etc.

i suppose that will have to do for now. thank you for your help everyone.

mark
 

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

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,165
Latest member
JavierBrak
Top