Allow default constructors for structs
Quirin Schroll
qs.il.paperinik at gmail.com
Thu Sep 5 18:26:45 UTC 2024
On Thursday, 29 August 2024 at 14:28:09 UTC, Ogi wrote:
> This has been discussed ad nauseam, so I’m skipping rationale.
> Let’s just say that many users want this feature, especially
> those who need C++ interop. Here’s how it can be implemented in
> a non-problematic way.
>
> A struct with a default constructor can only be instantiated by
> an implicit constructor call, following the same rules as a
> struct with a disabled default constructor.
>
> ```D
> struct S {
> this() {
> writeln("S.this()");
> }
> }
>
> void main {
> S s; // error
> S t = S(); // ok (constructed by calling `S.this()`)
> S u = void; // ok (not `@safe`)
> S v = S.init; // ok (may be a logically incorrect object)
> S[3] a; // error
> S[3] b = [S(), S(), S()]; // ok
> }
> ```
I’d prefer some modifications:
```d
S s; // same as `S s = S();`
S t = S(); // calls nullary constructor
S u = void; // not @safe, do not use
S v1 = S.init; // deprecated; use `default(S)`
S v2 = default(S); // not @safe; do not use
S v3 = default; // same as `S v3 = default(S)`
S[3] a; // same as `S[3] = [S(), S(), S()];`
S[3] b = [S(), S(), S()]; // calls nullary constructor thrice
```
Essentially, a struct variable goes through the following steps:
1. Memory is allocated for it – this is `= void` initialization
2. The type’s `default` is blitted onto it – this is `= default`
initialization or using the newly added `__default(x)` function
for an already allocated value `x`.
3. A constructor runs on the default initialized value – this is
the usual initialization, or call `x.__ctor(args)` for an already
defaulted value `x`.
Then the value is ready to use. For some types, might be ready to
use earlier, but in general, it’s not. For example:
- A `= void` initialized `int` can be used.
- A `= void` initialized pointer cannot be used.
- A `= default` initialized (nullable) pointer can be used (it’s
just a null pointer).
- A `= default` initialized non-null reference cannot be used
(it’s null, but ought not to be).
I really don’t like banning `S s;` for _some_ types. Either
require explicit initialization of all variables (normal, `=
void;` or `= default;`) or make it do the Right Thing always. Of
course, if a type has a disabled nullary constructor, `S s;` is
an error, as that’s the purpose of disabling the constructor.
Also, folks, terminology is important: nullary constructor is a
much better term than default constructor. Don’t be fooled by C++.
More information about the dip.ideas
mailing list