Date: Sat, 25 Apr 2026 20:10:20 +1200
Hi all.
I believe inheritance should have two different mechanics:
1. undefined values.
2. defined values.
For defined values, it is quite easy:
Use them like ordinary class members' initialisation.
for example:
a)
enum class Fruit { Apple =1, Grape =2, Orange =3 };
enum class Color { Red =1, Orange =2, Yellow = 3 };
enum class Thing : using Fruit, Color { Red = 3, Orange = 4, Yellow = 5};
compiler result:
Thing::Orange = 4
//access for inherited value
Thing::Fruit::Orange = 3,
Thing::Red = 3
Thing::Fruit.Apple = 1
b)
enum class Fruit { Apple =1, Grape =2, Orange =3 };
enum class Color { Red =1, Orange =2, Yellow =3 };
enum class Thing : using Fruit, Color {};
compiler errors: both enums have the same values.
both enums have the same field: Orange
For undefined... the compiler needs to determine values for all the
enums, and they should not have cross-sections. If it is not possible,
make an error.
For example:
a)
enum class Fruit { Apple, Grape, Mango};
enum class Color { Red, Orange, Yellow };
enum class Thing : using Fruit, Color {};
Fruit::Apple = 1
Color::Red = 4
Thing::Yellow = 6
b)
enum class Chars: unsigned char{ a, b, c... ,Я}; //255 elements
enum class Numbers: unsigned char{I, II, II, IV... XLX} // 255 elements
enum class CharAndNumbers: using Chars, Numbers
compiler error: too many elements for char
I think these mechanics should work.
Kind regards,
Dmitrii Shabalin.
сб, 25 апр. 2026 г. в 09:09, Arthur O'Dwyer via Std-Proposals
<std-proposals_at_[hidden]>:
>
> 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 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 (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
I believe inheritance should have two different mechanics:
1. undefined values.
2. defined values.
For defined values, it is quite easy:
Use them like ordinary class members' initialisation.
for example:
a)
enum class Fruit { Apple =1, Grape =2, Orange =3 };
enum class Color { Red =1, Orange =2, Yellow = 3 };
enum class Thing : using Fruit, Color { Red = 3, Orange = 4, Yellow = 5};
compiler result:
Thing::Orange = 4
//access for inherited value
Thing::Fruit::Orange = 3,
Thing::Red = 3
Thing::Fruit.Apple = 1
b)
enum class Fruit { Apple =1, Grape =2, Orange =3 };
enum class Color { Red =1, Orange =2, Yellow =3 };
enum class Thing : using Fruit, Color {};
compiler errors: both enums have the same values.
both enums have the same field: Orange
For undefined... the compiler needs to determine values for all the
enums, and they should not have cross-sections. If it is not possible,
make an error.
For example:
a)
enum class Fruit { Apple, Grape, Mango};
enum class Color { Red, Orange, Yellow };
enum class Thing : using Fruit, Color {};
Fruit::Apple = 1
Color::Red = 4
Thing::Yellow = 6
b)
enum class Chars: unsigned char{ a, b, c... ,Я}; //255 elements
enum class Numbers: unsigned char{I, II, II, IV... XLX} // 255 elements
enum class CharAndNumbers: using Chars, Numbers
compiler error: too many elements for char
I think these mechanics should work.
Kind regards,
Dmitrii Shabalin.
сб, 25 апр. 2026 г. в 09:09, Arthur O'Dwyer via Std-Proposals
<std-proposals_at_[hidden]>:
>
> 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 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 (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
Received on 2026-04-25 08:10:35
