Search code examples
c++c++11enumsfinal

Final enum classes in C++11


I am just curious whether an enum class can be final or not ... since the compilers are giving me contradictory results.

Consider the code:

#include <iostream>

enum class some_enums final : char
{
    a = 'a', 
    b = 'b',
    c = 'c'
};

int main()
{
    some_enums aa = some_enums::a;
    std::cout << "aa=" << static_cast<char>(aa) << std::endl;
}

Compiling this with Visual Studio 2015 compiler (http://rextester.com/l/cpp_online_compiler_visual) works... however compiling it with clang (http://rextester.com/l/cpp_online_compiler_clang) gives me an error:

source_file.cpp:3:30: error: expected ';' after top level declarator
        enum class some_enums final : char

I have seen no traces of final enum classes anywhere in the standard so I give credit to clang ... however why does Visual Studio accept it in this case although it is not mentioned in MSDN (https://msdn.microsoft.com/en-us/library/2dzy4k6e.aspx) ?


Solution

  • The final specifier is used to signify that a class cannot be inherit from. Since an enum class cannot be inherited, the final specifier used in your case is useless.

    "Stollen" from here and also mention in §7.2/p1 Enumeration declarations [dcl.enum] , a class enum declaration is of the form:

    enum-key attr(optional) nested-name-specifier(optional) identifier enum-base(optional) ;
    
    • enum-key - one of enum, enum class (since C++11), or enum struct (since C++11)
    • attr (C++11) - optional sequence of any number of attributes
    • identifier - the name of the enumeration that's being declared. If present, and if this declaration is a re-declaration, it may be preceded by nested-name-specifier (since C++11): sequence of names and scope-resolution operators ::, ending with scope-resolution operator. The name can be omitted only in unscoped enumeration declarations.
    • enum-base (C++11) - colon (:), followed by a type-specifier-seq that names an integral type (if it is cv-qualified, qualifications are ignored).
    • enumerator-list - comma-separated list of enumerator definitions, each of which is either simply an identifier, which becomes the name of the enumerator, or an identifier with an initializer: identifier = constexpr. In either case, the identifier can be directly followed by an optional attribute specifier sequence. (since C++17).

    Consequently, defining an enum class with final specifier as:

    enum class some_enums final : char {
    ...
    };
    

    is not a standard form.