digitalmars.D - Struct d'tors and destructive assignment of return vals
- dsimcha (52/52) May 26 2009 import std.stdio;
- Steven Schveighoffer (3/35) May 26 2009 What if fun throws an exception?
- dsimcha (3/47) May 26 2009 Argh good point, didn't think of that. Then I guess you're just screwed...
- Steven Schveighoffer (3/10) May 26 2009 opAssign maybe? not sure...
- Andrei Alexandrescu (6/54) May 26 2009 This has been discussed by Bartosz, Walter, and myself quite a lot a
import std.stdio; struct RC { uint N; this(this) { writeln("Postblit: ", N); } ~this() { writeln("D'tor: ", N); } } RC fun() { writeln("Doing stuff..."); return RC(3); } void main() { RC foo = RC(1); writeln("Calling fun()..."); foo = fun(); writeln("Exiting..."); } Output: Calling fun()... Doing stuff... D'tor: 1 Exiting... D'tor: 3 Would it be feasible to require that, when a struct is being destructively assigned the return value of a function, the d'tor is called for the old contents before the function that provides the return value is called instead of calling it after? This would be useful, for example, for providing COW semantics when dealing with ranges whose elements are lazily constructed arrays: struct SomeRange { T[] someArray; uint* nExternalReferences; // to someArray. T[] popNext() { if(*nExternalReferences > 0) { someArray = someArray.dup; nExternalReferences = new uint; } // Modify someArray. return referenceCounted(someArray, nExternalReferences); } } Caller's end: SomeRange s; RefCounted r; while(!s.empty) { // The underlying array will constantly be dup'd because // the d'tor for r is not being called until after popNext() // is called. r = s.popNext; }
May 26 2009
On Tue, 26 May 2009 21:20:41 -0400, dsimcha <dsimcha yahoo.com> wrote:import std.stdio; struct RC { uint N; this(this) { writeln("Postblit: ", N); } ~this() { writeln("D'tor: ", N); } } RC fun() { writeln("Doing stuff..."); return RC(3); } void main() { RC foo = RC(1); writeln("Calling fun()..."); foo = fun(); writeln("Exiting..."); } Output: Calling fun()... Doing stuff... D'tor: 1 Exiting... D'tor: 3 Would it be feasible to require that, when a struct is being destructively assigned the return value of a function, the d'tor is called for the old contents before the function that provides the return value is called instead of calling it after?What if fun throws an exception? -Steve
May 26 2009
== Quote from Steven Schveighoffer (schveiguy yahoo.com)'s articleOn Tue, 26 May 2009 21:20:41 -0400, dsimcha <dsimcha yahoo.com> wrote:Argh good point, didn't think of that. Then I guess you're just screwed. In that case, do you see any other way to get good COW semantics in this situation?import std.stdio; struct RC { uint N; this(this) { writeln("Postblit: ", N); } ~this() { writeln("D'tor: ", N); } } RC fun() { writeln("Doing stuff..."); return RC(3); } void main() { RC foo = RC(1); writeln("Calling fun()..."); foo = fun(); writeln("Exiting..."); } Output: Calling fun()... Doing stuff... D'tor: 1 Exiting... D'tor: 3 Would it be feasible to require that, when a struct is being destructively assigned the return value of a function, the d'tor is called for the old contents before the function that provides the return value is called instead of calling it after?What if fun throws an exception? -Steve
May 26 2009
On Tue, 26 May 2009 21:44:51 -0400, dsimcha <dsimcha yahoo.com> wrote:== Quote from Steven Schveighoffer (schveiguy yahoo.com)'s articleopAssign maybe? not sure... -SteveWhat if fun throws an exception? -SteveArgh good point, didn't think of that. Then I guess you're just screwed. In that case, do you see any other way to get good COW semantics in this situation?
May 26 2009
dsimcha wrote:== Quote from Steven Schveighoffer (schveiguy yahoo.com)'s articleThis has been discussed by Bartosz, Walter, and myself quite a lot a couple of years ago. The solution we settled on was to always move the bits directly when a copy is the last access of the source (as is the case in your return expression). Walter hasn't implemented that yet. AndreiOn Tue, 26 May 2009 21:20:41 -0400, dsimcha <dsimcha yahoo.com> wrote:Argh good point, didn't think of that. Then I guess you're just screwed. In that case, do you see any other way to get good COW semantics in this situation?import std.stdio; struct RC { uint N; this(this) { writeln("Postblit: ", N); } ~this() { writeln("D'tor: ", N); } } RC fun() { writeln("Doing stuff..."); return RC(3); } void main() { RC foo = RC(1); writeln("Calling fun()..."); foo = fun(); writeln("Exiting..."); } Output: Calling fun()... Doing stuff... D'tor: 1 Exiting... D'tor: 3 Would it be feasible to require that, when a struct is being destructively assigned the return value of a function, the d'tor is called for the old contents before the function that provides the return value is called instead of calling it after?What if fun throws an exception? -Steve
May 26 2009