C++ Logo

std-proposals

Advanced search

Re: [std-proposals] A proposal on default enum initialization

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Fri, 24 Mar 2023 11:33:27 -0400
On Fri, Mar 24, 2023 at 11:17 AM Andrey Semashev via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On 3/24/23 18:05, Oleksandr Koval via Std-Proposals wrote:
> > Actually, allowing default values can break
> > existing code because right now `Enum e{};` always means e = 0, after
> > your change the value will be different.
>
> No existing code uses "default:" for marking the default enum value
> because currently this syntax is invalid. So this is not a breaking change.
>

It's a breaking change to the programmer's intuition, though, if they're
used to `T t = T();` meaning "zero-initialization" for scalar types.
It certainly interacts with Giuseppe's recent P2782 "Type trait to detect
whether a type is trivially value-initializable by zero-filling."
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2782r0.html
Right now that trait is obviously `true` in practice for all integer and
enum types, at least on sane platforms; and P2782R0 proposes that it should
be formally set in stone for integer and enum types forever.
Aleksej is proposing to make that trait not-true for *some* (but not all)
enum types.

Anyway, that's a game-ending objection to the semantics IMHO; but even
syntax-wise, we don't currently use the `default` keyword in this way at
all.
    enum E { RED, GREEN, default: BLUE=42, }; // not terribly confusing,
but not consistent with the rest of the language
The way C++ does defaults is with an equals sign:
    int foo(int x = 42); // default argument
    struct S { int x = 42; }; // default initializer
So the right syntax for the proposed semantics might be something like
    enum E : int = 42 { RED, GREEN, BLUE=42, };
except that we want to say `= BLUE` there and we can't because `BLUE` is an
unknown identifier; so perhaps
    enum E : int { RED, GREEN, BLUE, E() = BLUE };
except that that syntax already has a meaning (consider what happens if
`operator=` is overloaded and constexpr) and is ugly anyway.
Seems to me that this feature would fit in(...to the trash can) with all
other proposals around "adding member functions to enum types." What you're
doing here is simply adding a non-trivial default constructor to the enum
type:
    enum E : int {
        RED, GREEN, BLUE,
        E() : E(BLUE) {} // C++11 delegating ctor syntax; delegate to the
copy ctor which already implicitly exists(*)
    };
(*— or maybe to the ctor from int, which already exists; it depends on what
context you think we're in at this point in the source code.)

Rather than adding member functions to enums, maybe it would be more
productive to look at ways to
- derive class types *from* enum types, so that you could inherit the
enumerators and then add methods to the class in the usual way
- define value-semantic class types with nested "enumerators" quickly and
easily, without involving C-style enum types at all

my $.02,
–Arthur

Received on 2023-03-24 15:33:40