I'm currently trying to fix the problem I have with std.conv.emplace to fully replace the deprecated new/delete operator overloading with a template. However it discovered that this is currently not possible, at least not to my knowdelge. The problem is as follows:

class Foo {
}

class Test {
  private:
    Foo m_foo;
  public:
    this(Foo foo){
      m_foo = foo;
    }

    void SetFoo(Foo foo){
      m_foo = foo;
    }
}

void main(){
  void[__traits(classInstanceSize,Test)] mem = typeid(Test).init[];
emplace!Test(mem,null); //do not know how to create a object of type test with args (void*)
}

If I however do the following it works (ignore the missing init part here):
void main(){
  void[__traits(classInstanceSize,Test)] mem = typeid(Test).init[];
  Test t = cast(Test)mem.ptr;
  t.__ctor(null);
}

The same problem occurs when you do:
void CallSetFoo(T)(Test c,T arg){
  c.SetFoo(arg);
}

CallSetFoo(new Test(),null);

It seems that null actually has it's own type but that type is not exposed into the language and is lost as soon as null is passed to a template. To a template null just looks like a void* and therefore can not be used correctly any more.

Now one could write some code that would query all possible constructors find a matching one and manually cast void* to the correct reference type however this would require a runtime check for null to avoid casting any void* to a reference, and I would highly prefer a solution that would not require runtime checks to be safe.

My suggestion would be to actually give null it's own type and expose that into the language so it can be correctly used with templates.

Any other ideas how to fix this? Maybe there is a way with the current type system I don't know of.

--
Kind Regards
Benjamin Thaut

Reply via email to