This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4634. Underlying bool type in make_signed and make_unsigned

Section: 21.3.8.4 [meta.trans.sign] Status: New Submitter: Jan Schultke Opened: 2026-10-23 Last modified: 2026-10-31

Priority: Not Prioritized

View all issues with New status.

Discussion:

The intent is for make_signed and make_unsigned to reject bool, which is enforced by their Mandates element. However, enumerations whose underlying type is bool are accepted (presumably by accident), with implementation divergence:

using SB = std::make_signed_t<bool>; // all reject
enum E : bool {};
using SE = std::make_signed_t<E>;    // libc++ rejects, others yield signed char

Proposed resolution:

This wording is relative to N5054.

  1. Modify 21.3.8.4 [meta.trans.sign] as indicated:

    Table 59 — Sign modifications [tab:meta.trans.sign]
    Template Comments
    template <class T>
    struct make_signed;
    If T is a (possibly cv-qualified) signed integer type (6.9.3 [basic.fundamental]) then the
    member typedef type denotes T; otherwise, if T is a (possibly
    cv-qualified) unsigned integer type then type denotes the
    corresponding signed integer type, with the same cv-qualifiers as T;
    otherwise, type denotes the signed integer type with smallest
    rank (6.9.7 [conv.rank]) for which sizeof(T) == sizeof(type), with the same
    cv-qualifiers as T.
    Mandates: T is either an integral or enumeration type other than cv bool
    or an enumeration type whose underlying type is not bool.
    template <class T>
    struct make_unsigned;
    If T is a (possibly cv-qualified) unsigned integer type (6.9.3 [basic.fundamental]) then the
    member typedef type denotes T; otherwise, if T is a (possibly
    cv-qualified) signed integer type then type denotes the corresponding
    unsigned integer type, with the same cv-qualifiers as T; otherwise,
    type denotes the unsigned integer type with smallest rank (6.9.7 [conv.rank]) for
    which sizeof(T) == sizeof(type), with the same cv-qualifiers as
    T.
    Mandates: T is either an integral or enumeration type other than cv bool
    or an enumeration type whose underlying type is not bool.