Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > To const or to enum?

Reply
Thread Tools

To const or to enum?

 
 
Steven T. Hatton
Guest
Posts: n/a
 
      08-20-2004
Any opinions or comments on the following? I don't say it below, but I came
out on the side of using enumerations over static constants.

/* I'm trying to figure out the pros and cons of using static const
* int class members as opposed to using enumerations to accomplish a
* similar goal. The use of static constants seems more explicit and
* obvious to me. Unless I assign values to the enumerators, the
* compiler will do it for me. This has the advantage of saving
* keystrokes and digital ink. It has the disadvantage that I have to
* calculate the actual numerical value if I want to know what it
* is. With static constants, it is right there poking you in the eye.
*
* Enumerations support a rudimentary form of type checking. It may be
* useful, but possibly also deceptive. Basically any value that fits
* in the storage location used by the compiler to hold the
* enumerators will convert to the enumeration type, even if it is not
* a value of any of the enumerators. That can be useful for bounding
* a range of values, but it may also lead to a false impression that
* you are using a 'type-safe' value.
*
* The type checking can keep me honest if I want to be. That is, if
* I use the type name as an indicator that a given parameter is
* intended to be of that enumeration type, I can use the enumerators
* by name without explicit type conversions of the form Type(val).
*
* An example of where public static integral constants are used is in
* the w3c DOM recommendations. They serve as a form of poor-man's
* type checking. Each node type is assigned an integral constant
* value with an associated name. The base type of all nodes holds the
* definitions of these constants, and each derived node is assigned
* a named constant identical to one of those named in the baseclass.
*
* A purist may argue that static_cast, or dynamic_cast should be used
* instead, but static_cast only works for types known at compile
* time, and dynamic_cast incurs overhead beyond that of using a
* statically bound integral constant. I may be incorrect regarding
* this last point, but I'm pretty sure of it.
*
*
*/

/*
http://xml.apache.org/xerces-c/Apach...BindingL2.html
*/

/*
DOMNode.hpp:
class DOMNode
{
public:
enum NodeType {
ELEMENT_NODE = 1,
ATTRIBUTE_NODE = 2,
TEXT_NODE = 3,
CDATA_SECTION_NODE = 4,
ENTITY_REFERENCE_NODE = 5,
ENTITY_NODE = 6,
PROCESSING_INSTRUCTION_NODE = 7,
COMMENT_NODE = 8,
DOCUMENT_NODE = 9,
DOCUMENT_TYPE_NODE = 10,
DOCUMENT_FRAGMENT_NODE = 11,
NOTATION_NODE = 12,
};
*/

/*
* The following is code I created to test certan uses of const and
* enum. I'll be more than happy to see alternatives, or additional
* uses of these syntactic elements.
*/
#include <iostream>
class A {
public:

/*
* We can't use A::EA or A: before they are declared.
* Therefore the constructor is placed after the declarations,
* which are, in the case, definitions.
*/
/*
A(const A::AE& ae=A: )
{
if(ae > x)
{
std::cout << "ae > x \n";
}
}
*/

/* Concise, but ugly.*/
/*
static const int X=0,
Y=1,
Z=2;
*/

/* More verbose, but clearer */
static const int X=0;
static const int Y=1;
static const int Z=2;

/* More concise, but more obscure to the untrained eye.*/
enum AE {x,y,z};

/* Placed after declarations (definitions) so I can use them*/
A(const A::AE& ae=A: )
{
if(ae > x)
{
std::cout << "ae > x \n";
}
}

void f(const AE& ae)
{
if(ae > x)
{
std::cout << "ae > x \n";
}
}

/* How to make a DOM to XML generator, or syntax checker.*/
void g(const AE& ae)
{
switch(ae)
{
case A:: std::cout << "case A: \n";
return;
case A: std::cout << "case A::y \n";
return;
case A::z: std::cout << "case A::z \n";
return;
}
}

void h(const AE& ae)
{
switch(ae)
{
case A:: std::cout << "case A: \n";
return;
case A: std::cout << "case A::y \n";
return;
case A::z: std::cout << "case A::z \n";
return;
}
}
};

void i(const A::AE& ae)
{
switch(ae)
{
case A:: std::cout << "case A: \n";
return;
case A: std::cout << "case A::y \n";
return;
case A::z: std::cout << "case A::z \n";
return;
}
}

int main()
{
A a;
a.f(A:);
a.f(A::AE(A::Z));
a.f(A::AE(5));
}

--
STH
Hatton's Law: "There is only One inviolable Law"
KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
Mozilla: http://www.mozilla.org
 
Reply With Quote
 
 
 
 
David Hilsee
Guest
Posts: n/a
 
      08-20-2004
"Steven T. Hatton" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Any opinions or comments on the following? I don't say it below, but I

came
> out on the side of using enumerations over static constants.
>
> /* I'm trying to figure out the pros and cons of using static const
> * int class members as opposed to using enumerations to accomplish a
> * similar goal. The use of static constants seems more explicit and
> * obvious to me. Unless I assign values to the enumerators, the
> * compiler will do it for me. This has the advantage of saving
> * keystrokes and digital ink. It has the disadvantage that I have to
> * calculate the actual numerical value if I want to know what it
> * is. With static constants, it is right there poking you in the eye.


Either the value is important, or it's not. If it is important, then it
should be specified in the code. If it is not, then just let the compiler
do the work. Most of the enumerations that I have unimportant values that I
have never needed to know or calculate by hand.

> * Enumerations support a rudimentary form of type checking. It may be
> * useful, but possibly also deceptive. Basically any value that fits
> * in the storage location used by the compiler to hold the
> * enumerators will convert to the enumeration type, even if it is not
> * a value of any of the enumerators. That can be useful for bounding
> * a range of values, but it may also lead to a false impression that
> * you are using a 'type-safe' value.


The entire C++ language presents a false impression of type-safety. Once UB
behavior occurs, all sorts of problems may occur. Sure, someone could
accidentally put an invalid value in the enum, but then again, someone could
also walk off the end of an array and cause all sorts of damage, so I won't
be losing any sleep over an enum. The "false impression" can be cured with
a little education.

<snip>
> * An example of where public static integral constants are used is in
> * the w3c DOM recommendations. They serve as a form of poor-man's
> * type checking. Each node type is assigned an integral constant
> * value with an associated name. The base type of all nodes holds the
> * definitions of these constants, and each derived node is assigned
> * a named constant identical to one of those named in the baseclass.


The quoted header uses an enum, not static integers. Are you referring to
something else, or did you mistype something?

> * A purist may argue that static_cast, or dynamic_cast should be used
> * instead, but static_cast only works for types known at compile
> * time, and dynamic_cast incurs overhead beyond that of using a
> * statically bound integral constant. I may be incorrect regarding
> * this last point, but I'm pretty sure of it.


I don't know of any purists that would argue for using static_cast with
enums, but that's a matter of taste. That should work just fine. However,
you can't use dynamic_cast because it's an enum, and not a polymorphic type.

<snip>
> /* More concise, but more obscure to the untrained eye.*/
> enum AE {x,y,z};

<snip>

I think you mean "more concise, but more obscure to someone who doesn't know
the very basics of C or C++."

--
David Hilsee


 
Reply With Quote
 
 
 
 
Ian
Guest
Posts: n/a
 
      08-20-2004
Steven T. Hatton wrote:
> Any opinions or comments on the following? I don't say it below, but I came
> out on the side of using enumerations over static constants.
>

Each has its place.

> /* I'm trying to figure out the pros and cons of using static const
> * int class members as opposed to using enumerations to accomplish a
> * similar goal. The use of static constants seems more explicit and
> * obvious to me. Unless I assign values to the enumerators, the
> * compiler will do it for me. This has the advantage of saving
> * keystrokes and digital ink. It has the disadvantage that I have to
> * calculate the actual numerical value if I want to know what it
> * is. With static constants, it is right there poking you in the eye.
> *

How often do you have to know the numerical value? If you do, then
maybe an enum is not the correct option. In the DOM example you quote,
you will never (or at least I have never) have to know the numeric
value. An enum is what is says on the box, an enumeration - the value
don't matter.

> * Enumerations support a rudimentary form of type checking. It may be
> * useful, but possibly also deceptive. Basically any value that fits
> * in the storage location used by the compiler to hold the
> * enumerators will convert to the enumeration type, even if it is not
> * a value of any of the enumerators. That can be useful for bounding
> * a range of values, but it may also lead to a false impression that
> * you are using a 'type-safe' value.
> *

No, it won't. The compiler will barf on an attempt to pass an int to a
function with an enum parameter.

> * The type checking can keep me honest if I want to be. That is, if
> * I use the type name as an indicator that a given parameter is
> * intended to be of that enumeration type, I can use the enumerators
> * by name without explicit type conversions of the form Type(val).
> *

? It's not an indicator, it's a requirement!

> * An example of where public static integral constants are used is in
> * the w3c DOM recommendations. They serve as a form of poor-man's
> * type checking. Each node type is assigned an integral constant
> * value with an associated name. The base type of all nodes holds the
> * definitions of these constants, and each derived node is assigned
> * a named constant identical to one of those named in the baseclass.
> *

Don't forget these cam form IDL and Java bindings (there is (or at least
was) no C++ binding in the W3C specification). So the lowest common
denominator, const ints was used.

> * A purist may argue that static_cast, or dynamic_cast should be used
> * instead, but static_cast only works for types known at compile
> * time, and dynamic_cast incurs overhead beyond that of using a
> * statically bound integral constant. I may be incorrect regarding
> * this last point, but I'm pretty sure of it.
> *

When working with DOM, the dynamic_cast overhead tends to be trivial.
You have the choice of RTTI or the node type, again, remember this stuff
started as IDL, so it has to be language neutral.

Ian
 
Reply With Quote
 
David Hilsee
Guest
Posts: n/a
 
      08-20-2004
"David Hilsee" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
<snip>
> > * A purist may argue that static_cast, or dynamic_cast should be used
> > * instead, but static_cast only works for types known at compile
> > * time, and dynamic_cast incurs overhead beyond that of using a
> > * statically bound integral constant. I may be incorrect regarding
> > * this last point, but I'm pretty sure of it.

>
> I don't know of any purists that would argue for using static_cast with
> enums, but that's a matter of taste. That should work just fine.

However,
> you can't use dynamic_cast because it's an enum, and not a polymorphic

type.

After reading Ian's post, I realized that you were talking about
dynamic_cast being applied to the nodes in the DOM, not the enums
themselves. My mistake.

IMHO, the "purist" approach of using dynamic_cast doesn't buy you much. You
still wind up in a switch/case-like structure. I'm not even sure that
purists would normally argue for dynamic_cast. Most of the time, they argue
against it, opting for virtual functions instead. In this case, they might
argue for the visitor pattern, which may look better to some and confusing
to others.

--
David Hilsee


 
Reply With Quote
 
Steven T. Hatton
Guest
Posts: n/a
 
      08-21-2004
David Hilsee wrote:

> "Steven T. Hatton" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> Any opinions or comments on the following? I don't say it below, but I

> came
>> out on the side of using enumerations over static constants.
>>...
>> * An example of where public static integral constants are used is in
>> * the w3c DOM recommendations. They serve as a form of poor-man's
>> * type checking. Each node type is assigned an integral constant
>> * value with an associated name. The base type of all nodes holds the
>> * definitions of these constants, and each derived node is assigned
>> * a named constant identical to one of those named in the baseclass.

>
> The quoted header uses an enum, not static integers. Are you referring to
> something else, or did you mistype something?


No. I was just speaking in abstract terms. Static binding means a binding
that occurs before execution. I should have been more careful to make the
distinction. Enumerators are not integral types as defined in ISO/IEC
14882:2003, nor are they declared static const. Nonetheless, from a
conceptual perspective they are virtually identical. I was actually
thinking in terms of the w3c IDE recommendation.

http://www.w3.org/TR/2004/REC-DOM-Le...finitions.html
interface Node {

// NodeType
const unsigned short ELEMENT_NODE = 1;
const unsigned short ATTRIBUTE_NODE = 2;
const unsigned short TEXT_NODE = 3;
const unsigned short CDATA_SECTION_NODE = 4;
const unsigned short ENTITY_REFERENCE_NODE = 5;
const unsigned short ENTITY_NODE = 6;
const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
const unsigned short COMMENT_NODE = 8;
const unsigned short DOCUMENT_NODE = 9;
const unsigned short DOCUMENT_TYPE_NODE = 10;
const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
const unsigned short NOTATION_NODE = 12;

//...
}

There is no w3c DOM binding recommendation for C++. What I posted was
Apache's proposed DOM binding.

> I don't know of any purists that would argue for using static_cast with
> enums,


I intended it as an alternative to using enums. If you use dynamic_cast you
don't need the enums. See 12.2.5 of TC++PL(SE) for a discussion of the use
of type fields (enums or static constants in this discussion).

> but that's a matter of taste. That should work just fine.
> However, you can't use dynamic_cast because it's an enum, and not a
> polymorphic type.


As I said, that incurs more overhead than the use of statically bound
constants.

> <snip>
>> /* More concise, but more obscure to the untrained eye.*/
>> enum AE {x,y,z};

> <snip>
>
> I think you mean "more concise, but more obscure to someone who doesn't
> know the very basics of C or C++."


That is not what I meant. Understanding is one thing. familiarity another.
I've understood what an expression of that form means for over a decade.
But that doesn't mean that it would be as immediately recognizable as the
explicitly named static constants, or explicitly initialized enumerators.
The reason I use the w3c DOM as an example is because the numerical values
are explicitly specified. A programmer could not, for example, add an
enumerator to the beginning of the list above and remove the explicit
initializations without deviating from the interface specification.

--
STH
Hatton's Law: "There is only One inviolable Law"
KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
Mozilla: http://www.mozilla.org
 
Reply With Quote
 
Steven T. Hatton
Guest
Posts: n/a
 
      08-21-2004
David Hilsee wrote:

> "David Hilsee" <(E-Mail Removed)> wrote in message


> IMHO, the "purist" approach of using dynamic_cast doesn't buy you much.
> You
> still wind up in a switch/case-like structure. I'm not even sure that
> purists would normally argue for dynamic_cast. Most of the time, they
> argue
> against it, opting for virtual functions instead.


Yes, but that only works if you are invoking a method on the object, not if
you are trying to determine what to do with the object as a parameter to a
function, etc.

> In this case, they
> might argue for the visitor pattern, which may look better to some and
> confusing to others.


It depends on what you are trying to accomplish. One problem with building
all your smarts into the node and its derivatives is that it requires some
very convoluted inheritance to create any kind of recursive instantiation.
I have built a parser that consisted of nodes that thought for themselves.
But I had to feed it meaningful tokens one at a time.

--
STH
Hatton's Law: "There is only One inviolable Law"
KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
Mozilla: http://www.mozilla.org
 
Reply With Quote
 
David Hilsee
Guest
Posts: n/a
 
      08-21-2004
"Steven T. Hatton" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
<snip>
> > In this case, they
> > might argue for the visitor pattern, which may look better to some and
> > confusing to others.

>
> It depends on what you are trying to accomplish. One problem with

building
> all your smarts into the node and its derivatives is that it requires some
> very convoluted inheritance to create any kind of recursive instantiation.
> I have built a parser that consisted of nodes that thought for themselves.
> But I had to feed it meaningful tokens one at a time.


I'm not sure I understand what you're saying. I was just pointing out that
the dynamic_cast could be eliminated with the visitor pattern, and that
might be supported by purists. I don't understand why that means the node
"thinks for itself" or why that means you have to feed it "one at a time."
For the visitor pattern, the node just has to override one member function
with a simple implementation (void accept(Visitor * p){p->visit(this);}).
What are you saying is the issue that results from this?

BTW, I'm not a huge fan of the visitor pattern. I was just pointing out
what some people might prefer.

--
David Hilsee


 
Reply With Quote
 
David Hilsee
Guest
Posts: n/a
 
      08-21-2004
"Steven T. Hatton" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> David Hilsee wrote:

<snip>
> > I think you mean "more concise, but more obscure to someone who doesn't
> > know the very basics of C or C++."

>
> That is not what I meant. Understanding is one thing. familiarity

another.
> I've understood what an expression of that form means for over a decade.
> But that doesn't mean that it would be as immediately recognizable as the
> explicitly named static constants, or explicitly initialized enumerators.
> The reason I use the w3c DOM as an example is because the numerical values
> are explicitly specified. A programmer could not, for example, add an
> enumerator to the beginning of the list above and remove the explicit
> initializations without deviating from the interface specification.


Well, I meant that as a joke to poke fun at those who might find enums
strange or mildly confusing, but I am surprised that you would say that
enums without explicitly specified values are not immediately recognizable.
I learned about enums when I first learned C, I have never had to think
twice about them since then. To me, it is immediately recognizable, easily
understandable, and very familiar, even though I do not often use enums or
see them used in practice. I guess I just found them very intuitive and
simple.

--
David Hilsee


 
Reply With Quote
 
Conrad Weyns
Guest
Posts: n/a
 
      08-21-2004

"Steven T. Hatton" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Any opinions or comments on the following? I don't say it below, but I

came
> out on the side of using enumerations over static constants.
>
> /* I'm trying to figure out the pros and cons of using static const
> * int class members as opposed to using enumerations to accomplish a
> * similar goal. The use of static constants seems more explicit and
> * obvious to me. Unless I assign values to the enumerators, the
> * compiler will do it for me. This has the advantage of saving
> * keystrokes and digital ink. It has the disadvantage that I have to


[...]
I.m.o the problem with enums is that they get abused.
One should be able to change the position and values of an enum entry
at any time without breaking code.

An enum is indeed a type and has many advantages over const variables.
Enums look like classes but do not profit from the implicit namespace that a
class has, in other words:
EColType::Red
is illegal. This is unfortunate. Yet ms vc7 will eat accept!

The type of an enum member is not known and should never be assumed.

Here is what I try to adhere to when using enums:

1. Prefix every enum member with the enum name unless the enum
is part of a class in which case it "can" be left out:

enum EColorType
{
EColTypeInvalid,
EColTypeRed,
EColTypeBlue
};

This is necessary because enum members have global scope wether we
like it or not. In any sizeable project, good descriptive names get very
quickly used up.

2. Never ever cast an enum member.
Allways provide a complete (however large) switch to map enum
members to and from other context appropriate values.
This mapping is vital because this is the place where published
values (as read from and written to a data base) are maintained and
de-coupled from the enum.

3. Never ever use enum members in loop indexes and loop limits.

Regards,
Conrad Weyns

> --
> STH
> Hatton's Law: "There is only One inviolable Law"
> KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
> Mozilla: http://www.mozilla.org




 
Reply With Quote
 
Niels Dekker - no reply address
Guest
Posts: n/a
 
      08-21-2004
Conrad Weyns wrote:
>
> Here is what I try to adhere to when using enums:
>
> 1. Prefix every enum member with the enum name unless the enum
> is part of a class in which case it "can" be left out:
>
> enum EColorType
> {
> EColTypeInvalid,
> EColTypeRed,
> EColTypeBlue
> };



Your prefix "EColType" differs from the enum name, but I guess that's a
typo...? Still, shouldn't we use a little namespace instead? Like
this:

namespace Color
{
enum Type
{
Invalid,
Red,
Blue
};
};


Regards,

Niels Dekker
www.xs4all.nl/~nd/dekkerware
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
const vector<const MyType> Vs const vector<MyType> magnus.moraberg@gmail.com C++ 2 02-09-2009 10:45 PM
is const necessary in eg int compar(const void *, const void *) lovecreatesbeauty@gmail.c0m C Programming 26 11-10-2008 09:47 PM
const correctness - should C++ prefer const member over non-const? fungus C++ 13 10-31-2008 05:33 AM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
Casting int'** to 'const int * const * const' dosn't work, why? Jonas.Holmsten@gmail.com C Programming 11 07-01-2007 06:16 PM



Advertisments