C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Add inheritance for Enum Class enumerations

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Fri, 24 Apr 2026 17:09:33 -0400
On Fri, Apr 24, 2026 at 4:00 PM Gašper Ažman via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Note that `using enum` exists and probably does what you need.
>

I don't think "using enum" does what Andrey wants — because I think Andrey
is trying to describe this other common problem instead. This
/r/ProgrammingLanguages thread
<https://www.reddit.com/r/ProgrammingLanguages/comments/rk1y4u/extending_enums/>
calls it "extending enums."
Here's some lightly-anonymized code from a real (DNS-related) codebase:

    enum HttpServerStat {
        TLS_HANDSHAKES,
        TLS_HANDSHAKE_ERRORS,
        TLS_HANDSHAKE_TIMEOUTS,
        [...]
        RESPONSE_DROPS,
        MAX_HTTP_SERVER_STAT_ID
    };

    enum HttpStat {
        // Extends HttpServerStat
        QUERY_COUNT_HTTP = MAX_HTTP_SERVER_STAT_ID,
        QUERY_BYTES_HTTP,
        RESPONSE_COUNT_HTTP,
        RESPONSE_BYTES_HTTP,
        [...]
        MAX_HTTP_STAT_ID
    };

    enum ODoHStat {
        // Extends HttpStat
        ODOH_QUERY_COUNT = MAX_HTTP_STAT_ID,
        ODOH_QUERY_BYTES,
        [...]
        ODOH_4XX_RESPONSE,
        MAX_ODOH_STAT_ID
    };

(Sidebar: We had to make some very minor changes to the users of this code
for C++20, which tightened restrictions on cross-enum arithmetic and
comparison.)
The idea is that ODoHStat "extends" HttpStat in the same way that
std::partial_ordering "extends" std::strong_ordering. Every value in the
domain of HttpStat is also in the domain of ODoHStat (although the reverse
is not true).
Notice that this is the opposite of what class inheritance means! When a
*class* ODoHStat *derives* from HttpStat then we say that every object of
type ODoHStat is an object of type HttpStat (not the reverse).

What we really want to be able to say here is something like
    enum class ODoHStat : using HttpStat {
        ODOH_QUERY_COUNT = MAX_HTTP_STAT_ID,
        ODOH_QUERY_BYTES,
        [...]
        ODOH_4XX_RESPONSE,
        MAX_ODOH_STAT_ID
    };
Again, notice the inappropriateness of "inheritance" syntax here.
    enum ODoHStat : HttpStat { // NO!
Because that syntax already has a meaning for enum declarations: it's
"HttpStat is the underlying type of ODoHStat; we guarantee that all values
of type ODoHStat will fit into an HttpStat." Which is *not at all* what we
mean here; in fact we mean the opposite: here we guarantee that all values
of type *HttpStat* will fit into an *ODoHStat*.

This fantasy feature would permit us to use `enum class`, and expose all
the enumerators of the "parent" enum as members of the "child", thus:
    ODoHStat e = ODoHStat::QUERY_COUNT_HTTP;
Today, we can't do that. We can either avoid scoped enums altogether, or
else we have to write
    ODoHStat e = static_cast<ODoHStat>(HttpStat::QUERY_COUNT_HTTP);

If we got such a facility:

(1) We would not want to permit the "child" enum to just start listing new
enumerators without an initializer for the first one:
    enum class ODoHStat : using HttpStat { ODOH_QUERY_COUNT,
ODOH_QUERY_BYTES, [...] // NO!
because what would they start numbering at — zero?
one-more-than-the-parent-enum's-highest-enumerator?
std::bit_ceil-of-one-more-than-the-parent-enum's-highest-enumerator? None
of these are safe answers. The only safe pattern is as we do in the code
above: start where the parent enum tells you to start. Even then, this is
super fragile: if we add a new enumerator to HttpStat, that will increment
the values of ODoHStat's enumerators too. Arguably the author of ODoHStat
knew what they were signing up for when they used this facility?

(2) The facility does not seem to permit "multiple inheritance," or if it
does, the semantics might be surprising.
    enum class Fruit { Apple, Grape, Orange };
    enum class Color { Red, Orange, Yellow };
    enum class Thing : using Fruit, Color {};
      // both Thing::Apple and Thing::Red have value zero, right?
      // does Thing::Orange exist? what is its value?

Anyway, I'm sure "extending enums" has been proposed before, but I haven't
yet found where. N1513 Improving Enumeration Types
<http://www2.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1513.pdf> (2003)
sketches several ideas re enums, but not this one.

my $.02,
–Arthur

Received on 2026-04-24 21:09:51