www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Undo struct slicing by type-punning

reply "ponce" <contact gam3sfrommars.fr> writes:
Hi,

I am porting C++ code that undo "Object Slicing" by casting 
const-references:
http://en.wikipedia.org/wiki/Object_slicing


My translation in D Code
----

struct A
{
  // stuff
}

struct B
{
   A a;
   alias a this;
  // stuff
}

void myFunction(ref const(A) a)
{
     if (<a-is-actually-a-B>)
     {
         // here goes the converstion to a B reference
         myFunction2(*cast(const(B)*)(&a)); // using pointer to do 
type-punning
     }
}

----


To do this, I need to by guaranteed an object passed through ref 
const(A) is never, ever passed by value. Is it safe to assume?
Jul 14 2014
parent reply "ponce" <contact gam3sfrommars.fr> writes:
Ok, solved it, I just use pointer casts and it seems to work when 
the struct is sliced.


On Monday, 14 July 2014 at 13:23:57 UTC, ponce wrote:
 Hi,

 I am porting C++ code that undo "Object Slicing" by casting 
 const-references:
 http://en.wikipedia.org/wiki/Object_slicing


 My translation in D Code
 ----

 struct A
 {
  // stuff
 }

 struct B
 {
   A a;
   alias a this;
  // stuff
 }

 void myFunction(ref const(A) a)
 {
     if (<a-is-actually-a-B>)
     {
         // here goes the converstion to a B reference
         myFunction2(*cast(const(B)*)(&a)); // using pointer to 
 do type-punning
     }
 }

 ----


 To do this, I need to by guaranteed an object passed through 
 ref const(A) is never, ever passed by value. Is it safe to 
 assume?
Jul 14 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/14/2014 10:35 AM, ponce wrote:

 Ok, solved it, I just use pointer casts and it seems to work when the
 struct is sliced.
I think there is a terminology issue here. Slicing cannot be undone; once the object is sliced, the non-A parts are gone.
 On Monday, 14 July 2014 at 13:23:57 UTC, ponce wrote:
 Hi,

 I am porting C++ code that undo "Object Slicing" by casting
 const-references:
 http://en.wikipedia.org/wiki/Object_slicing


 My translation in D Code
 ----

 struct A
 {
  // stuff
 }

 struct B
 {
   A a;
   alias a this;
  // stuff
 }

 void myFunction(ref const(A) a)
 {
     if (<a-is-actually-a-B>)
     {
         // here goes the converstion to a B reference
         myFunction2(*cast(const(B)*)(&a)); // using pointer to do
 type-punning
     }
 }

 ----


 To do this, I need to by guaranteed an object passed through ref
 const(A) is never, ever passed by value. Is it safe to assume?
It is guaranteed by the language spec that yes, myFunction() takes an A by reference. However, you can't know where that A is coming from; so, the safety of that cast is up to you. Consider: void foo(A a) // <-- Already sliced { myFunction(a); // <-- Will perform invalid cast } Ali
Jul 14 2014
next sibling parent reply "ponce" <contact gam3sfrommars.fr> writes:
On Monday, 14 July 2014 at 18:43:36 UTC, Ali Çehreli wrote:
 On 07/14/2014 10:35 AM, ponce wrote:

 Ok, solved it, I just use pointer casts and it seems to work
when the
 struct is sliced.
I think there is a terminology issue here. Slicing cannot be undone; once the object is sliced, the non-A parts are gone.
Well they are not really gone if the struct is passed by-ref, you can recover the "gone" parts: http://dpaste.dzfl.pl/d64863fd4c6d
Jul 14 2014
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/14/2014 02:34 PM, ponce wrote:

 On Monday, 14 July 2014 at 18:43:36 UTC, Ali Çehreli wrote:
 On 07/14/2014 10:35 AM, ponce wrote:

 Ok, solved it, I just use pointer casts and it seems to work
when the
 struct is sliced.
I think there is a terminology issue here. Slicing cannot be undone; once the object is sliced, the non-A parts are gone.
Well they are not really gone if the struct is passed by-ref,
Oh, it's not slicing in that case... but wait! There is a problem here. :) In C++, both structs and classes are value types and they both support inheritance. To observe slicing in C++, one needs pass-by-value and inheritance, which is available by structs and classes. In D, structs don't support inheritance and classes don't support pass-by-value. However... Enter 'alias this' and we have D's version of slicing.
 you can recover the "gone" parts: http://dpaste.dzfl.pl/d64863fd4c6d
Aggreed but in D's case the non-A parts are not gone; as long as A lives, we know that B is alive. This is different from C++ where due to the necessary pass-by-value, they are truly gone (the bits may still be there but a C++ code should not do as D does). Ali
Jul 14 2014
prev sibling parent "ponce" <contact gam3sfrommars.fr> writes:
On Monday, 14 July 2014 at 18:43:36 UTC, Ali Çehreli wrote:
 It is guaranteed by the language spec that yes, myFunction() 
 takes an A by reference. However, you can't know where that A 
 is coming from; so, the safety of that cast is up to you. 
 Consider:

 void foo(A a)         // <-- Already sliced
 {
     myFunction(a);    // <-- Will perform invalid cast
 }
Indeed, the code I port do that because struct have a type-tag.
Jul 14 2014