3092. Unclear semantics of enum class bitmask types

Section: 16.3.3.3.3 [bitmask.types] Status: Open Submitter: Geoffrey Romer Opened: 2018-03-26 Last modified: 2020-09-06

Priority: 3

View other active issues in [bitmask.types].

View all other issues in [bitmask.types].

View all issues with Open status.

Discussion:

[bitmask.types] specifies the semantics of a bitmask type in terms of an "exposition only" enum definition, together with some constants and overloads. Notably, it is depicted as an unscoped enum, which implies among other things that it is implicitly convertible to int_type. At least some sources treat that as normative (as of this writing, cppreference.com's documentation for BitmaskType says the expression (X & Y) != 0 is guaranteed to be well-formed), and it's hard to argue that they're wrong on the basis of the existing wording.

On the other hand, many standard library types are depicted as scoped enums, but still specified to be "bitmask types". As far as I can tell, it's impossible in library code to make a scoped enum implicitly convertible to its underlying type, and even if you could, what would be the point? Presumably the specification of those types as scoped enums is intended to have some sort of observable consequences.

In addition, some library types (notably in clause 31) are specified to be bitmask types, without indicating whether they are scoped or unscoped. It's not clear what the standard guarantees about e.g. whether they can be implicitly converted.

I assume the intent is that "bitmask type" doesn't specify an implicit conversion, or any of the other ways unscoped and scoped enums differ, but the standard doesn't actually say that. We really ought to rewrite [bitmask.types] as a requirements table, but here's a quick hack to the existing wording as a stopgap.

[2018-04-23 Priority set to 2 after discussion on the reflector.]

[2018-08-23 Batavia Issues processing]

N3110 also touches on this.

Nico to survey the enums in the library and report back on which ones should be class.

[2019 Cologne Wednesday night]

Changing existing enums to class enums is an ABI break on some platforms; current wording does not require the use of enums. See N3110.

Daniel to provide requirements tables, Jonathan to assist. Reduce priority to 3

Proposed resolution:

This wording is relative to N4727.

  1. Edit 16.3.3.3.3 [bitmask.types] as indicated:

    -2- The bitmask type bitmask can be written:

    // For exposition only.
    // int_type is an integral type capable of representing all values of the bitmask type.
    enumE bitmask : int_type {
      V0 = 1 << 0, V1 = 1 << 1, V2 = 1 << 2, V3 = 1 << 3, .....
    };
    […]
    

    -3- Here, E may represent either enum or enum class (the choice is implementation-defined unless otherwise specified), and the names C0, C1, etc. represent bitmask elements for this particular bitmask type. The zero value bitmask{} is used to represent an empty bitmask, in which no bitmask elements are set. All suchbitmask elements have distinct, nonzero values such that, for any pair Ci and Cj where ij, Ci & Ci is nonzero and Ci & Cj is zero. Additionally, the value 0 is used to represent an empty bitmask, in which no bitmask elements are set.