Disallowing S() when struct S has a constructor
Quirin Schroll
qs.il.paperinik at gmail.com
Thu Sep 5 17:46:18 UTC 2024
On Friday, 30 August 2024 at 16:32:21 UTC, Jonathan M Davis wrote:
> On Friday, August 30, 2024 9:17:06 AM MDT Steven Schveighoffer
> via Digitalmars- d wrote:
>> On Thursday, 29 August 2024 at 16:44:46 UTC, Nick Treleaven
>> wrote:
>> > Should we make S() for any struct an error in the next
>> > edition?
>>
>> I have a bold suggestion instead -- let's just start having
>> default constructors.
>>
>> What's stopping us? We are on the cusp of ridding ourselves of
>> magic runtime hooks, they are all now becoming templates.
>>
>> For instance, setting the length of an array now calls a
>> template and that template could just call the default
>> constructor if it exists.
>>
>> Then this whole mess of what S() means vs S.init, or whatnot
>> becomes much more sane.
>>
>> It's something we should start thinking about and discussing.
>
> I don't know. Initialization is just simpler if default
> constructors aren't a thing. Occasionally, it would be really
> nice to have them, but the vast majority of the time, they're
> simply not needed. And there's a _lot_ of D code written with
> the assumption that they're not a thing. It's already
> problematic that we added the ability to disable default
> initialization, since most code tends to assume that that isn't
> really a thing, and it creates annoying corner cases.
> Similarly, the fact that types can declare an init member just
> causes problems, because most code assumes that that's not a
> thing (and I'd argue that it shouldn't be a thing).
The right course of action is:
- Deprecate `init`. Replace it with `default(T)` (read: “default
of `T`”) which gives you an uninitialized object of type `T` that
might or might not be usable. It can’t be hooked (unlike `init`)
because `default` is a keyword. A constructor transforms a the
`default(T)` object into an object that satisfies the invariants
of `T` if any. In general, using `default(T)` is a bad idea
unless you do it knowing full well what you’re getting.
- Allow default constructors. Those are called on `T()` or
variables declared of type `T` that are not explicitly
initialized. `T x;` calls the default constructor of `T`.
- A default constructor is only implicitly present if all data
members have a default constructor and no constructor is
explicitly defined.
- A default constructor can be explicitly set to be the generated
one using `default`: `default this();`
Initialization of a variable:
```d
T x = void; // random garbage; do not use
T y = default; // y contains T’s default; do not use, unless you
know it’s okay
T z; // default constructor runs on z; safe to use
x.__default(); // bits default(T) onto x
x.__ctor(args); // runs a constructor on x, which in general
expects that x is default(T)
```
Essentially, `T y = default;` is equivalent to `T y = void;` plus
`y.__default()`; both are `@system`.
And `T z;` is equivalent to `T z = default;` plus `z.__ctor()`
and the language knows that this isn’t inherently unsafe, i.e.
`@safe` depends on the constructor.
C++ has had default constructors forever. It’s one of the few
decisions where I’m convinced that C++ got it right and D isn’t.
“Variable declarations must be cheap” is a dogma that I’d expect
in a language like C or Zig, not in a language like D, where
frequently, safety wins over performance. The fact that I can
declare a variable in D and it might not be safe to use is a
problem.
In C++, if you design a data structure or algorithm, the question
whether a type parameter `T` must be default-constructible has an
obvious answer (to me at least).
Last but not least (I cut it out, but you did mention it), D has
`static opCall`, which IMO is a worse design than having default
constructors because it means that `T()` can mean one thing or
another, but worst, it may not return a `T` at all! Just thinking
about it, `init` need not have the right type as well. (And some
other magical properties like `tupleof`, `sizeof`, and other
`of`s can be defined to lie, too.)
More information about the Digitalmars-d
mailing list