Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any rule about why is the redefinition of the enumerator ill-formed?

Consider this example

enum class A{
    a = 0,
    a = 1
};

The compilers will report an error, which is the "redefinition of enumerator 'a'". However, [basic.def.odr#1] does not have any requirement for the enumerator

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, template, default argument for a parameter (for a function in a given scope), or default template argument.

I wonder which normative rule, in the standard, is restricting that?

like image 978
xmh0511 Avatar asked Jul 31 '21 13:07

xmh0511


1 Answers

Original answer

Yes, as of now, the One Definition Rule in the C++ standard doesn't include enumerators.

However, the "the second a is a redeclaration of the first a" explanation doesn't work too.
From [dcl.enum#nt:enumerator-list] we can know that an enumerator-list is a list of enumerator-definition, so they're all definitions.

enumerator-list:
    enumerator-definition
    enumerator-list , enumerator-definition

Why isn't enumerator included in the one definition rule? That's likely an oversight on the standard committee's part. Considering that in C, enumerators are prohibited from redefinition.

From the draft of C99, Section 6.7:

5

A declaration specifies the interpretation and attributes of a set of identifiers. A definition of an identifier is a declaration for that identifier that:
— for an object, causes storage to be reserved for that object;
— for a function, includes the function body;101)
— for an enumeration constant or typedef name, is the (only) declaration of the identifier.

From Section 6.7.2.2 we can see an enumerator is an enumeration-constant:

enumerator:
    enumeration-constant
    enumeration-constant = constant-expression

And from 6.7.2.2 one can also infer that all enumerator in a enumerator-list will always be not only declared but also defined.

3

The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted. An enumerator with = defines its enumeration constant as the value of the constant expression. If the first enumerator has no =, the value of its enumeration constant is 0. Each subsequent enumerator with no = defines its enumeration constant as the value of the constant expression obtained by adding 1 to the value of the previous enumeration constant. (The use of enumerators with = may produce enumeration constants with values that duplicate other values in the same enumeration.) The enumerators of an enumeration are also known as its members.

So in C, you can't define an enumerator with the same identifier for more than one time, because if you can, it will no longer be the only declaration of the identifier, which makes it an invalid definition according to Section 6.7.

The behaviour in C might be why almost all C++ compiler prohibits redefinition of enumerator, and it is likely the intended or expected behaviour of C++ too.

Update

Update 2022-02-16: I've submitted an issue regarding this question following the procedure detailed in https://isocpp.org/std/submit-issue. It's been accepted and is now Issue 2530.

like image 172
Miigon Avatar answered Nov 15 '22 11:11

Miigon