Struct initialization is a mess

Dukc ajieskola at gmail.com
Thu Jul 29 15:28:38 UTC 2021


On Wednesday, 28 July 2021 at 23:43:25 UTC, H. S. Teoh wrote:
> [snip]

Ok, that kind-of explains it, but not quite. I re-read the 
language spec and did some more tests. I try to wrap up the whole 
construction deal here.

First off, every `struct` type has one, and only one 
initialization class. They are: literal initialized, constructed, 
call-overloaded, and call-disabled. The algrorithm to determine 
the type is:

If a `struct` has any non-default constructors, it is constructed.

Otherwise, If it has `@disable this()` it is call-disabled. A 
member with `@disable this()` does not count.

Otherwise, if a struct has any `static opCall` overloads, it is 
call-overloaded.

Otherwise it is literal-initialized.

Any struct that has `@disable this()` is default-uninitializable. 
Also any struct that has a default-uninitializable member without 
default value is itself default-uninitializable.

A default-uninitializable struct can only be default-initialized 
by explicitly assigning it's `.init` value to it. All other 
structs can be default-initialized as always.

All default-initializable literal-initialized or constructed 
structs can be initialized with syntax `S()` which is the same as 
`S.init` (is/would be) if it's not redefined in S. Call-disabled 
`struct`s cannot obviously use the syntax in question.

For call-overloaded `struct`s, `S()` results in the respective 
`opCall` if it exists. That function need not to return `S`. 
Otherwise, syntax `S()` is illegal for that struct. This applies 
regardless of whether the struct is default-initializable.

C-style initialization syntax is legal for call-overloaded, 
call-disabled and literal-initialized `struct`s, but not for 
constructed structs. If any members are default-uninitializable 
without default value, they must be set. It does not matter if 
the struct itself is default-initializable.

Syntax `S(a,b)` will call the respective `opCall` for 
call-overloaded `struct`s, the respective constructor for 
constructed ones, and act a struct literal for 
literal-initialized ones. The syntax in question is always 
forbidden for call-disabled `struct`s.

Syntax `S s = a` where `!is(typeof(a) : S)` is forbidden for 
literal-initialized and call-disabled `struct`s (absent 
`opAssign` overloads at least - I didn't test them), but will be 
interpreted as `S s = S(a)` for constructed and call-overloaded 
`struct`s.

Now, does this sound like a good summary? Any improvement ideas 
(either to summary or how things currently work)?


More information about the Digitalmars-d mailing list