Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

§7.1.6.3/1 (C++14) doesn't accept the construction in the second snippet below. Why is this?

First part:

I'm studying in some detail opaque-enum-declarations and elaborated-type-specifiers for a few days already, and I really would like somebody to confirm this. GCC and VS2013 don't compile this code (clang does) and I believe clang is in accordance with §7.1.6.3/1, as enum E is an elaborated-type-specifier that is not the sole constituent of the declaration enum E e = E::b;. Is my analysis correct?

#include <iostream>
enum class E : char {a = 'a', b};
int E;
enum E e = E::b;        // Doesn't compile in GCC and VS2013
int main()
{
    std::cout << (char)(e) << '\n';
}

Second part:

The snippet below, which is very similar to the one above, doesn't compile. I understand why it doesn't (the elaborated-type-specifier enum E is the sole constituent of the declaration enum E; and §7.1.6.3/1 doesn't allow this). What I'd like to know is why can't the compiler accept this construction?

#include <iostream>
enum class E : char {a = 'a', b};
int E;
enum E;                 // This doesn't compile.
E e = E::b;        
int main()
{
    std::cout << (char)(e) << '\n';
}
like image 932
Belloc Avatar asked Mar 20 '15 21:03

Belloc


1 Answers

N4140 [basic.scope.hiding]/2:

A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.

It would appear the the declaration of int E hides the name of the enumeration E in the global scope after the int's point of declaration. However, the name E::b is a qualified-id with nested-name-specifier of E::, so the rules for qualified name lookup apply. In particular, [basic.lookup.qual]/1:

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. If a :: scope resolution operator in a nested-name-specifier is not preceded by a decltype-specifier, lookup of the name preceding that :: considers only namespaces, types, and templates whose specializations are types. [emphasis added.] If the name found does not designate a namespace or a class, enumeration, or dependent type, the program is ill-formed.

So clang is conforming, GCC and MSVC are not.

like image 59
Casey Avatar answered Oct 22 '22 10:10

Casey