Default struct constructor

bitwise bitwise.pvt at gmail.com
Fri Feb 8 17:23:54 UTC 2019


On Friday, 8 February 2019 at 08:25:18 UTC, Jonathan M Davis 
wrote:
> [...]
>
> So, basically, you want default constructors but are suggesting 
> that there be an explicit void parameter in the declaration to 
> indicate that that's what you're doing rather than just having 
> it not have any parameters.

Yeah, that *was* the general idea.

> Well, that runs into all of the problems related to the fact 
> that D was designed around the idea that everything is 
> default-initialized. It's not an impossible hurdle, but it 
> would be a significant shift in how the language works, and it 
> would mean that stuff like how arrays are initialized would 
> change drastically depending on the types involved whereas 
> right now, you need default initialization, or you simply can't 
> use the type in an array,
> and the way that arrays are initialized is the same for all 
> types. It also would be a problem from the standpoint of code 
> clarity. With something like
>
> S s = void;
>
> you can clearly see that the programmer has explicitly 
> requested that the variable not be properly initialized, 
> whereas with your suggested default constructors, suddenly you 
> would no longer know what
>
> S s;
>
> did unless you looked at the type. In the vast majority of 
> cases, it would be default-iniatialized, but occasionally, it 
> would be default constructed, and that could cause quite a bit 
> of confusion.
>
> It also still doesn't get around the fact that _all_ types in D 
> have an init value, and someone could use it (e.g. 
> std.algorithm's move function uses it to give the old variable 
> a valid value rather than garbage after the move). Even types 
> which have disabled default initialization have init values.
>
> And it would be very disruptive to the language to try to 
> change that if it's really possible at all (e.g. objects are 
> always initialized to their init value before any constructors 
> are run, so the way that constructors work in D relies on there 
> being an init value for the type). So, with how D is designed, 
> you really can't rely on a constructor having been run for a 
> struct object. It can be made much harder to not have called a 
> constructor (e.g. by using @disable this();), but as long as 
> the init value exists, there's a way around the constructor.

This is a good point, but I think it's a workable problem. I 
actually wouldn't be opposed to having T.init blitted over my 
struct before my dynamic constructor was called. My concern here 
is more functional than performance-based. As long as my struct 
had the correct values by the beginning of it's lifetime, that 
would be fine.

So maybe this(auto) could work ;)

> So, fundamentally, I really don't see how default constructors 
> for structs can fully work in D. At best, it could be made to 
> work in the common cases and even that's only possible by 
> complicating how a number of core things work so that they do 
> different things depending on whether a struct is default 
> constructed or default initialized, which would definitely 
> complicate the language.

My (revised) concern is only that my struct have the opportunity 
to change it's values right before the start of it's lifetime, 
but without adding boiler-plate code all over the place. 
Essentially, I guess I'm asking for a  post-init constructor, 
similar to how a post-blit would work.

It has also been very annoying not to be able to have dynamic 
class/struct field initializers, and this would also be fixed by 
some kind of post-init constructor method.

> It's useful in rare situations, but it has to be handled with 
> care - particularly since the type's init value still exists, 
> and some code will use it.

I have to strongly disagree with this. I haven't touched D in 
nearly a year because of these types of problems. I'm still 
waiting to see how the memory/resource situation shapes up with 
the addition of scope and possible RC classes.

> It's true that there are use cases where the lack of a default 
> constructor for structs is annoying, but in general, all you 
> have to do is use a factory method instead and then make sure 
> that the type still works if its init value is used (e.g. make 
> sure that the destructor is aware that the factory method can 
> be bypassed). And if you absolutely must have default 
> construction, you can always use a class instead.

I think my comment above about wanting structs to have the 
appropriate values _before_ their lifetime starts applies here 
too.

A factory method requires explicit runtime invocation and is no 
different than a static opCall, unary dummy constructor, or 
having to add initialization boilerplate.


Thanks for the detailed response,
    Bit



More information about the Digitalmars-d mailing list