www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Copy a struct on the heap and get the pointer to it.

reply deadalnix <deadalnix gmail.com> writes:
Hi all,

We recently had a discution on #D about copying a struct on the heap and 
getting a pointer to it.

We come up with the following solution (Thanks to CyberShadow !) :

struct S;
S s; // Allocated locally.
[s].ptr; // Get a pointer to a copy in the heap of the struct

What is going on ? An array of one object is allocated on the heap and 
the struct copied in it. Then we get a pointer to the first (and only 
one) element of the array with ptr.

So we have a pointer to a copy of s on the heap.

I have several question on that :
  - Does a idiomatic way to do that exists ?
  - Is this intented to do so ? Will this construct risk to be broken in 
a future version of D ?
  - Is this construct the idiomatic way to do so ?
Nov 12 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 11/12/2011 03:39 PM, deadalnix wrote:
 Hi all,

 We recently had a discution on #D about copying a struct on the heap and
 getting a pointer to it.

 We come up with the following solution (Thanks to CyberShadow !) :

 struct S;
 S s; // Allocated locally.
 [s].ptr; // Get a pointer to a copy in the heap of the struct

 What is going on ? An array of one object is allocated on the heap and
 the struct copied in it. Then we get a pointer to the first (and only
 one) element of the array with ptr.

 So we have a pointer to a copy of s on the heap.

 I have several question on that :
 - Does a idiomatic way to do that exists ?
I don't think that this is such a common need.
 - Is this intented to do so ?
Yes.
 Will this construct risk to be broken in a
 future version of D ?
No.
 - Is this construct the idiomatic way to do so ?
It is certainly the most elegant way to do so.
Nov 12 2011
parent reply kenji hara <k.hara.pg gmail.com> writes:
Here is a pitfall.
If S has the postblit, it is not called with your code.

import core.stdc.stdio;
struct S
{
    this(this){
        printf("postblit\n");
    }
}
void main()
{
    S s;
    S* ps = [s].ptr;
    // does not print "postblit"
}

I've already poted a pull
(https://github.com/D-Programming-Language/dmd/pull/375) to fix it,
but it is not yet merged.

A workaround is follows.

// The definition of S is same as above.
T makecopy(T)(ref T obj) if (is(T == struct))
{
    auto dup = obj;  // make copy with calling postblit
    return dup;
}
void main()
{
    S s;
    S* ps = [makecopy(s)].ptr;
    // print "postblit"
}

If you use it, please be careful.

Kenji Hara.

2011/11/13 Timon Gehr <timon.gehr gmx.ch>:
 On 11/12/2011 03:39 PM, deadalnix wrote:
 Hi all,

 We recently had a discution on #D about copying a struct on the heap and
 getting a pointer to it.

 We come up with the following solution (Thanks to CyberShadow !) :

 struct S;
 S s; // Allocated locally.
 [s].ptr; // Get a pointer to a copy in the heap of the struct

 What is going on ? An array of one object is allocated on the heap and
 the struct copied in it. Then we get a pointer to the first (and only
 one) element of the array with ptr.

 So we have a pointer to a copy of s on the heap.

 I have several question on that :
 - Does a idiomatic way to do that exists ?
I don't think that this is such a common need.
 - Is this intented to do so ?
Yes.
 Will this construct risk to be broken in a
 future version of D ?
No.
 - Is this construct the idiomatic way to do so ?
It is certainly the most elegant way to do so.
Nov 12 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/12/11 9:22 AM, kenji hara wrote:
 Here is a pitfall.
 If S has the postblit, it is not called with your code.

 import core.stdc.stdio;
 struct S
 {
      this(this){
          printf("postblit\n");
      }
 }
 void main()
 {
      S s;
      S* ps = [s].ptr;
      // does not print "postblit"
 }

 I've already poted a pull
 (https://github.com/D-Programming-Language/dmd/pull/375) to fix it,
 but it is not yet merged.
Thanks! This is important. I recall C++ was much more difficult to use in the period of time where compilers got various copy construction scenarios wrong. We need to have object copying rock-solid. Andrei
Nov 12 2011
parent deadalnix <deadalnix gmail.com> writes:
Le 12/11/2011 16:27, Andrei Alexandrescu a écrit :
 On 11/12/11 9:22 AM, kenji hara wrote:
 Here is a pitfall.
 If S has the postblit, it is not called with your code.

 import core.stdc.stdio;
 struct S
 {
 this(this){
 printf("postblit\n");
 }
 }
 void main()
 {
 S s;
 S* ps = [s].ptr;
 // does not print "postblit"
 }

 I've already poted a pull
 (https://github.com/D-Programming-Language/dmd/pull/375) to fix it,
 but it is not yet merged.
Thanks! This is important. I recall C++ was much more difficult to use in the period of time where compilers got various copy construction scenarios wrong. We need to have object copying rock-solid. Andrei
Well I don't think the postblit should be called if s isn't used after the copy on the heap. This should have the move semantic and not the copy semantic. Obviously, if s is used after the copy on the heap, the postblit should be called.
Nov 12 2011
prev sibling next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
The way I'd do it is:

S s;

auto heap = new S;

*heap = s;


that should work.
Nov 12 2011
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 11/12/2011 04:17 PM, Adam D. Ruppe wrote:
 The way I'd do it is:

 S s;

 auto heap = new S;

 *heap = s;


 that should work.
struct S{ immutable no_it_does_not = 0; // ;) }
Nov 12 2011
prev sibling next sibling parent reply "Martin Nowak" <dawg dawgfoto.de> writes:
On Sat, 12 Nov 2011 16:17:29 +0100, Adam D. Ruppe  
<destructionator gmail.com> wrote:

 The way I'd do it is:

 S s;

 auto heap = new S;

 *heap = s;


 that should work.
auto ps = std.conv.emplace(new S, s); Avoids the hacky array aliasing. // slightly more efficient auto ps2 = emplace(cast(S*)(new ubyte[](S.sizeof)).ptr, s); You will need to define a copy constructor for immutable fields.
Nov 12 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/12/11 9:37 AM, Martin Nowak wrote:
 On Sat, 12 Nov 2011 16:17:29 +0100, Adam D. Ruppe
 <destructionator gmail.com> wrote:

 The way I'd do it is:

 S s;

 auto heap = new S;

 *heap = s;


 that should work.
auto ps = std.conv.emplace(new S, s); Avoids the hacky array aliasing.
That constructs S two times.
 // slightly more efficient
 auto ps2 = emplace(cast(S*)(new ubyte[](S.sizeof)).ptr, s);

 You will need to define a copy constructor for immutable fields.
That should work but it's rather complicated. Andrei
Nov 12 2011
prev sibling parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Sat, 12 Nov 2011 17:17:29 +0200, Adam D. Ruppe  
<destructionator gmail.com> wrote:

 auto heap = new S;
Won't work if S has a constructor (which was the OP's case). -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Nov 12 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/12/11 8:39 AM, deadalnix wrote:
 Hi all,

 We recently had a discution on #D about copying a struct on the heap and
 getting a pointer to it.

 We come up with the following solution (Thanks to CyberShadow !) :

 struct S;
 S s; // Allocated locally.
 [s].ptr; // Get a pointer to a copy in the heap of the struct
This should work: S s; auto p = new S(s); It's a bug in the compiler if it doesn't. Unfortunately it doesn't for primitive types, e.g. new int(5) does not work. Andrei
Nov 12 2011
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 11/12/2011 04:29 PM, Andrei Alexandrescu wrote:
 On 11/12/11 8:39 AM, deadalnix wrote:
 Hi all,

 We recently had a discution on #D about copying a struct on the heap and
 getting a pointer to it.

 We come up with the following solution (Thanks to CyberShadow !) :

 struct S;
 S s; // Allocated locally.
 [s].ptr; // Get a pointer to a copy in the heap of the struct
This should work: S s; auto p = new S(s); It's a bug in the compiler if it doesn't. Unfortunately it doesn't for primitive types, e.g. new int(5) does not work.
It does not work for structs either. It fails with 'Error: no constructor for S'. Where is the behaviour you describe documented?
Nov 12 2011
prev sibling next sibling parent "Martin Nowak" <dawg dawgfoto.de> writes:
On Sat, 12 Nov 2011 16:29:01 +0100, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 11/12/11 8:39 AM, deadalnix wrote:
 Hi all,

 We recently had a discution on #D about copying a struct on the heap and
 getting a pointer to it.

 We come up with the following solution (Thanks to CyberShadow !) :

 struct S;
 S s; // Allocated locally.
 [s].ptr; // Get a pointer to a copy in the heap of the struct
This should work: S s; auto p = new S(s); It's a bug in the compiler if it doesn't. Unfortunately it doesn't for primitive types, e.g. new int(5) does not work. Andrei
Yes it should, but it doesn't.
Nov 12 2011
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
It has been already filed in bugzilla?
If so, I'd like to fix it.

Kenji Hara

2011/11/13 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>:
 On 11/12/11 8:39 AM, deadalnix wrote:
 Hi all,

 We recently had a discution on #D about copying a struct on the heap and
 getting a pointer to it.

 We come up with the following solution (Thanks to CyberShadow !) :

 struct S;
 S s; // Allocated locally.
 [s].ptr; // Get a pointer to a copy in the heap of the struct
This should work: S s; auto p = new S(s); It's a bug in the compiler if it doesn't. Unfortunately it doesn't for primitive types, e.g. new int(5) does not work. Andrei
Nov 12 2011
prev sibling next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 12/11/2011 16:29, Andrei Alexandrescu a écrit :
 On 11/12/11 8:39 AM, deadalnix wrote:
 Hi all,

 We recently had a discution on #D about copying a struct on the heap and
 getting a pointer to it.

 We come up with the following solution (Thanks to CyberShadow !) :

 struct S;
 S s; // Allocated locally.
 [s].ptr; // Get a pointer to a copy in the heap of the struct
This should work: S s; auto p = new S(s); It's a bug in the compiler if it doesn't. Unfortunately it doesn't for primitive types, e.g. new int(5) does not work. Andrei
That was my first try. It does not work.
Nov 12 2011
next sibling parent "Martin Nowak" <dawg dawgfoto.de> writes:
On Sat, 12 Nov 2011 17:41:43 +0100, deadalnix <deadalnix gmail.com> wrot=
e:

 Le 12/11/2011 16:29, Andrei Alexandrescu a =C3=A9crit :
 On 11/12/11 8:39 AM, deadalnix wrote:
 Hi all,

 We recently had a discution on #D about copying a struct on the heap=
=
 and
 getting a pointer to it.

 We come up with the following solution (Thanks to CyberShadow !) :

 struct S;
 S s; // Allocated locally.
 [s].ptr; // Get a pointer to a copy in the heap of the struct
This should work: S s; auto p =3D new S(s); It's a bug in the compiler if it doesn't. Unfortunately it doesn't fo=
r
 primitive types, e.g. new int(5) does not work.


 Andrei
That was my first try. It does not work.
I'll make bug reports for it.
Nov 12 2011
prev sibling parent "Martin Nowak" <dawg dawgfoto.de> writes:
On Sat, 12 Nov 2011 17:41:56 +0100, Martin Nowak <dawg dawgfoto.de> wrot=
e:

 On Sat, 12 Nov 2011 17:41:43 +0100, deadalnix <deadalnix gmail.com>  =
 wrote:

 Le 12/11/2011 16:29, Andrei Alexandrescu a =C3=A9crit :
 On 11/12/11 8:39 AM, deadalnix wrote:
 Hi all,

 We recently had a discution on #D about copying a struct on the hea=
p =
 and
 getting a pointer to it.

 We come up with the following solution (Thanks to CyberShadow !) :

 struct S;
 S s; // Allocated locally.
 [s].ptr; // Get a pointer to a copy in the heap of the struct
This should work: S s; auto p =3D new S(s); It's a bug in the compiler if it doesn't. Unfortunately it doesn't f=
or
 primitive types, e.g. new int(5) does not work.


 Andrei
That was my first try. It does not work.
I'll make bug reports for it.
http://d.puremagic.com/issues/show_bug.cgi?id=3D6937 http://d.puremagic.com/issues/show_bug.cgi?id=3D6938 It's actually two bugs. If the 6937 worked one could have used 'new S(s.tupleof)'. martin
Nov 12 2011
prev sibling parent "Martin Nowak" <dawg dawgfoto.de> writes:
On Sat, 12 Nov 2011 16:29:01 +0100, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 11/12/11 8:39 AM, deadalnix wrote:
 Hi all,

 We recently had a discution on #D about copying a struct on the heap and
 getting a pointer to it.

 We come up with the following solution (Thanks to CyberShadow !) :

 struct S;
 S s; // Allocated locally.
 [s].ptr; // Get a pointer to a copy in the heap of the struct
This should work: S s; auto p = new S(s); It's a bug in the compiler if it doesn't. Unfortunately it doesn't for primitive types, e.g. new int(5) does not work. Andrei
Not so sure about built-in types. It's preferable for generic code to define 'Type(Expression)' as initializer, but is there a consensus for 'int(3)'? Also as it is allowed for structs there should be no ambiguities with function signatures, still this needs a thorough thought.
Nov 12 2011