This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 110b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2023-01-15


172. Unsigned int as underlying type of enum

Section: 9.7.1  [dcl.enum]     Status: CD1     Submitter: Bjarne Stroustrup     Date: 26 Sep 1999

[Moved to DR at October 2002 meeting.]

According to 9.7.1 [dcl.enum] paragraph 5, the underlying type of an enum is an unspecified integral type, which could potentially be unsigned int. The promotion rules in 7.3.7 [conv.prom] paragraph 2 say that such an enumeration value used in an expression will be promoted to unsigned int. This means that a conforming implementation could give the value false for the following code:

    enum { zero };
    -1 < zero;       // might be false
This is counterintuitive. Perhaps the description of the underlying type of an enumeration should say that an unsigned underlying type can be used only if the values of the enumerators cannot be represented in the corresponding signed type. This approach would be consistent with the treatment of integral promotion of bitfields (7.3.7 [conv.prom] paragraph 3) .

On a related note, 9.7.1 [dcl.enum] paragraph 5 says,

the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int.

This specification does not allow for an enumeration like

    enum { a = -1, b = UINT_MAX };

Since each enumerator can fit in an int or unsigned int, the underlying type is required to be no larger than int, even though there is no such type that can represent all the enumerators.

Proposed resolution (04/01; obsolete, see below):

Change 9.7.1 [dcl.enum] paragraph 5 as follows:

It is implementation-defined which integral type is used as the underlying type for an enumeration except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int neither int nor unsigned int can represent all the enumerator values. Furthermore, the underlying type shall not be an unsigned type if the corresponding signed type can represent all the enumerator values.

See also issue 58.

Notes from 04/01 meeting:

It was noted that 7.3.7 [conv.prom] promotes unsigned types smaller than int to (signed) int. The signedness chosen by an implementation for small underlying types is therefore unobservable, so the last sentence of the proposed resolution above should apply only to int and larger types. This observation also prompted discussion of an alternative approach to resolving the issue, in which the bmin and bmax of the enumeration would determine the promoted type rather than the underlying type.

Proposed resolution (10/01):

Change 7.3.7 [conv.prom] paragraph 2 from

An rvalue of type wchar_t (6.8.2 [basic.fundamental]) or an enumeration type (9.7.1 [dcl.enum]) can be converted to an rvalue of the first of the following types that can represent all the values of its underlying type: int, unsigned int, long, or unsigned long.
to
An rvalue of type wchar_t (6.8.2 [basic.fundamental]) can be converted to an rvalue of the first of the following types that can represent all the values of its underlying type: int, unsigned int, long, or unsigned long. An rvalue of an enumeration type (9.7.1 [dcl.enum]) can be converted to an rvalue of the first of the following types that can represent all the values of the enumeration (i.e., the values in the range bmin to bmax as described in 9.7.1 [dcl.enum]): int, unsigned int, long, or unsigned long.