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

```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
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
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
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
```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
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
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
"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
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
```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,
```
Nov 12 2011
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
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
"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
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
```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
"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
"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
"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