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