Re: struct constructors and destructors.
On Wednesday, 19 July 2017 at 14:09:32 UTC, SrMordred wrote: Hm, isnt that wrong? Did my post even go through? http://forum.dlang.org/post/udaxeyujrafklzpww...@forum.dlang.org What's going on here is actually pretty simple. Though calling a destructor on a default-initialized struct should always be valid anyway.
Re: struct constructors and destructors.
On Thursday, 20 July 2017 at 09:09:42 UTC, Danni Coy wrote: On Thu, Jul 20, 2017 at 12:19 AM, SrMordred via Digitalmars-d < digitalmars-d@puremagic.com> wrote: On Wednesday, 19 July 2017 at 14:09:32 UTC, SrMordred wrote: On Wednesday, 19 July 2017 at 09:09:40 UTC, Stefan Koch wrote: On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote: Is there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor? What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); } Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differently No Sorry, it behaves almost the same. just in D ctor and dtor are not called on declaration even if you drop " = void". Is there a way to delay the initialisation of a struct? void initialization + emplace: struct Foo { this (string name) { create_count++; } ~this() { destroy_count--; } } int create_count; int destroy_count; Foo foo = void; void main() { import std.stdio; import std.conv : emplace; writefln("this(string) ran %s times.", create_count); writefln("~this() ran %s times.", destroy_count); emplace(&foo, "test"); writeln("--- emplace ---"); writefln("this(string) ran %s times.", create_count); writefln("~this() ran %s times.", destroy_count); } this(string) ran 0 times. ~this() ran 0 times. --- emplace --- this(string) ran 1 times. ~this() ran 0 times. https://is.gd/G06GvK
Re: struct constructors and destructors.
On Thu, Jul 20, 2017 at 12:19 AM, SrMordred via Digitalmars-d < digitalmars-d@puremagic.com> wrote: > On Wednesday, 19 July 2017 at 14:09:32 UTC, SrMordred wrote: > >> On Wednesday, 19 July 2017 at 09:09:40 UTC, Stefan Koch wrote: >> >>> On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote: >>> Is there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor? >>> >>> What happens is this. >>> >>> void open() >>> { >>> foo = () { >>> Foo _tmp = Foo.__ctor("test"); >>> return _tmp; >>> } (); >>> } >>> >> >> Hm, isnt that wrong? >> If I destroy resources on the dtor, wouldn't it invalidate the resource >> on the copy? >> Also, C++ behaves differently >> > > No Sorry, it behaves almost the same. > just in D ctor and dtor are not called on declaration even if you drop " = > void". > Is there a way to delay the initialisation of a struct?
Re: struct constructors and destructors.
On Wednesday, 19 July 2017 at 14:09:32 UTC, SrMordred wrote: On Wednesday, 19 July 2017 at 09:09:40 UTC, Stefan Koch wrote: On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote: Is there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor? What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); } Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differently No Sorry, it behaves almost the same. just in D ctor and dtor are not called on declaration even if you drop " = void".
Re: struct constructors and destructors.
On Wednesday, 19 July 2017 at 09:09:40 UTC, Stefan Koch wrote: On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote: Is there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor? What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); } Hm, isnt that wrong? If I destroy resources on the dtor, wouldn't it invalidate the resource on the copy? Also, C++ behaves differently
Re: struct constructors and destructors.
Yeah somehow I read that as a question -- must be getting tired. That makes more sense. is there any way to On Wed, Jul 19, 2017 at 10:34 PM, Stefan Koch via Digitalmars-d < digitalmars-d@puremagic.com> wrote: > On Wednesday, 19 July 2017 at 12:23:06 UTC, Danni Coy wrote: > >> On Wed, Jul 19, 2017 at 7:09 PM, Stefan Koch via Digitalmars-d < >> digitalmars-d@puremagic.com> wrote: >> >> >>> What happens is this. >>> >>> void open() >>> { >>> foo = () { >>> Foo _tmp = Foo.__ctor("test"); >>> return _tmp; >>> } (); >>> } >>> >>> >>> Error: need 'this' for 'this' of type 'ref Foo(string s)' >>> >> > I posted pseudo code to show you that you are creating a temporary. > Which leaves the scope after assigning. > And therefore triggers the destructor. >
Re: struct constructors and destructors.
On Wednesday, 19 July 2017 at 12:34:50 UTC, Stefan Koch wrote: Which leaves the scope after assigning. And therefore triggers the destructor. No, that's not the case. There is a temporary, but its destructor is not called. The existing object in `foo` is destroyed, so the new one can be moved (and indeed moved, not copied, so no postblit, no dtor call, though it might or might not invalidate internal pointers - that's why the spec bans those) into its place.
Re: struct constructors and destructors.
On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote: tries to OpAssign foo to itself then calls foo's destructor? Are you sure that's what's actually happening? What should be happening there is: 1) it calls Foo's constructor on a temporary location 2) it destroys the old contents of `foo` 3) it moves the Foo from (1) into the variable freshly destroyed from (2) It is void initialized, so you might think there are no old contents of foo, but the compiler doesn't know this for certain (consider you called `open` twice. would be true the first time, but not the second time. the compiler needs to generate the function so it works both times). There is a function which the compiler knows will only be called once though: a static constructor. --- shared static this() { foo = Foo("test"); } --- That only runs once, and the compiler will skip the destruction of old `foo` as long as it isn't already initialized. Ironically, removing the `= void` from it causes the compiler to realize this and only use the ctor initialization. Otherwise, it tries to destroy the existing item, apparently not realizing it was void arguably a small compiler bug there.
Re: struct constructors and destructors.
On Wednesday, 19 July 2017 at 12:23:06 UTC, Danni Coy wrote: On Wed, Jul 19, 2017 at 7:09 PM, Stefan Koch via Digitalmars-d < digitalmars-d@puremagic.com> wrote: What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); } Error: need 'this' for 'this' of type 'ref Foo(string s)' I posted pseudo code to show you that you are creating a temporary. Which leaves the scope after assigning. And therefore triggers the destructor.
Re: struct constructors and destructors.
On Wed, Jul 19, 2017 at 7:09 PM, Stefan Koch via Digitalmars-d < digitalmars-d@puremagic.com> wrote: > > What happens is this. > > void open() > { > foo = () { > Foo _tmp = Foo.__ctor("test"); > return _tmp; > } (); > } > > > Error: need 'this' for 'this' of type 'ref Foo(string s)'
Re: struct constructors and destructors.
On Wednesday, 19 July 2017 at 07:48:28 UTC, Danni Coy wrote: Is there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor? What happens is this. void open() { foo = () { Foo _tmp = Foo.__ctor("test"); return _tmp; } (); }
struct constructors and destructors.
Is there a reason that the following code struct Foo { this (string name) { do_something(name); } ~this() { undo_something(); } } Foo foo = void; void open() { foo = Foo("test"); // <- this line } tries to OpAssign foo to itself then calls foo's destructor?
Re: Standard struct constructors for the heap?
On Wed, 16 May 2012 19:50:25 -0400, bearophile wrote: Regarding the efforts of removing limitations from D, do you know if there are problems in implementing this oldish enhancement request? http://d.puremagic.com/issues/show_bug.cgi?id=4086 Should be absolutely feasible. I'd also like to see this work: struct X { int x; this(int x) {this.x = x;} } void main(){ X x; // no ctor needed X *xp = new X; // but this is an error! } -Steve
Re: Standard struct constructors for the heap?
Andrej Mitrovic: Mixin workaround: Yeah, in some cases I have used a similar workaround. Now I'd like to avoid the workaround. Bye, bearophile
Re: Standard struct constructors for the heap?
On 5/17/12, bearophile wrote: > snip Mixin workaround: import std.conv; @property string makeCtors(T)() { T t; string res; foreach (i; 0 .. typeof(t.tupleof).length) { res ~= "this(typeof(this.tupleof[0.." ~ to!string(i+1) ~ "]) tup) { this.tupleof[0.." ~ to!string(i+1) ~ "] = tup; }\n"; } return res; } struct Node { mixin(makeCtors!Node); int data; Node* next; } void main() { Node* n1 = new Node(10); // OK Node* n2 = new Node(10, null); // OK }
Re: Standard struct constructors for the heap?
struct Node { int data; Node* next; } void main() { Node n1 = new Node(10); // OK Node n2 = new Node(10, null); // OK } I am sleepy. Third try: struct Node { int data; Node* next; } void main() { Node* n1 = new Node(10); // OK Node* n2 = new Node(10, null); // OK }
Re: Standard struct constructors for the heap?
struct Node { int data; Node* next; } void main() { Node n1 = Node(10); // OK Node n2 = Node(10, null); // OK } Sorry, I meant: struct Node { int data; Node* next; } void main() { Node n1 = new Node(10); // OK Node n2 = new Node(10, null); // OK } Bye, bearophile
Standard struct constructors for the heap?
Regarding the efforts of removing limitations from D, do you know if there are problems in implementing this oldish enhancement request? http://d.puremagic.com/issues/show_bug.cgi?id=4086 The idea is to just allow the heap creation of simple structs with no need to define a constructor: struct Node { int data; Node* next; } void main() { Node n1 = Node(10); // OK Node n2 = Node(10, null); // OK } I am writing many of those stupid struct initializations, it's boring busy work and they don't make the code more readable, just longer, so I'd like D to define them by itself: this(int data_=int.init, Node* next_=(Node*).init) pure nothrow @safe { this.data = data_; this.next = next_; } Removing this limit also makes D more uniform with locally-allocated struct construction semantics. Bye, bearophile
Re: Templated Struct Constructors
On Wed, Dec 21, 2011 at 10:32 PM, kenji hara wrote: > Please file it into bugzilla, because it is a bug. > I'll post a patch to fix it. > > Kenji Hara > Filed: http://d.puremagic.com/issues/show_bug.cgi?id=7150 Thanks!
Re: Templated Struct Constructors
Please file it into bugzilla, because it is a bug. I'll post a patch to fix it. Kenji Hara 2011/12/22 Andrew Wiley : > Is this a bug, or are templated struct constructors not allowed to > call other constructors? > > --- > struct A { > this(T)(T thing, int i) { > this(thing, i > 0); // Error: constructor call must be in a constructor > } > this(T)(T thing, bool b) { > } > } > > void main() { > auto a = A(5, 5); // Error: template instance > constructtest.A.__ctor!(int) error instantiating > } > ---
Templated Struct Constructors
Is this a bug, or are templated struct constructors not allowed to call other constructors? --- struct A { this(T)(T thing, int i) { this(thing, i > 0); // Error: constructor call must be in a constructor } this(T)(T thing, bool b) { } } void main() { auto a = A(5, 5); // Error: template instance constructtest.A.__ctor!(int) error instantiating } ---
Re: allowing zero-argument runtime-only struct constructors
Some days ago, I created patch, and posted pull request #72. http://d.puremagic.com/issues/show_bug.cgi?id=6036 https://github.com/D-Programming-Language/dmd/pull/72 This patch fixes some opCall problem, and allow a zero-argument default constructor on stack allocation, even exists multiple-argument explicit constructors. > // Calls zero-argument constructor function, > // due to parentheses after type. > // Compile-time error if no zero-argument constructor defined. > MyStruct ms3 = MyStruct(); This will be passing compilation with my patch (unless zero-argument static opCall is defined). > // Calls zero-argument constructor function, > // due to parentheses after type. > // Compile-time error if no zero-argument constructor defined. > // This behavior CANNOT BE GOTTEN with new and opCall in current > // versions of D to my knowledge. > MyStruct *ms4 = new MyStruct(); Unfortunately, my patch doesn't fix this behavior. Please post a new report into bugzilla with test cases. Kenji Hara
allowing zero-argument runtime-only struct constructors
Hello everyone! This is a continuation of a discussion on digitalmars.D.learn. So I'm investigating the possibility of permitting a syntax which would allow a zero-argument struct constructor to be defined and called explicitly like their multiple-argument constructor cousins. On 5/20/11 5:31 PM, Andrej Mitrovic wrote: > http://www.digitalmars.com/d/archives/digitalmars/D/Why_no_struct_default_constructors_129559.html I see that D's omitting a zero-argument struct constructor has to do with default initialization. What I propose is NOT a "default constructor" that will *automatically* be run any time a struct is declared or implicitly allocated, but rather one that can only be explicitly run at run-time (just like the 1-or-more parameter struct constructors already implemented in D2.0). Would it be possible to implement new semantics so that the following are true: // These two are always default initialized // without constructor call. MyStruct ms1; MyStruct ms2 = MyStruct.init; // Calls zero-argument constructor function, // due to parentheses after type. // Compile-time error if no zero-argument constructor defined. MyStruct ms3 = MyStruct(); // Always default initialized without constructor call. MyStruct* ms5 = new MyStruct; // Calls zero-argument constructor function, // due to parentheses after type. // Compile-time error if no zero-argument constructor defined. // This behavior CANNOT BE GOTTEN with new and opCall in current // versions of D to my knowledge. MyStruct *ms4 = new MyStruct(); Any big reasons why this would be bad, undesirable, or not implementable? The struct's .init property would still be known at compile time so there would be no worries about exceptions being thrown and chaotic stuff happening at compile time. The zero-argument constructor could run at run time or not run according to the choice of the programmer. Also, there would not have to be a distinction between constructor functions of different argument numbers--all constructors could have the same syntax instead of some with regular constructor syntax and another hacked on using opCall. What do people think? -- Christopher
Re: Struct constructors
That looks like a similar issue. Thanks!
Re: Struct constructors
Probably related to http://d.puremagic.com/issues/show_bug.cgi?id=5460
Re: Struct constructors
Am 20.01.2011 19:42, schrieb Sean Eskapp: In code like this: import std.stdio; struct foo { int val; static immutable bar = foo(1); this(int val) { this.val = 50; } } void main() { writeln(foo.bar.val); } The user-defined struct constructor is not called, because it's overridden by a built-in constructor which treats it like an initializer list. Shouldn't constructors in structs either generate errors/warnings, or work as they would appear to? See http://d.puremagic.com/issues/show_bug.cgi?id=3863.
Struct constructors
In code like this: import std.stdio; struct foo { int val; static immutable bar = foo(1); this(int val) { this.val = 50; } } void main() { writeln(foo.bar.val); } The user-defined struct constructor is not called, because it's overridden by a built-in constructor which treats it like an initializer list. Shouldn't constructors in structs either generate errors/warnings, or work as they would appear to?
Re: Default struct constructors with pure
On Thursday, October 07, 2010 16:42:47 Denis Koroskin wrote: > On Fri, 08 Oct 2010 03:31:54 +0400, Jonathan M Davis > > wrote: > > Isn't the main > > problem with having default constructors for structs that the default > > constructor must result in the same value every time so that the > > compiler can > > set init appropriately? > > Problem is that requirement is too restrictive. If ctor is pure, doesn't > access globals and results in perfectly same objects, then why can't you > do the initialization at compile-time? You usually can, that's not the > issue. > The issue is that sometimes you need to call external functionals that are > not pure in general (e.g. allocate some resources, initialize fields with > unique values, register itself somewhere etc). With the relaxed purity rules (which should be in the next release of dmd), that problem should be somewhat mitigated. But you still won't be able to call globals. - Jonathan M Davis
Re: Default struct constructors with pure
On Fri, 08 Oct 2010 03:31:54 +0400, Jonathan M Davis wrote: Isn't the main problem with having default constructors for structs that the default constructor must result in the same value every time so that the compiler can set init appropriately? Problem is that requirement is too restrictive. If ctor is pure, doesn't access globals and results in perfectly same objects, then why can't you do the initialization at compile-time? You usually can, that's not the issue. The issue is that sometimes you need to call external functionals that are not pure in general (e.g. allocate some resources, initialize fields with unique values, register itself somewhere etc).
Default struct constructors with pure
This has probably been brought up before, but given that the lack of default constructors for structs was a major problem for the QtD folks, I've been thinking about the problem again, and I was wondering whether it would work to have default constructors for structs as long as they were pure? Isn't the main problem with having default constructors for structs that the default constructor must result in the same value every time so that the compiler can set init appropriately? Or is there something else to it? It does seem to me that we should get default constructors for structs to work if we can. It's obviously been causing a problem in real code, including for major projects like QtD. - Jonathan M Davis
Re: Syntax for struct constructors
Ali Ãehreli Wrote: > > but it would be nicer if you could just do: > > > > Bar bar(256); > > I miss that from C++ too. I assumed that there must be reasons related > to D's syntax for not allowing that. This syntax is reserved for function prototypes.
Re: Syntax for struct constructors
Steve Teale wrote: > The D2 structs and unions documentation tells how to define a struct > constructor (that's a mouthful). But it doesn't tell how to use it. Seems > like if you have say > > struct Bar > { > int[] a; > this(uint sz) { a.length = sz; } > } > > you can do either: > > Bar bar = Bar(256); > > or: > > Bar bar; > bar = bar(256); You probably meant Bar(256) on the right hand side? Then it's a struct literal. In any case, even if the produced codes are the same; *I think* the latter is actually technically default construction, followed by assignment. Which may involve different operations, depending on the struct... > but it would be nicer if you could just do: > > Bar bar(256); I miss that from C++ too. I assumed that there must be reasons related to D's syntax for not allowing that. I've settled to this syntax myself, which is effectively the same as your first above: auto bar = Bar(256); > > In any case, it should be documented. Ali
Syntax for struct constructors
The D2 structs and unions documentation tells how to define a struct constructor (that's a mouthful). But it doesn't tell how to use it. Seems like if you have say struct Bar { int[] a; this(uint sz) { a.length = sz; } } you can do either: Bar bar = Bar(256); or: Bar bar; bar = bar(256); but it would be nicer if you could just do: Bar bar(256); In any case, it should be documented.
Re: Struct constructors and opCall
On Tue, Mar 17, 2009 at 10:23 PM, Gide Nwawudu wrote: > On Tue, 17 Mar 2009 11:59:42 +0100, Lars Kyllingstad > wrote: > >>I've come across the following strange behaviour in D2. Consider a >>struct with a constructor, static opCall and non-static opCall: >> >> import std.stdio; >> >> struct Foo >> { >> this(int i) { writefln("constructor"); } >> static void opCall(int i) { writefln("static opCall"); } >> void opCall(int i) { writefln("instance opCall"); } >> } >> >> void main() >> { >> auto foo = Foo(1); >> Foo(1); >> foo(1); >> } >> >>I expected that either compilation should fail because of ambiguity, or >>the program should compile and run with the following output: >> >> constructor >> static opCall >> instance opCall >> >>Instead, compiled with the newest DMD (2.026), it prints >> >> constructor >> constructor >> constructor >> >>This has to be a bug. Is it a known one? I tried searching for "struct >>constructor opCall" in both Bugzilla and Google, but couldn't find anything. >> >>-Lars > > > http://www.digitalmars.com/d/archives/digitalmars/D/announce/DMD_1.035_and_2.019_releases_12806.html#N12833 > > Walter wrote: > "If there's any constructor defined for S, then S(args) is a > constructor call. > > If there's any opCall defined for S, then S(args) is an opCall call. > > Otherwise, it's a struct literal." foo(1) calling the constructor is almost certainly a bug, though. It really should call the instance opCall.
Re: Struct constructors and opCall
On Tue, 17 Mar 2009 11:59:42 +0100, Lars Kyllingstad wrote: >I've come across the following strange behaviour in D2. Consider a >struct with a constructor, static opCall and non-static opCall: > > import std.stdio; > > struct Foo > { > this(int i) { writefln("constructor"); } > static void opCall(int i) { writefln("static opCall"); } > void opCall(int i){ writefln("instance opCall"); } > } > > void main() > { > auto foo = Foo(1); > Foo(1); > foo(1); > } > >I expected that either compilation should fail because of ambiguity, or >the program should compile and run with the following output: > > constructor > static opCall > instance opCall > >Instead, compiled with the newest DMD (2.026), it prints > > constructor > constructor > constructor > >This has to be a bug. Is it a known one? I tried searching for "struct >constructor opCall" in both Bugzilla and Google, but couldn't find anything. > >-Lars http://www.digitalmars.com/d/archives/digitalmars/D/announce/DMD_1.035_and_2.019_releases_12806.html#N12833 Walter wrote: "If there's any constructor defined for S, then S(args) is a constructor call. If there's any opCall defined for S, then S(args) is an opCall call. Otherwise, it's a struct literal." Gide
Re: Struct constructors and opCall
Lars Kyllingstad wrote: I've come across the following strange behaviour in D2. Consider a struct with a constructor, static opCall and non-static opCall: import std.stdio; struct Foo { this(int i) { writefln("constructor"); } static void opCall(int i) { writefln("static opCall"); } void opCall(int i){ writefln("instance opCall"); } } void main() { auto foo = Foo(1); Foo(1); foo(1); } I expected that either compilation should fail because of ambiguity, or the program should compile and run with the following output: constructor static opCall instance opCall Instead, compiled with the newest DMD (2.026), it prints constructor constructor constructor This has to be a bug. Is it a known one? I tried searching for "struct constructor opCall" in both Bugzilla and Google, but couldn't find anything. -Lars You can always report it as a bug and if its a duplicate; it'll be closed as one.
Struct constructors and opCall
I've come across the following strange behaviour in D2. Consider a struct with a constructor, static opCall and non-static opCall: import std.stdio; struct Foo { this(int i) { writefln("constructor"); } static void opCall(int i) { writefln("static opCall"); } void opCall(int i){ writefln("instance opCall"); } } void main() { auto foo = Foo(1); Foo(1); foo(1); } I expected that either compilation should fail because of ambiguity, or the program should compile and run with the following output: constructor static opCall instance opCall Instead, compiled with the newest DMD (2.026), it prints constructor constructor constructor This has to be a bug. Is it a known one? I tried searching for "struct constructor opCall" in both Bugzilla and Google, but couldn't find anything. -Lars