Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 Accessing Unscoped Enumerators with Qualified Name

I have a question about the wording of the C++11 standard as I have not had to dig into it frequently in the past and recently found myself confused on the (admittedly unimportant) topic of unscoped enums.

I recently came across some code in a code review that was using an unscoped enum but accessing the enumerators using fully qualified names, like this:

enum SomeEnum
{
  EnumA,
  ...
};

void foo()
{
  SomeEnum x = SomeEnum::EnumA;
}

I was certain that this didn't work and that SomeEnum had to be an enum class for this behavior, but, sure enough, it compiled cleanly.

Peeking into the C++11 standard, I at first thought that the standard agreed with me:

§ 7.2 Enumeration Declarations: Each enum-name and each unscoped enumerator is declared in the scope that immediately contains the enum-specifier. Each scoped enumerator is declared in the scope of the enumeration.

This appears to me to indicate that unscoped enumerators are declared only at the immediately containing scope of the enum itself. It doesn't mention that they are also declared at the enumeration scope.

However, a little further down, the standard does include an example that shows accessing an unscoped enumerator using the fully qualified name.

A quick bit of googling and searching on SO gave me a small number of places that assert that the standard does now allow the fully qualified name, but there isn't much discussion. Is this just weak wording in the spec that is clarified by the example, or is there something else I'm missing?

Again, this isn't earth shattering, but I'm hoping someone can set me straight on my reading of the standard and I can learn something that may be useful in a future situation.

like image 367
Derek Miller Avatar asked Nov 04 '14 20:11

Derek Miller


1 Answers

The quote you are looking for from the draft C++11 standard is from section 5.1 Primary expressions which in paragraph 10 says:

A nested-name-specifier that denotes an enumeration (7.2), followed by the name of an enumerator of that enumeration, is a qualified-id that refers to the enumerator. The result is the enumerator. The type of the result is the type of the enumeration. The result is a prvalue.

It does not restrict the use to scoped enumerations and so the example in section 7.2 Enumeration declarations:

enum direction { left='l', right='r' };

void g() {
   direction d; // OK
   d = left; // OK
   d = direction::right; // OK
}

is entirely consistent. This is also consistent with section 3.4.3 Qualified name lookup which says:

The name of a class or namespace member or enumerator can be referred to after the :: scope resolution operator (5.1) applied to a nested-name-specifier that denotes its class, namespace, or enumeration. [...]

and:

A name prefixed by a nested-name-specifier that nominates an enumeration type shall represent an enumerator of that enumeration.

again, there is nothing restricting this behavior to scoped enumerations.

Examples are non normative but as long as they don't conflict with the normative text then they should be considered a good guideline.

like image 64
Shafik Yaghmour Avatar answered Oct 17 '22 01:10

Shafik Yaghmour