473,387 Members | 3,810 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

enum is poorly defined

"The C++ Programming Language" by Bjarne Stroustrup, copyright 1997 by AT&T,
section 4.8 (pp 77):
"A value of integral type may be explicitly converted to an enumeration
type. The result of such a conversion is undefined unless the value is
within the range of the enumeration. For example:
enum flag { x=1, y=2, z=4, e=8 }; // range 0:15
flag f1 = 5; // type error: 5 is not of type flag
flag f2 = flag(5); // ok: flag(5) is of type flag and withing the range of
flag"

C++ Draft 2, December 1996, Section 7.2.9:
"An expression of arithmetic or enumeration type can be converted to an
enumeration type explicitly. The value is unchanged if it is in the range of
enumeration values of the enumeration type; otherwise the resulting
enumeration value is unspecified."

In both of these old references, an explicit conversion from integer (or
another enumeration) to an enumeration is allowed as long as the value falls
within the range of the enumeration. The first text even offers up the
obvious bug, and states that this is ok!

Consider what we are representing with an enumeration: At first glance, it
appears to be a set, useful for categorizing/subdividing some domain, with
the implicit purpose of later performing a switch/case or (less optimally)
if/then against the categories.

However,

enum TEST_T {FIRST = 0, SECOND = 0, THIRD = 100};
TEST_T eTest = FIRST, eSecondTest = SECOND;

if ( eTest == SECOND ){
cout << "faulty logic!" << endl;
}
if( eTest == eSecondTest ){
cout << "more confusion" << endl;
}

int iTest = 5;
eTest = (TEST_T) iTest; // which comes to what?
switch (eTest){
case FIRST:
case SECOND: // compiler catches what?: Duplicate case value
case THIRD:
cout << "success" << endl;
break;
default:
cout << "switch failure" << endl;
}

As you can see, several disasterous thinking processes are opened up.

Firstly, it doesn't seem to be in line with the mathematical concept of an
unordered set, nor does it seem to be a strictly ordered set, due to
duplicate values--which cause serious problems. Furthermore, explicit
conversion to an enumeration is allowed without having anything to do with
members of that enumeration! That's just absurd.

A tighter definition of what we are talking about when we refer to an
enumeration is in order, and thus I ask you, the programming world: What is
an enumeration?
Jul 22 '05 #1
9 3109
"AngleWyrm" <no***************@hotmail.com> wrote...
"The C++ Programming Language" by Bjarne Stroustrup, copyright 1997 by AT&T, section 4.8 (pp 77):
"A value of integral type may be explicitly converted to an enumeration
type. The result of such a conversion is undefined unless the value is
within the range of the enumeration. For example:
enum flag { x=1, y=2, z=4, e=8 }; // range 0:15
flag f1 = 5; // type error: 5 is not of type flag
flag f2 = flag(5); // ok: flag(5) is of type flag and withing the range of
flag"

C++ Draft 2, December 1996, Section 7.2.9:
"An expression of arithmetic or enumeration type can be converted to an
enumeration type explicitly. The value is unchanged if it is in the range of enumeration values of the enumeration type; otherwise the resulting
enumeration value is unspecified."

In both of these old references, an explicit conversion from integer (or
another enumeration) to an enumeration is allowed as long as the value falls within the range of the enumeration. The first text even offers up the
obvious bug, and states that this is ok!

Consider what we are representing with an enumeration: At first glance, it
appears to be a set, useful for categorizing/subdividing some domain, with
the implicit purpose of later performing a switch/case or (less optimally)
if/then against the categories.

However,

enum TEST_T {FIRST = 0, SECOND = 0, THIRD = 100};
TEST_T eTest = FIRST, eSecondTest = SECOND;

if ( eTest == SECOND ){
cout << "faulty logic!" << endl;
}
if( eTest == eSecondTest ){
cout << "more confusion" << endl;
}

int iTest = 5;
eTest = (TEST_T) iTest; // which comes to what?
switch (eTest){
case FIRST:
case SECOND: // compiler catches what?: Duplicate case value
case THIRD:
cout << "success" << endl;
break;
default:
cout << "switch failure" << endl;
}

As you can see, several disasterous thinking processes are opened up.

Firstly, it doesn't seem to be in line with the mathematical concept of an
unordered set,
No. Who claimed it was supposed to?
nor does it seem to be a strictly ordered set,
Of course not. It's just a separate type with named constants.
due to
duplicate values--which cause serious problems. Furthermore, explicit
conversion to an enumeration is allowed without having anything to do with
members of that enumeration!
There are no _members_ in an enumeration.
That's just absurd.
That's just trolling.

A tighter definition of what we are talking about when we refer to an
enumeration is in order, and thus I ask you, the programming world: What is an enumeration?


I think you're in a wrong newsgroup. You need either 'comp.programming'
for broader concept discussion or 'comp.std.c++' for discussions on _why_
certain things are the way they are in the language. 'comp.lang.c++' is
for discussions on 'how', not on 'why'. And its field of interest is
narrow: C++ language, not programming in general.

V
Jul 22 '05 #2
On Tue, 10 Feb 2004 12:47:07 GMT, "AngleWyrm"
<no***************@hotmail.com> wrote:

[SNIP]
In both of these old references, an explicit conversion from integer (or
another enumeration) to an enumeration is allowed as long as the value falls
within the range of the enumeration. The first text even offers up the
obvious bug, and states that this is ok!
What bug?
flag f2 = flag(5);
is fine, and expected. e.g.
flag f2 = flag(x | z);

It would be impossible to use an enum as a combinable set of flags
without this feature.
Consider what we are representing with an enumeration: At first glance, it
appears to be a set, useful for categorizing/subdividing some domain, with
the implicit purpose of later performing a switch/case or (less optimally)
if/then against the categories.
That is one use of it, yes. Another use is mentioned above. An
alternative to the flags use though is this:

enum Foo
{
A,
B,
C,
D,
MAXFOO
};

bitset<MAXFOO> foo;
foo[A] = 1;
foo[D] = 1;

if (foo[A])
{
//...
}
Firstly, it doesn't seem to be in line with the mathematical concept of an
unordered set, nor does it seem to be a strictly ordered set, due to
duplicate values--which cause serious problems. Furthermore, explicit
conversion to an enumeration is allowed without having anything to do with
members of that enumeration! That's just absurd.

A tighter definition of what we are talking about when we refer to an
enumeration is in order, and thus I ask you, the programming world: What is
an enumeration?


In C and C++, an enum is just a set of named constants with a
particular type. There is nothing stoping you from creating other
objects of this type. You could argue that this is less useful than it
could be, but it does enable certain idioms. The concept was created
in the C days - you might want to ask in a C experts group (perhaps
comp.std.c) for a good answer on the rationale behind the semantics.

You can of course create enum classes. It is harder to use them with
switch statements though, of course.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #3
AngleWyrm wrote in news:fp4Wb.274098$na.437128@attbi_s04:

A tighter definition of what we are talking about when we refer to an
enumeration is in order, and thus I ask you, the programming world:
What is an enumeration?


In a philisophical sence I don't care.

In a C++ sence an enum type provides an named alias's for a integral
constants, it also gives those names a distinct type. Both properties
are *very* useful.

It does what it does. If you don't try to use it as something it is
not you don't have a problem.

The same is true for int, its an integer, but not *any* integer. Its
only an integer from a *very* limited range, understand that and
use it apropriatly and you have no problem. forget it and you get
undefined/unspecified behaviour.

int doesent meet the mathimatical concept of integer and enum
doesn't meet most peoples concept of enumeration.

But writing code *is* engeneering it *isn't* mathematics (or poetry).

If you want a better enumeration type (for your needs), you can
engineer one:

class your_enumeration
{
// start typing here.
};

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #4
In article <fp4Wb.274098$na.437128@attbi_s04>,
"AngleWyrm" <no***************@hotmail.com> wrote:
"The C++ Programming Language" by Bjarne Stroustrup, copyright 1997 by AT&T,
section 4.8 (pp 77):
"A value of integral type may be explicitly converted to an enumeration
type. The result of such a conversion is undefined unless the value is
within the range of the enumeration. For example:
enum flag { x=1, y=2, z=4, e=8 }; // range 0:15
flag f1 = 5; // type error: 5 is not of type flag
flag f2 = flag(5); // ok: flag(5) is of type flag and withing the range of
flag"

C++ Draft 2, December 1996, Section 7.2.9:
"An expression of arithmetic or enumeration type can be converted to an
enumeration type explicitly. The value is unchanged if it is in the range of
enumeration values of the enumeration type; otherwise the resulting
enumeration value is unspecified."

In both of these old references, an explicit conversion from integer (or
another enumeration) to an enumeration is allowed as long as the value falls
within the range of the enumeration. The first text even offers up the
obvious bug, and states that this is ok!
I don't see a bug. Consider the following:

enum flag
{
bit1 = 1,
bit2 = 2,
bit3 = 4,
bit4 = 8
};

....

flag f = bit1 | bit3;

Representing bitfields in this manner is one of enum's many uses.
Consider what we are representing with an enumeration: At first glance, it
appears to be a set, useful for categorizing/subdividing some domain, with
the implicit purpose of later performing a switch/case or (less optimally)
if/then against the categories.

However,

enum TEST_T {FIRST = 0, SECOND = 0, THIRD = 100};
TEST_T eTest = FIRST, eSecondTest = SECOND;

if ( eTest == SECOND ){
cout << "faulty logic!" << endl;
}
if( eTest == eSecondTest ){
cout << "more confusion" << endl;
}

int iTest = 5;
eTest = (TEST_T) iTest; // which comes to what?
Anytime you have to explicitly cast something, that is a red flag
that should be paid careful attention.
switch (eTest){
case FIRST:
case SECOND: // compiler catches what?: Duplicate case value
case THIRD:
cout << "success" << endl;
break;
default:
cout << "switch failure" << endl;
}

As you can see, several disasterous thinking processes are opened up.

Firstly, it doesn't seem to be in line with the mathematical concept of an
unordered set, nor does it seem to be a strictly ordered set, due to
duplicate values--which cause serious problems. Furthermore, explicit
conversion to an enumeration is allowed without having anything to do with
members of that enumeration! That's just absurd.
Yes, but the conversion is explicit. It's no more absurd than
allowing other explicit casts:

const char aString[] = "A string";
const void *voidPtr = aString;
cout << (const char*)voidPtr << '\n';
A tighter definition of what we are talking about when we refer to an
enumeration is in order, and thus I ask you, the programming world: What is
an enumeration?


It's a group of integer constants an integer type able to represent
all of the values from the minimum constant to the maximum constant;
where's the confusion?

Jul 22 '05 #5
Under the heading "[29.19] If an enumeration type is distinct from any other
type, what good is it? What can you do with it?" the faq (
http://www.parashift.com/c++-faq-lit...html#faq-29.19 ) demonstrates
promoting an enum to an int, then explains that it is a one-way operation
implicitly, but can be explicitly overridden. It also states that enums
cannot be incremented. A good update to the faq might include the value of
compile-time type checking, which seems to be the only advantage that an
enum has over a set of #define statements.

Which brings up another question: Why bother with such a type check? Because
we want the values restricted to a given set? They aren't. They are allowed
to be in a range instead of discreet values, which makes the type check less
valuable.

With the ability to assign values along the way, the last value isn't
guaranteed to be the highest value, and it's physical position in the list
is psychologically misleading:

enum Foo{ A, B=10, C, D=2, MAXFOO };
bitset<MAXFOO> foo; // how many bits?
foo[b] = 1; // where am I writing?

cout << "MAXFOO=" << int(MAXFOO) << endl;
cout << "size of foo: " << sizeof(foo) << endl;
cout << "foo: " << foo << endl;

If C++ were a perfect language, there would be no reason for the standards
commitee, or future versions of the language. And it looks to me that enums
have evolutionary potential.
Jul 22 '05 #6
"Clark Cox" <cl*******@mac.com> wrote in message
news:clarkcox3-672FF1.10293210022004@localhost...
In article <fp4Wb.274098$na.437128@attbi_s04>,
"AngleWyrm" <no***************@hotmail.com> wrote:
A tighter definition of what we are talking about when we refer to an
enumeration is in order, and thus I ask you, the programming world: What is an enumeration?


It's a group of integer constants an integer type able to represent
all of the values from the minimum constant to the maximum constant;
where's the confusion?


One the one hand, it is a selected group of itemized constants; a subset of
the possible range. On the other hand, the type refers to the range of those
constants.

If you allow a what-if scenario, the language could be more expressive. What
if the values were restricted exclusively to the enumeration, and further
that they be unique? It would then be possible to use an enumeration type
with the knowledge that it is *only* one of a specific set of values,
providing excellent support for switch/case and if/then usage.

The combination methods for flag usage could still be done with type
casting.

Furthermore, it would pave the way for the possibility of using
increment/decrement operators on enums.

And finally, casting a value to an enum could be done on a greaterThan
basis, so that it would always be one of the set.
Jul 22 '05 #7
On Tue, 10 Feb 2004 16:08:28 GMT, "AngleWyrm"
<no***************@hotmail.com> wrote:
Under the heading "[29.19] If an enumeration type is distinct from any other
type, what good is it? What can you do with it?" the faq (
http://www.parashift.com/c++-faq-lit...html#faq-29.19 ) demonstrates
promoting an enum to an int, then explains that it is a one-way operation
implicitly, but can be explicitly overridden. It also states that enums
cannot be incremented. A good update to the faq might include the value of
compile-time type checking, which seems to be the only advantage that an
enum has over a set of #define statements.
That and namespacing (#defines are horrible - use namespace scope or
class static const variables if you want global constants).
Which brings up another question: Why bother with such a type check? Because
we want the values restricted to a given set? They aren't. They are allowed
to be in a range instead of discreet values, which makes the type check less
valuable.
But still potentially valuable, like any type safety.
With the ability to assign values along the way, the last value isn't
guaranteed to be the highest value, and it's physical position in the list
is psychologically misleading:

enum Foo{ A, B=10, C, D=2, MAXFOO };
What kind of idiom is that? The idiom:

enum Foo{ A, B, C, D, MAXFOO };

is quite well known, and explicitly involves relying on the implicit
values given to each constant.
If C++ were a perfect language, there would be no reason for the standards
commitee, or future versions of the language. And it looks to me that enums
have evolutionary potential.


Not without breaking lots of code. They're a C inherited feature - you
don't have to use them, and you can use a class based alternative if
you prefer. e.g.

template <class T>
class Enum
{
//allow lookup by name
static std::map<std::string, Enum<T>*> s_values;
static int s_value;
const char* const m_name;
int const m_value;

protected:
Enum(const char* name)
:m_name(name), m_value(s_value++)
{
//add this to map (check for duplicates)
}

public:

T const& get(const char* name) const;
//etc
int getValue() const;
};

class MyEnum: public Enum<MyEnum>
{
MyEnum(const char* name)
public:
static const MyEnum A;
static const MyEnum B;
static const MyEnum C;
static const MyEnum D;
};

const MyEnum MyEnum::A("A");
const MyEnum MyEnum::B("B");
const MyEnum MyEnum::C("C");
const MyEnum MyEnum::D("D");

etc.

This can even be combined with normal enums if you want switch
statement functionality and even macros if you want to drop some of
the boilerplate code.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #8
Ok, I'm working on it:

/*
* enum_t SPECIFICATION
*
* REASON FOR EXISTANCE
* The C++ enum keyword has problems, mostly for historical reasons,
* because of how it supports bit manipulations within a range.
* This effectively cripples the compiler's ability to issue a warning
* in cases where some of the enum's keywords are unhandled/misused.
*
* Further, in supporting a range, rather than the individual keywords,
* it becomes impossible to loop through a set of enumerated keywords,
* and thus the historical enum does not support ++ incrementing,
* and so cannot be used in for/while/loop constructs.
*
* Also, the historical enum is a logically fuzzy concept;
* it implies unsupported behavior. There is no guarantee
* that the values are unique, and yet if used in a switch/case statement,
* the compiler will choke on duplicate case values.
* If used in an if/then statement, unnoticed bugs can creep in.
*
* There is also no statement about the sequential status
* of items within an enum, and thus whether it is sortable.
* Yet enums often are used with a maxvalue terminator like so:
*
* enum eTerminated { A, B, C, MAX };
*
* this, to my mind, is confusing data with function,
* a chore better relegated to a container.size() function.
*
* DEFINITION
* enum_t defines a stricter version of the enum keyword,
* with the express purpose of supporting a set of mutually exclusive
values.
* Because of this, it is possible to increment/loop through an enum_t.
*
* The enum_t consists only of the keyword values defined within it;
* Values outside the set are not a part of the enumeration.
* As such, casting to an enum_t is a conversion to one of the
keyword-values.
*
* Due to unique values, the enum_t is also a sequential container,
* and therefore sortable.
*/

Any comments / criticisms / suggestions?
Jul 22 '05 #9
"AngleWyrm" <no***************@hotmail.com> wrote...
Ok, I'm working on it:

/* [...]
*/

Any comments / criticisms / suggestions?


Post it to comp.std.c++
Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: Alexander Grigoriev | last post by:
Not quite new version of GCC that I have to use, craps with the following code: enum E; enum E { e }; That is, it doesn't accept forward declaration of enum. C++ standard text doesn't...
5
by: DJTB | last post by:
Dear Group, I'd like to check if a value is defined in an enum. Example: ------------------------------------------------------ typedef enum { A_VALUE = 1,
2
by: mrhicks | last post by:
Hello all, I have a question about enumerations. Within some requirements data passed back a certain bit field is defined by three bits then in another section the bit field is defined as 4...
18
by: Visual Systems AB \(Martin Arvidsson\) | last post by:
Hi! I have created an enum list like this: enum myEnum : int { This = 2, That, NewVal = 10, LastItm
8
by: Joe | last post by:
I have a .cs file which is linked to several other projects. All my classes in this file are defined as internal. I would like to have an enum defined as well in the namespace but I get an error...
8
by: Craig Klementowski | last post by:
All, I've installed the VS 2005 Beta 1 and was trying to build our current product. I get a compile error when enum value is specified with classname::enumname::enumvalue. Seems the compiler...
2
by: Dennis | last post by:
I have an enum as follows: Public Enum myData FirstData = 6 SecondData = 7 end enum Is there anyway that I can return the Enum names by their value, i.e., I want to input 6 into a function...
34
by: Steven Nagy | last post by:
So I was needing some extra power from my enums and implemented the typesafe enum pattern. And it got me to thinking... why should I EVER use standard enums? There's now a nice little code...
3
by: Jens Müller | last post by:
I have a file here with several enums: #ifndef PLANARSEP_OPTIMIZE_H #define PLANARSEP_OPTIMIZE_H enum fund_cycle_behavior_t {PASS_MODE_FIRST, PASS_MODE_BEST, PASS_MODE_ALL};
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.