www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - The problem with std.conv.emplace

reply Benjamin Thaut <code benjamin-thaut.de> writes:
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
Oct 03 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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?
Oct 04 2011
parent reply kennytm <kennytm gmail.com> writes:
Timon Gehr <timon.gehr gmx.ch> wrote:
 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?
I did mention nullptr_t in 5899 <g>.
Oct 04 2011
parent Benjamin Thaut <code benjamin-thaut.de> writes:
Am 04.10.2011 20:44, schrieb kennytm:
 Timon Gehr<timon.gehr gmx.ch>  wrote:
 Is there already an enhancement request/bug report for this?
I did mention nullptr_t in 5899<g>.
There is already a similar enhancement request: http://d.puremagic.com/issues/show_bug.cgi?id=5416 I would really appreciate a comment by Walter or Andrei on this. Without this feature it is not possible to replace the deprecated new/delete operators in a nice way. -- Kind Regards Benjamin Thaut
Oct 07 2011