Would love to override default ctor of struct

Jonathan M Davis newsgroup.d at jmdavisprog.com
Mon Jan 21 22:48:41 UTC 2019


On Monday, January 21, 2019 12:08:49 PM MST Alex via Digitalmars-d wrote:
> On Monday, 21 January 2019 at 17:06:55 UTC, Nick Treleaven wrote:
> > On Saturday, 19 January 2019 at 11:01:14 UTC, Alex wrote:
> >>> 2. not everything can be set using member initializer because
> >>> of CTFE limitations.
> >>
> >> Hm... ok. But even then, if something does not work in the way
> >> it should because of limitations: What prevents of setting the
> >> parameter inside a function after or on creation?
> >
> > Performance for repeated function calls after construction, we
> > don't want an extra branch test on each function call and an
> > extra bool bloating/tainting fields in the struct.
> >
> > A pseudo constructor function is a workaround, but is a bit
> > ugly, adding a separate symbol you have to check for when
> > learning a new library struct, and the function has more
> > unnecessary boilerplate vs a constructor.
> >
> >> Or, using a non-default constructor exactly for these params?
> >
> > You can't have a zero argument non-default struct constructor.
> > I've never been told why:
> > https://wiki.dlang.org/Language_issues#Explicit_syntax_and_.40disable_th
> > is
> >
> > Only the default constructor is constrained by .init, explicit
> > zero argument construction is unconstrained. It could be
> > allowed.
>
> Could you give an example, where a zero argument construction has
> to be done, which cannot be accomplished by setting the
> appropriate field with a default value?

A classic case would be some uses of RAII such as what MFC does with its
hourglass. You get code something like

Hourglass hg;

and that does everything. The constructor pops up the hourglass, and the
destructor takes it down. If you wanted an object like that in D, you would
have to use a factory function. e.g.

auto hg = Hourglass.create();

and you would then have to make it so that the object can deal with the fact
that the init value never when through the factory function and thus must do
nothing in its destructor (using @disable this() to disable default
initialization reduces that problem, but since the init value can still be
used explicitly, it really doesn't eliminate the problem).

Similarly, as Meta alludes to in his example, having dynamic arrays of
mutable elements as member variables is problematic with structs, because
all of the instances of that struct on the same thread have a dynamic array
that is a slice of the same chunk of memory, meaning that mutating an
element in one mutates all of them (at least all of them which haven't ended
up with their array being reallocated due to appending or whatnot). In most
cases, you'd really want a separate dynamic array for each instance of the
struct, and D doesn't give a good way to do that with init values, forcing
you to use a factory function instead of a constructor if you want to try
and force it. And now that we can actually directly initialize member
variables which are pointers or class references, those join the ranks of
potentially having problems due to all of the instances of that struct on a
particular thread having the same value for those pointers or references.
So, it can become a bit error-prone for those types of member variables.

And really, any and all situations where you're looking to have a piece of
code run when an instance of the struct is created but where you don't
necessarily have arguments for the constructor is going to be harder to deal
with cleanly in D thanks to the lack of default constructors.

In general, you just learn to live with it and use factory functions to deal
with the problem in those cases where it pops up. So, it usually isn't a big
deal, and it's mostly just something that folks new to D complain about, but
having init values such that we cannot have default constructors for structs
is an area in D that's a tradeoff, not a complete win. Many of us think that
the tradeoffs involved are well worth it, but that doesn't change the fact
that there are times when having a default constructor would be really nice,
and the fact that you can't is then annoying.

- Jonathan M Davis





More information about the Digitalmars-d mailing list