D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 4247 - Cannot create default-constructed struct on heap when constructor is defined
Summary: Cannot create default-constructed struct on heap when constructor is defined
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 major
Assignee: No Owner
URL:
Keywords: pull, rejects-valid
: 8760 (view as issue list)
Depends on:
Blocks:
 
Reported: 2010-05-28 15:55 UTC by Steven Schveighoffer
Modified: 2014-09-14 14:54 UTC (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Steven Schveighoffer 2010-05-28 15:55:49 UTC
If I want a struct on the heap, I do this:

struct S
{
}

auto s = new S;

But if I give S a constructor:

struct S
{
  this(int n) {}
}

auto s = new S;

dmd complains:
Error: constructor S.this (int n) is not callable using argument types ()

So I do this:

struct S
{
  this() {}
  this(int n) {}
}

but dmd now complains:
Error: constructor S.this default constructor not allowed for structs

So the auto s = new S is no longer usable.  However, I can easily declare a struct S on the stack, or create a new array of S.  In fact, you can do:

auto s = (new S[1])[0];

and achieve the desired effect, but this is oh so ugly.

Bottom line, if I can construct a struct on the stack, I should be able to identically construct it on the heap.
Comment 1 Andrej Mitrovic 2010-09-11 06:37:01 UTC
You can't make your own default constructor for structs, this is explained in TDPL. A constructor with no arguments is created by default, with each field of a struct initialized to it's type's .init property. You cannot override this. See page 244 in TDPL.

Also, since when are structs allowed to be allocated on the heap? TDPL explicitly states that structs have scoped lifetime.
Comment 2 bearophile_hugs 2010-09-11 07:00:37 UTC
(In reply to comment #1)
> Also, since when are structs allowed to be allocated on the heap? TDPL
> explicitly states that structs have scoped lifetime.

I double TDPL says this. And if it says so, then it's wrong. TDPL is not a religious book.


> You cannot override this. See page 244 in TDPL.

The reason given at page 244 is that all type needs a statically defined init.

On the other hand the need to allocate a struct on the heap with no arguments is real, and the current workarounds look bad for a nice language as D2. This small program shows that you can create a S2 on the stack:


struct S1 {}
struct S2 {
    this(int) {}
}
void main() {
    S1 s1a;
    auto s1b = new S1;
    S2 s2a; // OK
    auto s2b = new S2; // ERR
}


So I think "new S2;" may just create the same struct that "S2 s2a;" creates, but allocate it on the heap instead of the stack. I think this is a solution.
Comment 3 nfxjfg 2010-09-11 07:10:59 UTC
(In reply to comment #1)
> Also, since when are structs allowed to be allocated on the heap? TDPL
> explicitly states that structs have scoped lifetime.

If structs couldn't be allocated on the heap, you'd have to forget about struct arrays. And this is pure bullshit. E.g. this wouldn't be allowed anymore:

S[] array;
array.length = 1;

You couldn't seriously want this to be illegal.

(This code snippet also shows that it's advantageous to force structs having a "simple" default ctor, i.e. one that doesn't require the runtime to run code on each element to construct it.)
Comment 4 Andrej Mitrovic 2010-09-11 08:00:51 UTC
(In reply to comment #2)
> (In reply to comment #1)
> > Also, since when are structs allowed to be allocated on the heap? TDPL
> > explicitly states that structs have scoped lifetime.
> 
> I double TDPL says this. And if it says so, then it's wrong. TDPL is not a
> religious book.
> 

It's not a religious book, but since the D docs aren't kept up to date, who can you trust? And AFAIK Andrei & Walter have both reviewed TDPL and agree with what it states there. As for structs on the heap, I simply didn't know it was possible to do that, so maybe I judged to quickly from what I've read. 

Whether it's legal or not is not up to me, so don't take it personal please. :)
Comment 5 Andrei Alexandrescu 2010-09-11 09:57:21 UTC
(In reply to comment #4)
> (In reply to comment #2)
> > (In reply to comment #1)
> > > Also, since when are structs allowed to be allocated on the heap? TDPL
> > > explicitly states that structs have scoped lifetime.
> > 
> > I double TDPL says this. And if it says so, then it's wrong. TDPL is not a
> > religious book.
> > 
> 
> It's not a religious book, but since the D docs aren't kept up to date, who can
> you trust? And AFAIK Andrei & Walter have both reviewed TDPL and agree with
> what it states there. As for structs on the heap, I simply didn't know it was
> possible to do that, so maybe I judged to quickly from what I've read. 
> 
> Whether it's legal or not is not up to me, so don't take it personal please. :)

Obviously there are many ways to allocate struct objects on the heap: using new, as members of class objects, or as elements of arrays. All of them are described in TDPL. If some particular sentence of TDPL seems to rule out such possibilities please let me know.
Comment 6 Andrej Mitrovic 2010-09-11 10:45:49 UTC
(In reply to comment #5)
> (In reply to comment #4)
> > (In reply to comment #2)
> > > (In reply to comment #1)
> > > > Also, since when are structs allowed to be allocated on the heap? TDPL
> > > > explicitly states that structs have scoped lifetime.
> > > 
> > > I double TDPL says this. And if it says so, then it's wrong. TDPL is not a
> > > religious book.
> > > 
> > 
> > It's not a religious book, but since the D docs aren't kept up to date, who can
> > you trust? And AFAIK Andrei & Walter have both reviewed TDPL and agree with
> > what it states there. As for structs on the heap, I simply didn't know it was
> > possible to do that, so maybe I judged to quickly from what I've read. 
> > 
> > Whether it's legal or not is not up to me, so don't take it personal please. :)
> 
> Obviously there are many ways to allocate struct objects on the heap: using
> new, as members of class objects, or as elements of arrays. All of them are
> described in TDPL. If some particular sentence of TDPL seems to rule out such
> possibilities please let me know.

Described where exactly? I haven't seen any snippet of code using new for struct objects in the structs section from page 240 onwards. There's a mention of using classes inside structs, and dynamic arrays inside structs (where the postblit constructor comes in handy), but no mention on how to use structs on the heap. Maybe it's in a different section..?
Comment 7 Andrej Mitrovic 2013-02-18 10:05:18 UTC
(In reply to comment #6)
> Described where exactly?

Please ignore my comments from before as I didn't know at the time 'new'ing was possible for structs.
Comment 8 Maksim Zholudev 2013-04-15 07:09:04 UTC
(In reply to comment #0)
> So the auto s = new S is no longer usable.  However, I can easily declare a
> struct S on the stack, or create a new array of S.  In fact, you can do:
> 
> auto s = (new S[1])[0];
> 
> and achieve the desired effect, but this is oh so ugly.

This code would create structure on the heap and put COPY of it to `s`.
It is not the same as `auto s = new S`.

The workaround should be:
--------------------
auto s = (new S[1]).ptr;
--------------------
Comment 9 Steven Schveighoffer 2013-04-15 10:26:37 UTC
(In reply to comment #8)
> (In reply to comment #0)
> > So the auto s = new S is no longer usable.  However, I can easily declare a
> > struct S on the stack, or create a new array of S.  In fact, you can do:
> > 
> > auto s = (new S[1])[0];
> > 
> > and achieve the desired effect, but this is oh so ugly.
> 
> This code would create structure on the heap and put COPY of it to `s`.
> It is not the same as `auto s = new S`.
> 
> The workaround should be:
> --------------------
> auto s = (new S[1]).ptr;
> --------------------

Oh yes!  I was missing an & :)

Thanks
Comment 11 github-bugzilla 2013-04-15 20:00:15 UTC
Commits pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/17a69daa9c334407d4988037760de48f859fe0c6
fix Issue 4247 - Cannot create default-constructed struct on heap when constructor is defined

https://github.com/D-Programming-Language/dmd/commit/f0e2ec31995046396261aab401b8d20fa58dccdb
Merge pull request #1898 from 9rnsr/fix4247

Issue 4247 - Cannot create default-constructed struct on heap when constructor is defined
Comment 12 Kenji Hara 2014-09-14 14:54:46 UTC
*** Issue 8760 has been marked as a duplicate of this issue. ***