Thread overview
static initialization question
Dec 10, 2008
Weed
Dec 10, 2008
Weed
Dec 10, 2008
Denis Koroskin
Dec 10, 2008
Denis Koroskin
Dec 10, 2008
BCS
Dec 10, 2008
Weed
December 10, 2008
moved from digitalmars.D

> Re: static initialization question 	Digital Mars
> Benjamin Shropshire (ao@pathlink.com) 	2008/12/10 16:46
> Reply to Weed,
>
>> why I can not initialize static variable this way:
>>
>> static MyClass c = new MyClass;
>>
>> Error: non-constant expression new MyClass
>>
>> (dmd 2.014)
>>
>
> this NG is more or less dead. The digitalmars.d.learn NGs would be a better choice.
>
> Only compile time constant values are legal for static initializers because they are initialized at compile time as part of the static data segments.

But my class does not contain data that need initialization and can be created in compile time
December 10, 2008
code:

import std.stdio;

class MyClass
{
    invariant uint a = 0;
}

void main()
{
    static MyClass c = new MyClass;
    writeln( c.a );
}
December 10, 2008
On Thu, 11 Dec 2008 01:31:32 +0300, Weed <resume755@mail.ru> wrote:

> But my class does not contain data that need initialization and can be created
> in compile time
>
> code:
>
> import std.stdio;
>
> class MyClass
> {
>     invariant uint a = 0;
> }
>
> void main()
> {
>     static MyClass c = new MyClass;
>     writeln( c.a );
> }

There is a memory allocation that may occurs at run time only.
December 10, 2008
On Wed, Dec 10, 2008 at 5:31 PM, Weed <resume755@mail.ru> wrote:
> code:
>
> import std.stdio;
>
> class MyClass
> {
>    invariant uint a = 0;
> }
>
> void main()
> {
>    static MyClass c = new MyClass;
>    writeln( c.a );
> }

It's not the class member that wants static initialization, it's your variable declaration.

static MyClass c = new MyClass;

This is illegal because static variables must be initialized with compile-time constants.  The simple way around this is:

static MyClass c; // defaults to null
c = new MyClass;

Which separates the declaration from initialization.
December 10, 2008
Reply to Jarrett,

> On Wed, Dec 10, 2008 at 5:31 PM, Weed <resume755@mail.ru> wrote:
> 
>> code:
>> 
>> import std.stdio;
>> 
>> class MyClass
>> {
>> invariant uint a = 0;
>> }
>> void main()
>> {
>> static MyClass c = new MyClass;
>> writeln( c.a );
>> }
> It's not the class member that wants static initialization, it's your
> variable declaration.
> 
> static MyClass c = new MyClass;
> 
> This is illegal because static variables must be initialized with
> compile-time constants.  The simple way around this is:
> 
> static MyClass c; // defaults to null
> c = new MyClass;
> Which separates the declaration from initialization.
> 

As long as you do this in main it works. In other functions (that might get called more than once) you will need to do something else.

Ripping the variable out of the function would let you use a static constructor:


class MyClass
{
  invariant uint a = 0;
}

MyClass c;
static this() { c = new MyClass; }

void main()
{
  writeln( c.a );
}


December 10, 2008
Jarrett Billingsley пишет:
> On Wed, Dec 10, 2008 at 5:31 PM, Weed <resume755@mail.ru> wrote:
>> code:
>>
>> import std.stdio;
>>
>> class MyClass
>> {
>>    invariant uint a = 0;
>> }
>>
>> void main()
>> {
>>    static MyClass c = new MyClass;
>>    writeln( c.a );
>> }
> 
> It's not the class member that wants static initialization, it's your
> variable declaration.
> 
> static MyClass c = new MyClass;
> 
> This is illegal because static variables must be initialized with
> compile-time constants.  The simple way around this is:
> 
> static MyClass c; // defaults to null
> c = new MyClass;
> 
> Which separates the declaration from initialization.


In C++ analogous construction means creation of uninitialized static pointer (in compile time) and it's initialization at first execution of this line in the function.

Why D does not behave that way on this construction?
December 10, 2008
On Thu, 11 Dec 2008 02:13:58 +0300, Weed <resume755@mail.ru> wrote:

> Denis Koroskin пишет:
>> On Thu, 11 Dec 2008 01:31:32 +0300, Weed <resume755@mail.ru> wrote:
>>
>>> But my class does not contain data that need initialization and can be created
>>> in compile time
>>>
>>> code:
>>>
>>> import std.stdio;
>>>
>>> class MyClass
>>> {
>>>     invariant uint a = 0;
>>> }
>>>
>>> void main()
>>> {
>>>     static MyClass c = new MyClass;
>>>     writeln( c.a );
>>> }
>>  There is a memory allocation that may occurs at run time only.
>
> In C++ analogous construction means creation of uninitialized static pointer (in compile time) and it's initialization at first execution this line in the function.
>
> Why D does not behave that way on this construction?

You can this easily yourself.

// That's what C++ do under the hood:
static MyClass c = null;
if (c is null) {
   c = new MyClass();
}

But it is
a) thread-unsafe
b) a runtime check is done upon every function execution

It can be replaced with a more sophisticated (and error prone) solution:

static MyClass c = null;
if ( (auto old = c) is null ) {
   MyClass tmp = new MyClass();
   if (!CAS(&c, old, tmp)) {
       delete tmp;
   }
}

While it is (arguably) safe, two object might co-exist for a short amount of time, which is unacceptable in many case.

As a summary, the C++ solution is full of problems and leads to bad design practices. The D way is to avoid them.

You should use a private global variable that is initialized in a static initializer (static this) or a plain old struct, instead.