Run-time initialised static variables

Jonathan M Davis newsgroup.d at jmdavisprog.com
Wed Feb 7 00:31:01 UTC 2018


On Tuesday, February 06, 2018 23:50:52 dekevin via Digitalmars-d-learn 
wrote:
> Thanks a lot! I will change all my initialisations to static
> constructors now.

I should point out that the downside to static constructors is that if you
have modules that recursively depend on each other, the program throws an
Error at startup, because the runtime can't determine the correct order of
initialization. So, while static constructors can be very useful, you do
have to be careful with them.

> The only additional problem I have, is that ℚInf has a disabled
> default constructor.

D does not have default constructors. What you're really disabling is
default initialization. This is an important distinction in understanding
how objects are initialized in D. The init value is known at compile time
and can't involve runtime stuff, whereas a default constructor would be able
to run arbitrary code at runtime.

> Is there a way to allow shared static constructors, but not the
> default constructor?
> struct ℚInf {
>       ℚ qval;
>       immutable static ℚInf zero;
>      @disable this();
>       shared static this() {
>            zero.qval = ℚ(0);
>       }
>       this(long num, long den) {
>            qval = ℚ(num,den); //this initialisation requires
>   dynamically linked code
>        }
> }

If you're initializing an immutable variable, you have to initialize it in
one go. What you're doing is letting it be default initialized (which
results in a compilation error, because default initialiaztion is disabled
for that type) and then assigning to one of its members. If the default
initialization weren't disabled, you'd get an error about not being able to
mutate an immutable variable, whereas the fact that you disabled default
initialization but did not explicitly initialize the variable results in a
compilation error about not initializing the variable.

If you want zero to be immutable, you must initialize the entire object at
once. e.g.

zero = QInf(0, 0);

or whatever makes sense. If you need zero to be initialized differently from
other QInfs, then you could make a private constructor that just takes the
value for qval. But it either has to be default initialized with whatever
the init type is (which you clearly don't want, since you disabled that), or
it needs to be explicitly given a value.

- Jonathan M Davis




More information about the Digitalmars-d-learn mailing list