Date: Sat, 25 Apr 2026 15:16:25 +0900
2 is somewhat facilitated by
https://isocpp.org/files/papers/P4033R0.html
Sent from Gmail Mobile
On Sat, Apr 25, 2026 at 14:42 Simon Schröder via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> Sometimes we are using enums just because it is the only thing that we
> have. I‘m not entirely sure if we need to extend enums to get some of the
> things we want. Specifically, I‘m thinking of two things that might give
> some inspiration of how things could be solved.
>
> 1. I‘m thinking about std::expected, std::error_code, and
> std::error_condition. Here, we can create a hierarchy of error codes that
> can be used together. There is a way to specify how error codes decay into
> each other. IIRC both error codes and error conditions are backed by enums.
> However, those enums can have overlapping values. The disadvantage probably
> is that we cannot switch over these. I would hope that we get pattern
> matching and that is possible with pattern matching instead. Currently,
> using both error codes and error conditions requires allot of boilerplate
> code. Hopefully, future reflection with queue injection can help with this.
> This is not meant as a solution to the original problem at hand, but as an
> inspiration for how we might think differently about enum hierarchies.
>
> 2. In many cases we might want to use enums for flags. Currently, this is
> quite cumbersome to write. Years ago Herb Sutter talked about his vision of
> metaclasses in the context of reflection. One of his examples was to write
> a metaclass that implements flags properly (using power-of-two for enum
> values). In the same way we might write some metaclass in the future that
> does some form of inheritance for enums. Actually, I‘m thinking if we
> *want* different enums to be convertible between each other when using
> inheritance. Or with reflection we might just specify another enum and
> reflection will copy all definitions from the other enum into our enum. If
> we want to be able to convert from a parent enum class, we would need to
> specify some conversion operators. Especially with metaclasses (I hope we
> get them some time) we would have ways of making this work.
>
> On Apr 24, 2026, at 11:09 PM, Arthur O'Dwyer via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>
>
> 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
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
https://isocpp.org/files/papers/P4033R0.html
Sent from Gmail Mobile
On Sat, Apr 25, 2026 at 14:42 Simon Schröder via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> Sometimes we are using enums just because it is the only thing that we
> have. I‘m not entirely sure if we need to extend enums to get some of the
> things we want. Specifically, I‘m thinking of two things that might give
> some inspiration of how things could be solved.
>
> 1. I‘m thinking about std::expected, std::error_code, and
> std::error_condition. Here, we can create a hierarchy of error codes that
> can be used together. There is a way to specify how error codes decay into
> each other. IIRC both error codes and error conditions are backed by enums.
> However, those enums can have overlapping values. The disadvantage probably
> is that we cannot switch over these. I would hope that we get pattern
> matching and that is possible with pattern matching instead. Currently,
> using both error codes and error conditions requires allot of boilerplate
> code. Hopefully, future reflection with queue injection can help with this.
> This is not meant as a solution to the original problem at hand, but as an
> inspiration for how we might think differently about enum hierarchies.
>
> 2. In many cases we might want to use enums for flags. Currently, this is
> quite cumbersome to write. Years ago Herb Sutter talked about his vision of
> metaclasses in the context of reflection. One of his examples was to write
> a metaclass that implements flags properly (using power-of-two for enum
> values). In the same way we might write some metaclass in the future that
> does some form of inheritance for enums. Actually, I‘m thinking if we
> *want* different enums to be convertible between each other when using
> inheritance. Or with reflection we might just specify another enum and
> reflection will copy all definitions from the other enum into our enum. If
> we want to be able to convert from a parent enum class, we would need to
> specify some conversion operators. Especially with metaclasses (I hope we
> get them some time) we would have ways of making this work.
>
> On Apr 24, 2026, at 11:09 PM, Arthur O'Dwyer via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>
>
> 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
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2026-04-25 06:16:39
