Thread overview
class variable initialization
Apr 15, 2023
NonNull
Apr 15, 2023
Vijay Nayar
Apr 15, 2023
NonNull
Apr 15, 2023
NonNull
Apr 15, 2023
Ali Çehreli
April 15, 2023

I want a way to default initialize a class variable to a default object (e.g. by wrapping it in a struct, because initialization to null cannot be changed directly). Such a default object is of course not available at compile time which seems to make this impossible. Can this be done in some way?

April 15, 2023

On Saturday, 15 April 2023 at 14:05:17 UTC, NonNull wrote:

>

I want a way to default initialize a class variable to a default object (e.g. by wrapping it in a struct, because initialization to null cannot be changed directly). Such a default object is of course not available at compile time which seems to make this impossible. Can this be done in some way?

Assuming you want a default object that is unique per class instance rather than shared among all instances of the same class, then I think the constructor might be where you want to initialize such a member.

E.g.

class Var {
  int val;
  this(int val) {
    this.val = val;
  }
}

class MyClass {
  Var var;

  this() {
    var = new Var(3);
  }
}

I believe if you do initialization at the class declaration level, then every instance of the class shares the same instance, e.g.:

class Var {}

class MyClass {
  Var var = new Var();
}

void main() {
  MyClass c1 = new MyClass();
  MyClass c2 = new MyClass();
  assert(c1.var is c2.var);
}
April 15, 2023

On Saturday, 15 April 2023 at 14:17:19 UTC, Vijay Nayar wrote:

>

I believe if you do initialization at the class declaration level, then every instance of the class shares the same instance, e.g.:

class Var {}

class MyClass {
  Var var = new Var();
}

void main() {
  MyClass c1 = new MyClass();
  MyClass c2 = new MyClass();
  assert(c1.var is c2.var);
}

I should have made it clear that want a single shared default object. Your code above solves that problem. So does

Var defaultObj;
static this() { defaultObj = new Var(); }

By wrapping the new variable and the constructor call to initialize it in MyClass, you eliminate the need to call the constructor, which is what I want, but now you add the need to call another constructor. So for my purposes this is just moving the problem of null to another place.

April 15, 2023
On 4/15/23 7:05 AM, NonNull wrote:
> I want a way to default initialize a class variable to a default object (e.g. by wrapping it in a struct, because initialization to null cannot be changed directly). Such a default object is of course not available at compile time which seems to make this impossible. Can this be done in some way?

You can construct objects at compile time.

If I understand your question properly:

```d
struct Wrapper
{
   Object x = new Object();
   alias x this;
}

void foo(Object o)
{
   assert(o !is null);
}

void main()
{
   Wrapper w;
   foo(w);
}
```

-Steve
April 15, 2023
On Saturday, 15 April 2023 at 15:47:40 UTC, Steven Schveighoffer wrote:
> You can construct objects at compile time.
>
> If I understand your question properly:
>
> ```d
> struct Wrapper
> {
>    Object x = new Object();
>    alias x this;
> }
>
> void foo(Object o)
> {
>    assert(o !is null);
> }
>
> void main()
> {
>    Wrapper w;
>    foo(w);
> }
> ```
>
> -Steve

Amazing, was this always so?



April 15, 2023
On 4/15/23 09:06, NonNull wrote:

>> struct Wrapper
>> {
>>    Object x = new Object();
>>    alias x this;
>> }

> Amazing, was this always so?

At least for a long time. However, every Wrapper object will have a pointer to that single shared object.

If you think that cost is unnecessary, you can have a static variable:

struct Wrapper
{
   static Object x;
   alias x this;
}

static this() {
    Wrapper.x = new Object();
}

However, because such data are thread-local by-default, not the entire class, but each thread will have a copy that variable.

When you want a single class variable for all threads, then it must be defined as shared:

struct Wrapper
{
   shared static Object x;
   alias x this;
}

shared static this() {
    Wrapper.x = new Object();
}

void foo(shared Object o)
{
   assert(o !is null);
}

Note how foo's interface had to be changed as well. And of course you may have to provide thread synchronization when that variable needs to be mutated at run time.

Ali