473,395 Members | 1,689 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,395 software developers and data experts.

Enumerations

I'll try to explain what I want to do:

I have foo.h and foo.cpp. Units that include foo.h will define an
enumeration bar:

enum bar { typeNone, typeBaz, typeQuux, ... , count };

A method defined in foo.cpp needs to return typeNone. Is using

static_cast< bar >( 0 )

acceptable?

Also, methods in foo.cpp need to return typeBaz, typeQuux, etc. Is
there any way to specify that these are values of the bar enumeration
without actually defining bar (since units that include foo.h will
take care of that)?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #1
21 1900
On 21/7/04 8:46 pm, in article cd**********@chessie.cirr.com, "Christopher
Benson-Manica" <at***@nospam.cyberspace.org> wrote:
I'll try to explain what I want to do:

I have foo.h and foo.cpp. Units that include foo.h will define an
enumeration bar:

enum bar { typeNone, typeBaz, typeQuux, ... , count };

A method defined in foo.cpp needs to return typeNone. Is using

static_cast< bar >( 0 )

acceptable?

Am I missing something obvious? Why not just return typeNone?

Also, methods in foo.cpp need to return typeBaz, typeQuux, etc. Is
there any way to specify that these are values of the bar enumeration
without actually defining bar (since units that include foo.h will
take care of that)?

Is foo.cpp #including foo.h?
Steve.

Jul 22 '05 #2
On 21/7/04 8:50 pm, in article BD*****************@127.0.0.1, "Steve"
<ro**@127.0.0.1> wrote:
On 21/7/04 8:46 pm, in article cd**********@chessie.cirr.com, "Christopher
Benson-Manica" <at***@nospam.cyberspace.org> wrote:
I'll try to explain what I want to do:

I have foo.h and foo.cpp. Units that include foo.h will define an
enumeration bar:

enum bar { typeNone, typeBaz, typeQuux, ... , count };

A method defined in foo.cpp needs to return typeNone. Is using

static_cast< bar >( 0 )

acceptable?

Am I missing something obvious? Why not just return typeNone?

Also, methods in foo.cpp need to return typeBaz, typeQuux, etc. Is
there any way to specify that these are values of the bar enumeration
without actually defining bar (since units that include foo.h will
take care of that)?

Is foo.cpp #including foo.h?
Steve.

Oops, sorry, let me read the OP again more closely...

OK, let me rephrase my answer...

Why not put the enum declaration in foo.h?
Steve.

Jul 22 '05 #3
Steve <ro**@127.0.0.1> spoke thus:
Am I missing something obvious? Why not just return typeNone?


My intent is that neither foo.h nor foo.cpp will actually define bar,
perhaps something like

foo.h:

enum bar;

foo.cpp

#include "foo.h"

/* whatever

my_special_unit.cpp:

#include "foo.h"

enum bar { typeNone, typeBaz, count };

some_other_unit.cpp:

#include "foo.h"

enum bar { typeNone, typeQuux, typeCharlie, count };

Presumably this won't work, since the bar enumeration is never fleshed
out for foo.cpp. Basically, I want to make the symbols that the
enumeration will use available to foo.cpp without actually defining
the enumeration there. Does that make sense? Is it possible?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #4
Christopher Benson-Manica wrote:
Steve <ro**@127.0.0.1> spoke thus:

Am I missing something obvious? Why not just return typeNone?

My intent is that neither foo.h nor foo.cpp will actually define bar,
perhaps something like

foo.h:

enum bar;

foo.cpp

#include "foo.h"

/* whatever

my_special_unit.cpp:

#include "foo.h"

enum bar { typeNone, typeBaz, count };

some_other_unit.cpp:

#include "foo.h"

enum bar { typeNone, typeQuux, typeCharlie, count };

Presumably this won't work, since the bar enumeration is never fleshed
out for foo.cpp. Basically, I want to make the symbols that the
enumeration will use available to foo.cpp without actually defining
the enumeration there. Does that make sense? Is it possible?


If you need to use the enum as a return type and the function must be
declared in the .h file (which is the case if I understood the original
question correctly) the answer is no. Only if the enum is used only
inside function in the .cpp file but never as return type or argument
the enum can be declared inside the .cpp file.

In case of a class you might consider putting the enum definition in the
private section of the class. That way it is clear that the enum is
intended for internal use only, and isn't accessible to the outside
world. Another advantage is that it is defined within the scope of the
class, so potential name clashes are avoided.
--
Peter van Merkerk
peter.van.merkerk(at)dse.nl
Jul 22 '05 #5
Peter van Merkerk <me*****@deadspam.com> spoke thus:
In case of a class you might consider putting the enum definition in the
private section of the class. That way it is clear that the enum is
intended for internal use only, and isn't accessible to the outside
world. Another advantage is that it is defined within the scope of the
class, so potential name clashes are avoided.


Well, here's another question: If I put the enum definition in the
class, can a subclass override that definition?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #6
Without passing judgement on your design:

extern enum bar;

return bar(0);
-JKop
Jul 22 '05 #7
JKop <NU**@null.null> spoke thus:
Without passing judgement on your design:


No, please do! Seriously - otherwise, how do I learn how to improve? :)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #8
Christopher Benson-Manica posted:
JKop <NU**@null.null> spoke thus:
Without passing judgement on your design:


No, please do! Seriously - otherwise, how do I learn how to improve? :)


First I'm going to talk about enums. They're pretty much useless. For
instance:

enum Month
{
Jan = 1,
Feb = 2,
Mar = 3,
Apr = 4,
May = 5,
Jun = 6,
Jul = 7,
Aug = 8,
Sep = 9,
Oct = 10,
Nov = 11,
Dec = 12
};

int main()
{
Month my_super_duper_month(13);
}
So why are they useful? They're only merit is with switch statements:
switch (some_month)
{
case Jan:
//blah
case Feb:

//blah

}
The compiler can warn you when you leave one out of the switch statement.
Yipee!

Anyway, I'd suggest you return an "unsigned char" from this function. If you
want to give certain numbers special names, then by all means:

namespace ChocolateValues
{
const unsigned char no_error = 0;
const unsigned char multiple_errors = 1;
};

unsigned char SomeFunction()
{
return ChocolateValues::no_error;
}


-JKop
Jul 22 '05 #9

JKop wrote:
First I'm going to talk about enums. They're pretty much useless. For
instance:
you have some serious misconceptions about enumerations.
enum Month
{
Jan = 1,
Feb = 2,
Mar = 3,
Apr = 4,
May = 5,
Jun = 6,
Jul = 7,
Aug = 8,
Sep = 9,
Oct = 10,
Nov = 11,
Dec = 12
};

int main()
{
Month my_super_duper_month(13);
}
compiler error - illegal implicit conversion to int.

mind you:

Month m(static_cast<Month>(13));

would work. but that is a case of directly and maliciously circumventing
the enumeration.
So why are they useful? They're only merit is with switch statements:
switch (some_month)
{
case Jan:
//blah
case Feb:

//blah

}
The compiler can warn you when you leave one out of the switch statement.
Yipee!
what compiler? i would find it quite bizarre if a compiler barked that
warning at me, unless it had some crazy super verbose warning setting.
it is not an error, or even a mistake, to only switch on certain
enumerators.
Anyway, I'd suggest you return an "unsigned char" from this function. If you
want to give certain numbers special names, then by all means:

namespace ChocolateValues
{
const unsigned char no_error = 0;
const unsigned char multiple_errors = 1;
};

unsigned char SomeFunction()
{
return ChocolateValues::no_error;
}


and this has to be the wackiest suggestion of all, considering that you
write off enums for having an implicit conversion to int above (which
they don't, as i pointed out).

in fact, the example above is LESS robust than if it had used enums.
consider this:

////////////////////////////////////////////////////////

namespace error {
const unsigned char no_error = 0;
const unsigned char out_of_memory = 1;
const unsigned char cannot_open_file = 2;
}

enum type {
no_error,
out_of_memory,
cannot_open_file
};

void print_error(unsigned char c) {
// print error message based on error code
switch (c) {
case error::no_error: // whatever
case error::out_of_memory: // whatever
case error::cannot_open_file: // whatever
// ...
}
}

// nothing seems wrong with this...
unsigned char oops = 3;

// ...but
print_error(oops); // <--- what should this do?

////////////////////////////////////////////////////////

as opposed to:

////////////////////////////////////////////////////////

namespace error {

enum type {
no_error,
out_of_memory,
cannot_open_file
};

}

void print_error(error::type c) {
// print error message based on error code
switch (c) {
case error::no_error: // whatever
case error::out_of_memory: // whatever
case error::cannot_open_file: // whatever
// ...
}
}

error::type nope = 3; // won't compile

// this is explicit and obvious - the programmer knew what (s)he
// was doing, and should be able to explain him/herself
error::type iffy = static_cast<error::type>(3);

error::type ok = error::out_of_memory; // obviously ok

////////////////////////////////////////////////////////

enumerations are not perfect - personally, i was looking for a better
solution just last week, and i was not satisfied with the options - but
until the standard committee gives the thumbs up to the new super enums,
we're stuck with them. despite all their shortcomings though, i'd have
to say they're still a better choice than simple ints (or unsigned
char's for that matter).

indi

Jul 22 '05 #10
Christopher Benson-Manica wrote:
Peter van Merkerk <me*****@deadspam.com> spoke thus:
In case of a class you might consider putting the enum definition in the
private section of the class. That way it is clear that the enum is
intended for internal use only, and isn't accessible to the outside
world. Another advantage is that it is defined within the scope of the
class, so potential name clashes are avoided.


Well, here's another question: If I put the enum definition in the
class, can a subclass override that definition?


I'm afraid not.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl
Jul 22 '05 #11
Mark A. Gibbs posted:
would work. but that is a case of directly and maliciously circumventing the enumeration.

Month blah = Month(13);

error::type nope = 3; // won't compile


= EnumName(3); //*will* compile, regardless if the enum
contains a 3.

-JKOp
Jul 22 '05 #12
JKop <NU**@null.null> spoke thus:
= EnumName(3); //*will* compile, regardless if the enum
contains a 3.


Granted, but why on earth would you want to do *that*?

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #13
Peter van Merkerk <me*****@deadspam.com> spoke thus:
I'm afraid not.


No, no need to be afraid ;)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Jul 22 '05 #14
On Wed, 21 Jul 2004 19:46:21 +0000 (UTC), Christopher Benson-Manica
<at***@nospam.cyberspace.org> wrote:
I'll try to explain what I want to do:

I have foo.h and foo.cpp. Units that include foo.h will define an
enumeration bar:

enum bar { typeNone, typeBaz, typeQuux, ... , count };

A method defined in foo.cpp needs to return typeNone. Is using

static_cast< bar >( 0 )

acceptable?

Also, methods in foo.cpp need to return typeBaz, typeQuux, etc. Is
there any way to specify that these are values of the bar enumeration
without actually defining bar (since units that include foo.h will
take care of that)?


All definitions of bar must be token for token identical according to
the one definition rule. If they aren't, you've got undefined
behaviour.

In your case you might just want to return some named constants, and
have other TUs cast them to whatever enum type they want (and
presumably a different one for each TU).

Tom
Jul 22 '05 #15
Christopher Benson-Manica posted:
JKop <NU**@null.null> spoke thus:
= EnumName(3); //*will* compile, regardless if the enum contains a 3.


Granted, but why on earth would you want to do *that*?


Because it can be done. If you write a function that takes
a month, then you've to check that it's >= 1 and <= 12.
Therefore, what use has an enum? Why not just use constant
variables?

namespace Month{
const unsigned char jan = 1,
feb = 2,
mar = 3,
apr = 4,
may = 5,
jun = 6,
//and so on
-JKop
Jul 22 '05 #16
JKop <NU**@NULL.NULL> wrote in news:zh*****************@news.indigo.ie:
Christopher Benson-Manica posted:
JKop <NU**@null.null> spoke thus:
= EnumName(3); //*will* compile, regardless if the enum contains a 3.
Granted, but why on earth would you want to do *that*?


Because it can be done. If you write a function that takes


So can dereferencing a NULL pointer, and reinterpret_casting stuff between
incompatable types. Doesn't mean that it's defined behaviour.
a month, then you've to check that it's >= 1 and <= 12.
Therefore, what use has an enum? Why not just use constant
variables?


No you don't. Your function simply takes a Month as a parameter. No need
to check for range. Your caller would have to invoke undefined behaviour
to break your function then.
Jul 22 '05 #17

"Christopher Benson-Manica" <at***@nospam.cyberspace.org> wrote in message
news:cd**********@chessie.cirr.com...
JKop <NU**@null.null> spoke thus:
= EnumName(3); //*will* compile, regardless if the enum
contains a 3.


Granted, but why on earth would you want to do *that*?


I think he means, how would you keep a user from inadvertently doing that
via a compiler error.

Jeff F
Jul 22 '05 #18
Andre Kostur <nn******@kostur.net> wrote:

[snip - debate over whether to use 'enum' for month names]
No you don't. Your function simply takes a Month as a parameter. No need
to check for range. Your caller would have to invoke undefined behaviour
to break your function then.


If an enum contains values 1...11, then it can also hold values 12...15
without causing undefined behaviour. This language rule exists to allow
'flag' enums, eg:

enum flags
{
Foo = 0x80,
Bar = 0x40,
Quz = 0x20,
};

flags f = Foo | Quz; // 0xA0 is not an enum member, but is valid

So you still have to check range (> 0 as well as <= 12)
Jul 22 '05 #19
ol*****@inspire.net.nz (Old Wolf) wrote in
news:84**************************@posting.google.c om:
Andre Kostur <nn******@kostur.net> wrote:

[snip - debate over whether to use 'enum' for month names]
No you don't. Your function simply takes a Month as a parameter. No
need to check for range. Your caller would have to invoke undefined
behaviour to break your function then.


If an enum contains values 1...11, then it can also hold values
12...15 without causing undefined behaviour. This language rule exists
to allow 'flag' enums, eg:


I stand corrected. The enum may contain values beyond the specified ones.

I guess, for me, that would leave it in the realm of "bad programming
practice". One would need to explicitly do something to put the enum out
of range (explicit construction with an out of range value, or do some sort
of bitwise or arithmetic operations on the enums)
Jul 22 '05 #20

JKop wrote:
Because it can be done. If you write a function that takes
a month, then you've to check that it's >= 1 and <= 12.
"because it can be done" is not a good reason for doing something. i
fail to see what would inspire an otherwise level-headed programmer to
randomly construct an illegal enumeration. why explicitly construct at
all? it makes little sense. and if you decide you *must* explicitly
construct an enumerator, why pick a raondom value like 13? why not just
use an existing enumerator value, like "feb"?

do you hang around programmers that randomly assign spurious values to
obviously logically incompatible types (there is no month "13", just
like there is no month "6" or "100", but there is a "may")?
Therefore, what use has an enum? Why not just use constant
variables?

namespace Month{
const unsigned char jan = 1,
feb = 2,
mar = 3,
apr = 4,
may = 5,
jun = 6,
//and so on


because, as i showed you before, they are less safe than enumerators. no
one ever claimed enumerations cannot be broken, but at least when you
break an enumerator, it's not likely to be by accident. on the other hand:

unsigned char c = 42;
// lots of code in between
month m = c; // not a squeak from the compiler
// the only way you could break this with enums is
// if you did month m = static_cast<month>(c);
// or at least month m = month(c);
// which is pretty hard to miss

or:

namespace a {
typedef unsigned char month;
static const unsigned char jan = 0;
static const unsigned char feb = 1;
}
namespace b {
typedef unsigned char month;
static const unsigned char jan = 1;
static const unsigned char feb = 2;
}

b::month get_month()
{
using namespace a;
return jan; // but which jan?
// an enum version would not compile
}

and finally, let's assume that i thought that it would be reasonable for
a programmer to write month(13). in the enum version, modern ide's would
show you (via a tooltip or something) the name of the enumerator if it
was valid, and a number otherwise. in other words, you can debug just by
hovering the mouse over your suspect variable. you can't do that with
unsigned char's.

but i'll tell you what, i'll be open-minded about this. show me one (1)
real world error caused by any practical usage of enum that would be
fixed if the code were *identical* except the enum type were unsigned
char and the enumerators were static constants. by my count i've shown
you four code sample that demonstrate that enums are safer. all i ask
from you is one.

mark

Jul 22 '05 #21
I got around this by writing a Month class that validates
input on assignment and construction.
-JKop
Jul 22 '05 #22

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

Similar topics

1
by: Joyce | last post by:
In my schema I have 2 enumerations, let's say, country description and country code, and I want to use them so I can map each country description to its precise country code (and no other). So far...
0
by: Plinkerton | last post by:
I'm making an Base Class that will be inherited. In my base class, I have a public enumeration that defines a list of things I want my class to be able to do. I use it for Method input...
3
by: JoeH | last post by:
Hi, I'm using a COM DLL (created in VB) in my javascript code and can successfully call its methods and get/set its properties. There are also some Public enumerations defined in the ActiveX...
5
by: Seamus M | last post by:
I can't find any info on enumerations in the PHP manual, so I assume there is no built in way to create them. Can anyone tell me the best way to build a simple enumeration, such as: Enum...
1
by: someone else | last post by:
I have some code that creates dynamic enumerations for use in a PropertyGrid control. This all works perfectly but the memory usage of the program increases quite quicly when viewing the...
1
by: Oleg Ogurok | last post by:
Hi all, I've added a new DataSet (xsd file) to my project in VS.NET 2003. There I create a simple type as an enumeration of values. <xs:simpleType name="MyCustomType"> <xs:restriction...
4
by: ChrisB | last post by:
Hello: I will be creating 50+ enumerations related to a large number of classes that span a number of namespaces. I was wondering if there are any "best practices" when defining enumerations. ...
27
by: Ben Finney | last post by:
Antoon Pardon wrote: > I just downloaded your enum module for python > and played a bit with it. IMO some of the behaviour makes it less > usefull. Feedback is appreciated. I'm hoping to...
77
by: Ben Finney | last post by:
Howdy all, PEP 354: Enumerations in Python has been accepted as a draft PEP. The current version can be viewed online: <URL:http://www.python.org/peps/pep-0354.html> Here is the...
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?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
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,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

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.