How can I create a garbage-collected copy of a struct that's on the stack?
Coming from a C++ background, my first guess would be a copy constructor like the one below, but it doesn't seem very idiomatic for D, and I haven't seen one in any of the D projects I've taken a look at.
struct Foo {
immutable int bar;
this(int b) { bar = b; }
// A C++-style copy constructor works but doesn't seem idiomatic.
this(ref const Foo f) { bar = f.bar; }
}
void main()
{
// We initialize a Foo on the stack
auto f = Foo(42);
// Now I want to get a heap copy of its member. How?
// A C++-style copy constructor works but doesn't seem idiomatic.
Foo* f1 = new Foo(f);
}
Your example is overly complicated and doesn't even compile, but essentially, it sounds like what you want to be able to do is something like
struct Foo
{
int i;
}
void main()
{
auto f = Foo(5);
auto g = new Foo(f);
}
What you can do without any special constructors is
void main()
{
auto f = Foo(5);
auto g = new Foo;
*g = f;
}
but obviously that's more steps than you probably want. The normal "copy constructor" for D is a postblit constructor, which is declared as this(this) {...}
, but that's not required for Foo
as it's declared here (since all of its members are value types), and it doesn't help with allocating a struct on the heap anyway - just with copying a struct. Arguably
auto f = Foo(5);
auto g = new Foo(f);
should just work, but at the moment, it doesn't, and there is unfortunately, no support in the language for defining it for you. So, unfortunately, I think that you're currently forced to do something akin to what you're trying to avoid. e.g.
struct Foo
{
int i;
this(int j)
{
i = j;
}
this(Foo rhs)
{
this = rhs;
}
}
void main()
{
auto f = Foo(5);
auto g = new Foo(f);
}
However, I just opened an enhancement request for making it so that new Foo(foo)
will just work, and with the next release of dmd (2.066) we're going to get universal construction for primitive types (e.g. new int(5)
will now work), so I think that there's a very good argument for this just working as well.
For now though, you're going to have to provide an extra constructor to get this to work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With