reusing identifier in two enums

I

ImpalerCore

I have two related but separate enumerations where I'd like to use the
same identifier to represent an invalid type.

enum typeA
{
invalid_type = -1,
typeA = 0,
typeB = 1,
...
};

enum type0
{
invalid_type = -1,
type0 = 0,
type1 = 1,
...
};

Is it okay to for these enumerations to share the same identifier as
long as they have the same value in all enumerations that use them?
From my limited experience with the standard, I couldn't pull out
whether this was defined behavior.
 
M

Morris Keesan

I have two related but separate enumerations where I'd like to use the
same identifier to represent an invalid type.

enum typeA
{
invalid_type = -1,
typeA = 0,
typeB = 1,
...
};

enum type0
{
invalid_type = -1,
type0 = 0,
type1 = 1,
...
};

Is it okay to for these enumerations to share the same identifier as
long as they have the same value in all enumerations that use them?
From my limited experience with the standard, I couldn't pull out
whether this was defined behavior.

It looks like it's forbidden. From the 1999 standard, 6.7.2.2 Enumeration
Specifiers, paragraph 3 says, "The identifiers in an enumerator list are
declared as constants that have type int and may appear wherever such are
permitted.107)" and footnote 107 says, "107) Thus, the identifiers of
enumeration constants declared in the same scope shall all be distinct from
each other and from other identifiers declared in ordinary declarators."

The version of gcc I have on my machine agrees:
error: redeclaration of enumerator 'invalid_type'
 
K

Keith Thompson

ImpalerCore said:
I have two related but separate enumerations where I'd like to use the
same identifier to represent an invalid type.

enum typeA
{
invalid_type = -1,
typeA = 0,
typeB = 1,
...
};

enum type0
{
invalid_type = -1,
type0 = 0,
type1 = 1,
...
};

Is it okay to for these enumerations to share the same identifier as
long as they have the same value in all enumerations that use them?
From my limited experience with the standard, I couldn't pull out
whether this was defined behavior.

It's a constraint violation, assuming both types are declared in the
same scope.

Quoting N1570:

6.7.2.2:
The identifiers in an enumerator list are declared as constants that
have type int and may appear wherever such are permitted.

So your declaration of invalid_type is equivalent to:

const int invalid_type = -1;

A footnote makes it even clearer:

Thus, the identifiers of enumeration constants declared in the same
scope shall all be distinct from each other and from other
identifiers declared in ordinary declarators.

And 6.7p3 says:

If an identifier has no linkage, there shall be no more than one
declaration of the identifier (in a declarator or type specifier)
with the same scope and in the same name space, except that:
[...]
(The exceptions don't apply in this case.)

This is a constraint, so a diagnostic is required. A compiler *could*
issue a warning and accept the declaration anyway, but I don't know of
any that do so.

If you had tried to compile your example, the compiler would have
rejected it; for example, gcc gives me:

c.c:10:18: error: redeclaration of enumerator ‘invalid_type’
c.c:3:18: note: previous definition of ‘invalid_type’ was here

This doesn't prove that it's invalid (it *could* be a compiler bug), but
it's a strong indication.

You could declare the "invalid_type" enumeration constant with a
different name in each enum type, then declare a single:

enum { invalid_type = -1 };

and use that identifier everywhere. Enumeration constants aren't as
strongly associated with their types as you might expect; they're all of
type int, so there's no real type checking. (C++ has different rules,
so if you want your code to be compatible with C++ for some reason
you'll have to be more careful.)
 
I

ImpalerCore

It looks like it's forbidden.  From the 1999 standard, 6.7.2.2 Enumeration
Specifiers, paragraph 3 says, "The identifiers in an enumerator list are
declared as constants that have type int and may appear wherever such are
permitted.107)" and footnote 107 says, "107) Thus, the identifiers of
enumeration constants declared in the same scope shall all be distinct from
each other and from other identifiers declared in ordinary declarators."

The version of gcc I have on my machine agrees:
     error: redeclaration of enumerator 'invalid_type'

I got the same compiler error. I guess I didn't notice the duplicate
since I declared the identifier in two separate header files but I
never had any test code that directly used it.

Thanks,
John D.
 
I

ImpalerCore

[snip]
You could declare the "invalid_type" enumeration constant with a
different name in each enum type, then declare a single:

    enum { invalid_type = -1 };

and use that identifier everywhere.  Enumeration constants aren't as
strongly associated with their types as you might expect; they're all of
type int, so there's no real type checking.  (C++ has different rules,
so if you want your code to be compatible with C++ for some reason
you'll have to be more careful.)

Thanks for the idea. I'll keep it in mind.

Best regards,
John D.
 
J

Joe keane

I have two related but separate enumerations where I'd like to use the
same identifier to represent an invalid type.

This is basically subtypes which define the valid values, and a
supertype where one can only set an invalid value, and test for that.

class basic_type
{
static const int invalid = -1;
int x;

bool is_valid() const { return x >= 0; }
void set_invalid() { x = invalid; }
};

class color_type : basic_type
{
enum color { red = 1, orange = 13, yellow = 3, ... };

bool is_red() const { return x == red; }
void set_red() { x = red; }
...
};

Decrement the language:

#define BASIC_INVALID_TYPE -1
#define BASIC_TYPE_IS_VALID(X) ((X) >= 0)
#define BASIC_TYPE_SET_INVALID(X) ((X) = BASIC_INVALID_TYPE)
 
J

Jens Gustedt

Am 03/21/2012 03:45 AM, schrieb Joe keane:
This is basically subtypes which define the valid values, and a
supertype where one can only set an invalid value, and test for that.

subtype ?
class basic_type
{
static const int invalid = -1;
int x;

bool is_valid() const { return x >= 0; }
void set_invalid() { x = invalid; }
};

class color_type : basic_type
{
enum color { red = 1, orange = 13, yellow = 3, ... };

bool is_red() const { return x == red; }
void set_red() { x = red; }
...
};

wrong language? C doesn't know anything of "class", inheritance and
things like that
Decrement the language:

You mean C-- ?

Jens
 

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,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top