Struct initialization is a mess
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:
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
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
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