c++enumsnamespaceslanguage-lawyer

If an enum declared in a namespace is defined outside the namespace, are its enumeration values externally visible?


I think scoped enumerations are too restrictive so I have always used this method, but I found out today that it cause naming pollution in CLANG. What does the standard say about visibility?

namespace E1_space {
    enum E1: int;
}
using E1 = E1_space::E1;  // or using E1_space::E1;
enum E1_space::E1: int {
    Error
};

void foo() {
    Error; 
    // x86-64 GCC 14.2 error: 'Error' was not declared in this scope; did you mean 'P3::E1_space::Error'?
    // x64 MSVC v19.latest error C2065: 'Error': undeclared identifier
    // x86-64 CLANG 19.1.0 warning: expression result unused
}

Solution

  • It would seem the language itself (as of C++23 at least) has a bug, which makes Clang's behavior technically legal (regardless of using being present or not).

    [dcl.enum]

    12 The name of each unscoped enumerator is also bound in the scope that immediately contains the enum-specifier.

    Now, you define an unscoped enumeration and the global scope does seem to "immediately contain the enum-specifer". That is because enum-specifier is the whole enum definiton:

     enum-specifier:
         enum-head { enumerator-listopt }
         enum-head { enumerator-list , } 
    

    However, I find this totally bonkers. And while I couldn't find an issue about this with C++ Core Working Group, I don't believe that's an intended behavior.

    On the LLVM bug tracker, Richard Smith (a committee member and Clang maintainer) seems to agree as well that all compilers but Clang do the sensible thing, and both Clang as well as the language itself might need an amendment.


    After some thinking, this is likely leftover wording from pre-C++11. You couldn't forward-declare enumerations once; only enums with a fixed underlying type can be forward-declared, and that is only since C++11. So in C++03, you can't seperate definition from first declaration, making the above wording at [dcl.enum]/12 suffice.