enum members namespace clash

  • Thread starter Bilgehan.Balban
  • Start date
B

Bilgehan.Balban

Hi,

I have two different enum definitions with members of same name. The
compiler complains about duplicate definitions. Is this expected
behaviour?

Can't I have same-named fields in different enum definitions? I think
it should have been perfectly valid to do that. Its a stupid limitation
to have to define disjoint enum symbol definitions. This is like having
to have disjoint member names in structures.

Bahadir
 
P

Paul Mesken

Hi,

I have two different enum definitions with members of same name. The
compiler complains about duplicate definitions. Is this expected
behaviour?

Yes, enumeration constants are in one and the same namespace (which
they share with functions, variables and typedef names).

See 1.29 from the FAQ.
 
P

pete

Hi,

I have two different enum definitions with members of same name. The
compiler complains about duplicate definitions. Is this expected
behaviour?

Can't I have same-named fields in different enum definitions? I think
it should have been perfectly valid to do that.
Its a stupid limitation
to have to define disjoint enum symbol definitions.
This is like having
to have disjoint member names in structures.

Not really. You have no way of knowing which enum
a member belongs to, if members have the same name.

enum forward {ZERO, ONE};
enum backward{ONE, ZERO};

return ZERO;

Perhaps,
if your enum members have the same name at the same value,
you could do better with only one enum?
 
B

Ben Pfaff

I have two different enum definitions with members of same name. The
compiler complains about duplicate definitions. Is this expected
behaviour?

Yes.
Can't I have same-named fields in different enum definitions?
No.

I think it should have been perfectly valid to do that. Its a
stupid limitation to have to define disjoint enum symbol
definitions. This is like having to have disjoint member names
in structures.

You could always switch to C++. It has features that can do what
you want. Short of that, the standard practice is to use a
unique prefix for each enumerated type.
 
A

August Karlstrom

Hi,

I have two different enum definitions with members of same name. The
compiler complains about duplicate definitions. Is this expected
behaviour?

Can't I have same-named fields in different enum definitions? I think
it should have been perfectly valid to do that. Its a stupid limitation
to have to define disjoint enum symbol definitions. This is like having
to have disjoint member names in structures.

Bahadir

Enumeration constants in C are of type `int' and enumeration constant
identifiers are unqualified when used. If the same identifier occurs in
different enumerations there is no way for the compiler to know which
one to use.


-- August
 
A

August Karlstrom

August said:
Enumeration constants in C are of type `int' and enumeration constant
identifiers are unqualified when used. If the same identifier occurs in
different enumerations there is no way for the compiler to know which
one to use.

Which brings us to the question why enumerations in C aren't qualified.
Probably because that way things would get rather verbose:

f(SomeEnum.A_CONSTANT | SomeEnum.ANOTHER_CONSTANT
| SomeEnum.A_THIRD_CONSTANT);

rather than

f(A_CONSTANT | ANOTHER_CONSTANT | A_THIRD_CONSTANT);


-- August
 
A

August Karlstrom

Hi,

I have two different enum definitions with members of same name. The
compiler complains about duplicate definitions. Is this expected
behaviour?

Can't I have same-named fields in different enum definitions? I think
it should have been perfectly valid to do that. Its a stupid limitation
to have to define disjoint enum symbol definitions. This is like having
to have disjoint member names in structures.

Another strategy is to forget the `enum' feature and use plain integer
constants (I use double quotes for these pseudo enumerations from now
on). As long as all "enumeration" constants have distinct values, there
is no problem with sharing a constant between different "enumerations".
This is also a safer approach since if a client uses an "enumeration"
constant from the wrong "enumeration" it will be detected.


-- August
 
K

Keith Thompson

August Karlstrom said:
Which brings us to the question why enumerations in C aren't
qualified. Probably because that way things would get rather verbose:

f(SomeEnum.A_CONSTANT | SomeEnum.ANOTHER_CONSTANT
| SomeEnum.A_THIRD_CONSTANT);

rather than

f(A_CONSTANT | ANOTHER_CONSTANT | A_THIRD_CONSTANT);

The language *could* have been defined so that an enumeration constant
can be used without qualification if there's no ambiguity, with some
kind of qualification syntax to be used if there's another constant of
the same name. There are languages that do this. C, unsurprisingly,
isn't one of them.
 
A

August Karlstrom

Keith said:
The language *could* have been defined so that an enumeration constant
can be used without qualification if there's no ambiguity, with some
kind of qualification syntax to be used if there's another constant of
the same name. There are languages that do this. C, unsurprisingly,
isn't one of them.

What language do you have in mind?
 
K

Keith Thompson

August Karlstrom said:
What language do you have in mind?

<OT>
Ada.

Given a type declaration
type Enum is (Zero, One, Two);
each constant is equivalent to a function with no parameters returning
Enum. (Ada doesn't use empty parentheses for parameterless function
calls.) Enumeration constants aren't really implemented as functions,
and they can be used in constant expressions, but it allows all the
overloading rules that apply to functions to apply to enumeration
constants.
</OT>

Using the same approach in C would violate the "Spirit of C", I think.
Using another approach that's specific to enum types (and inventing a
syntax for the qualification) probably wouldn't be worth the effort.
 
M

Michael Wojcik

What language do you have in mind?

COBOL does this for its equivalent of structure members and the like.
(Whether it does it for all "enumeration constants" is a bit less
clear. I'm pretty sure level-88s are scoped and support both implicit
and explicit qualification. I don't think level-78s do, but those
are a Micro Focus extension, not part of the standard language.)

So in COBOL you only need the item name if it's unique; if not, you
have to qualify it.

ObC: I recently had quite a tussle with someone in comp.lang.cobol
over whether this difference between COBOL and C counted in favor of
the former or the latter - or rather whether C was flawed by its lack
of implicit qualification. I'm glad that C requires explicit
qualification; the small additional cost in writing code is more than
recovered when maintaining it, I think. Making the maintenance
programmer guess what variable is being referenced is not a good
move, in my book.

On the same note, I'm just as happy that C doesn't have Pascal's WITH
construct. While that would occasionally clean up some bits of code,
it can produce some rather hairy ambiguities, too.

Of course, C99 gives us compound literals with designations, which
provides some of the syntactic sugar of implicit qualification and
WITH, but in a more restricted and so perhaps somewhat cleaner way.

--
Michael Wojcik (e-mail address removed)

Be sure to push the button of the bottom, and push the button of the
settlement page indicated next only once, there is fear of the bottom
rhinoceros multiplex lesson money. -- Sukebe Net
 
M

Michael Mair

Others have commented on this already; usually, you work with prefixes
which make it harder to get enumeration constant names to clash.

Another strategy is to forget the `enum' feature and use plain integer
constants (I use double quotes for these pseudo enumerations from now
on). As long as all "enumeration" constants have distinct values, there
is no problem with sharing a constant between different "enumerations".
This is also a safer approach since if a client uses an "enumeration"
constant from the wrong "enumeration" it will be detected.

Usually, enum is a safe way to go because it does keep the values
distinct for you. Thus, if you have to insert another constant between
to certain constants, you do not have to adjust the values manually
and cannot make any mistakes there.
I do not see the advantages of your approach; maybe you can give a
little example... ?


Cheers
Michael
 
A

August Karlstrom

Michael said:
Others have commented on this already; usually, you work with prefixes
which make it harder to get enumeration constant names to clash.




Usually, enum is a safe way to go because it does keep the values
distinct for you. Thus, if you have to insert another constant between
to certain constants, you do not have to adjust the values manually
and cannot make any mistakes there.
I do not see the advantages of your approach; maybe you can give a
little example... ?

$ cat test.c
#include <stdio.h>

enum e1 {C1};
enum e2 {C2};

void f(enum e1 e)
{
switch (e) {
case C1:
printf("Hi I'm function f, I think I'm dealing with e = C1\n");
break;
}
}


int main(void)
{
f(C2);
return 0;
}
$ ./test
Hi I'm function f, I think I'm dealing with e = C1


-- August
 
M

Michael Mair

August said:
$ cat test.c
#include <stdio.h>

enum e1 {C1};
enum e2 {C2};

void f(enum e1 e)
{
switch (e) {
case C1:
printf("Hi I'm function f, I think I'm dealing with e = C1\n");
break;
}
}


int main(void)
{
f(C2);
return 0;
}
$ ./test
Hi I'm function f, I think I'm dealing with e = C1

Thanks for the example -- now I have understood what you mean.

BTW: My build process includes
$ splint test.c
....
Function f expects arg 1 to be enum e1 gets enum e2 { C2 }: C2
Types are incompatible
....
and would have caught this one.

However, if one wants globally distinct integer values, I
would once more suggest an enumeration:

enum AllTheConstants {
E1_START,
E1_C1 = E1_START,
....
E1_SOMETHING,
E1_END = E1_SOMETHING,

E2_START,
E2_C2 = E2_START,
.....
};


Cheers
Michael
 
A

August Karlstrom

Michael said:
Thanks for the example -- now I have understood what you mean.

BTW: My build process includes
$ splint test.c
....
Function f expects arg 1 to be enum e1 gets enum e2 { C2 }: C2
Types are incompatible
....
and would have caught this one.

Yes, you're right, I noticed that myself. A lint program is more or less
mandatory for serious development.
However, if one wants globally distinct integer values, I
would once more suggest an enumeration:

enum AllTheConstants {
E1_START,
E1_C1 = E1_START,
....
E1_SOMETHING,
E1_END = E1_SOMETHING,

E2_START,
E2_C2 = E2_START,
....
};

To sum it up:

Separate enums and lint checking: The best approach, the only drawback
being that different enums cannot share the same identifier. In that
case the constants have to be prefixed.

Macro constants with distinct values: Second best. No static type
checking possible (not even by lint) but wrong usage will at least lead
to a runtime exception (if the program has been carefully designed that
is). For clarity a type synonym can be introduced, e.g. `typedef int Color'.

Separate enums without lint checking: Worst. My example above
illustrates the problem.


-- August
 
K

Keith Thompson

Ari Lukumies said:
C++ or D?

I don't know how C++ deals with this, and there have been several
languages called "D" (I'm not familiar with any of them).

I was thinking of another language whose name is a hexadecimal
palindrome: Ada.
 
M

Michael Wojcik

Separate enums without lint checking: Worst. My example above
illustrates the problem.

I don't find this example compelling. Enumerations permit both better
naming conventions and separate value ranges; your example is simply
one of poor programmer decisions.

I don't see that you've made any case for the superiority of macro
constants over enumerations under any conditions. (There are some
cases where macro constants can be used but enumerations cannot, for
syntactic reasons, but that's not what we're discussing here.)

--
Michael Wojcik (e-mail address removed)

Advertising Copy in a Second Language Dept.:
The precious ovum itself is proof of the oath sworn to those who set
eyes upon Mokona: Your wishes will be granted if you are able to invest
it with eternal radiance... -- Noriyuki Zinguzi
 
B

Ben Pfaff

I don't see that you've made any case for the superiority of macro
constants over enumerations under any conditions.

Macro can expand to expressions of types other than `int'.
 

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

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top