On 04.10.2011 08:05, Benjamin Thaut wrote:
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.

This works.

emplace!Test(mem,cast(Foo)null);

But I am totally supporting your suggestion. null should not decay to a void* on template argument boundaries, it has bugged me multiple times.

Is there already an enhancement request/bug report for this?

Reply via email to