Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do scoped enums allow use of | operator when initializing using previously assigned values?

I'm converting unscoped enumerations to scoped enumerations, and have run across a puzzle.

Stroustrup, C++ Programming Language, 4th edition, Section 8.4.1, documents that scoped enum classes are not implicitly converted to integral types, and provides code for operators | and & as an example of how to use static_cast to work around that.

Shouldn't the following initialization using the | operator on previously defined enum values be illegal?

enum class FileCopy {
    PreviousHDUs   = 1,
    CurrentHDU     = 2,
    FollowingHDUs  = 4,
    AllHDUs        = PreviousHDUs | CurrentHDU | FollowingHDUs,
    CurrentHeader  = 8
};

int main()
{
    std::cout << static_cast<int>( FileCopy::AllHDUs) << "\n";
}

I've tested this on Wandbox using both clang & gcc HEAD with --pedantic-errors, and it compiles and returns the expected output, 7. That's not to say it's legal, just that it seems to be accepted by the compilers.

Is this explicitly documented behavior? I've been unable to parse the documentation in a way that describes this behavior.

like image 254
Diab Jerius Avatar asked Aug 06 '19 15:08

Diab Jerius


People also ask

What are scoped enums?

Overview. Scoped enums (enum class/struct) are strongly typed enumerations introduced in C++11. They address several shortcomings of the old C-style (C++98) enums, mainly associated with type-safety and name collisions.

What is use of enum in C?

Enumeration or Enum in C is a special kind of data type defined by the user. It consists of constant integrals or integers that are given names by a user. The use of enum in C to name the integer values makes the entire program easy to learn, understand, and maintain by the same or even different programmer.

What are enumeration variables How are they declared what are the advantages of using them in a program?

An enumeration type declaration gives the name of the (optional) enumeration tag. And, it defines the set of named integer identifiers (called the enumeration set, enumerator constants, enumerators, or members). A variable of the enumeration type stores one of the values of the enumeration set defined by that type.

What is the use of enum in Python?

Enum is a class in python for creating enumerations, which are a set of symbolic names (members) bound to unique, constant values. The members of an enumeration can be compared by these symbolic anmes, and the enumeration itself can be iterated over.


2 Answers

[dcl.enum]/5:

... If the underlying type is fixed, the type of each enumerator prior to the closing brace is the underlying type ...

That is, each enumerator has type int until the closing brace is encountered. After that point, the enumerators have type FileCopy and you would not be able to bitwise-OR them together like this anymore.

like image 65
Brian Bi Avatar answered Oct 09 '22 14:10

Brian Bi


According to the C++17 Standard (8.5.13 Bitwise inclusive OR operator)

1 The usual arithmetic conversions (8.3) are performed; the result is the bitwise inclusive OR function of its operands. The operator applies only to integral or unscoped enumeration operands.

And (10.2 Enumeration declarations)

  1. ... For a scoped enumeration type, the underlying type is int if it is not explicitly specified. In both of these cases, the underlying type is said to be fixed. Following the closing brace of an enum-specifier, each enumerator has the type of its enumeration. If the underlying type is fixed, the type of each enumerator prior to the closing brace is the underlying type and the constant-expression in the enumerator-definition shall be a converted constant expression of the underlying type

So this is explicitly documented behavior.

like image 28
Vlad from Moscow Avatar answered Oct 09 '22 16:10

Vlad from Moscow