digitalmars.D.learn - Copying reference types by value
- Joseph Rushton Wakeling (37/37) Apr 17 2013 Hello all,
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (15/24) Apr 17 2013 that were
- Joseph Rushton Wakeling (9/19) Apr 17 2013 Ahh, so you mean that the current members of a get discarded and replace...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (26/46) Apr 17 2013 what you need:
- Joseph Rushton Wakeling (8/22) Apr 18 2013 Could you expand a bit on that? Just that I'm not sure I understand you...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (53/62) Apr 18 2013 thing is.
Hello all, Suppose I have a couple of variables a, b that are reference types (e.g. arrays or classes). Then, setting a = b will mean that the two reference the same entity. If they're arrays, one can copy the values readily by setting a[] = b[], but this isn't a generic solution -- suppose instead of arrays, I a and b are instances of class A { int one; double two; size_t three; this(int _one, double _two, size_t _three) { one = _one; two = _two; three = _three; } } Now, I can see several solutions. The first is just to define a generic copy function, like, void copyMyClass(const A from, ref A to) { ... } ... which copies over values. However, as a general solution that seems a bit dodgy as it presumes I have the right to read and write all internal values of the class. Defining a .dup method doesn't seem appropriate either because although it allows me to duplicate the values, setting a = b.dup; will mean that a now becomes a new object, and any other entities that were pointing at the original a will suddenly become decoupled from its values. So, if I do, c = a; a = b.dup; ... I will no longer have c equal to a. So, can anyone recommend an appropriate general method for copying the values of one reference type instance to another? Perhaps an appropriate operator to overload? Thanks & best wishes, -- Joe
Apr 17 2013
On 04/17/2013 09:17 AM, Joseph Rushton Wakeling wrote:Defining a .dup method doesn't seem appropriate either becausealthough itallows me to duplicate the values, setting a = b.dup; will mean that a now becomes a new object, and any other entitiesthat werepointing at the original a will suddenly become decoupled from itsvalues. So,if I do, c = a; a = b.dup; ... I will no longer have c equal to a.I haven't used it anywhere but I did think about this very issue just the other day. I thought about defining a takeOver() member function that does what you need: // take over the members of b a.takeOver(b); // b becomes null (or .init?) Using takeOver() along with dup(), one can copy state: a.takeOver(b.dup()); Of course there can be a wrapper function for that. :) But I am curious as well. What do others do in such cases? Are there Ali
Apr 17 2013
On 04/17/2013 06:54 PM, Ali Çehreli wrote:I haven't used it anywhere but I did think about this very issue just the other day. I thought about defining a takeOver() member function that does what you need: // take over the members of b a.takeOver(b); // b becomes null (or .init?)Ahh, so you mean that the current members of a get discarded and replaced with those of b?Using takeOver() along with dup(), one can copy state: a.takeOver(b.dup()); Of course there can be a wrapper function for that. :)It's an intriguing thought. How do you get round the issue of private variables ... ? And what's the benefit over a method like, say, a.copyFrom(b); ... which just copies values between corresponding variables? (Leaving aside that takeOver has applications of its own -- I mean my question purely in the context of copying values.)
Apr 17 2013
On 04/17/2013 10:09 AM, Joseph Rushton Wakeling wrote:On 04/17/2013 06:54 PM, Ali Çehreli wrote:just the otherI haven't used it anywhere but I did think about this very issuewhat you need:day. I thought about defining a takeOver() member function that doesreplaced with// take over the members of b a.takeOver(b); // b becomes null (or .init?)Ahh, so you mean that the current members of a get discarded andthose of b?Yes but as I said I am not sure how useful or needed this whole thing is. The language handles copy, move, and assignment for structs. takeOver() seems to be a primitive operation for classes.private variablesUsing takeOver() along with dup(), one can copy state: a.takeOver(b.dup()); Of course there can be a wrapper function for that. :)It's an intriguing thought. How do you get round the issue of... ?takeOver()'s parameter is presumably the same type as the class's so the private members are accessible. Of course any member may be well encapsulated; then, takeOver() depends on similar functionality that those members provide, perhaps through member functions that are again named takeOver() but there is no standard for it. A framework may require that such "take over" member functions should be marked by a specific UDA.And what's the benefit over a method like, say, a.copyFrom(b);That's what I meant by "a wrapper function." But I think move is a more fundamental operation that elides a copy. If we had only copyFrom(), then the following would indeed need to copy: // foo() returns a class object a.copyFrom(foo()); On the other hand, takeOver() would have the ability to move the members of the returned rvalue object without needing to copy.... which just copies values between corresponding variables?(Leaving asidethat takeOver has applications of its own -- I mean my questionpurely in thecontext of copying values.)Agreed. Ali
Apr 17 2013
On 04/17/2013 10:29 PM, Ali Çehreli wrote:Yes but as I said I am not sure how useful or needed this whole thing is. The language handles copy, move, and assignment for structs. takeOver() seems to be a primitive operation for classes.Could you expand a bit on that? Just that I'm not sure I understand your meaning completely, and I'm curious. :-)That's what I meant by "a wrapper function." But I think move is a more fundamental operation that elides a copy. If we had only copyFrom(), then the following would indeed need to copy: // foo() returns a class object a.copyFrom(foo()); On the other hand, takeOver() would have the ability to move the members of the returned rvalue object without needing to copy.OK, clear. In fact seems possible that copying vs. takeover might be useful to define separately and use whichever is optimal for the given use-case.Agreed.I'd assumed this problem would be some fairly straightforward aspect of the language that I just wasn't familiar with, so I'm quite struck by the fact that it actually seems a non-trivial problem.
Apr 18 2013
On 04/18/2013 06:22 AM, Joseph Rushton Wakeling wrote:> On 04/17/2013 10:29 PM, Ali Çehreli wrote:thing is.Yes but as I said I am not sure how useful or needed this wholetakeOver() seems toThe language handles copy, move, and assignment for structs.Being value types, structs enjoy automatic handling of copy, assignment, and in the case of rvalues, move. struct S { int i; } S makeS() { return S(); } void main() { auto a = S(); auto b = a; // a is copied to b b = a; // a is assigned to b b = makeS(); // the returned rvalue is 'moved' to b } Of course that works only for structs with simple value members. When the automatic handling is not sufficient or does the wrong thing, then the programmer must provide this(this), opAssign(), or ~this(). Things get more interesting when the members are mutable or immutable references. With the above definition of S, all of the following compile: immutable(S) imm0; S mut = imm0; // immutable to mutable immutable(S) imm1 = mut; // mutable to immutable immutable(S) imm2 = imm0; // immutable to immutable Now naively add another member to S: struct S { int i; int[] arr; // <-- added } Only the latter of the three assignments compile: immutable(S) imm0; S mut = imm0; // compilation ERROR immutable(S) imm1 = mut; // compilation ERROR immutable(S) imm2 = imm0; // compiles Anyway... I am trying to wrap up what I have learned so far before going any further. :) For classes, none of these operations make sense: There is no automatic copying, no automatic assignment, nor there are rvalues to move.be a primitive operation for classes.Could you expand a bit on that? Just that I'm not sure I understand your meaning completely, and I'm curious. :-)I'd assumed this problem would be some fairly straightforward aspectof thelanguage that I just wasn't familiar with, so I'm quite struck by thefact thatit actually seems a non-trivial problem.My experience has been with C++ so I don't know how this is solved in languages, which would also mean that this is not a problem with D classes. Rather, if one has decided to go with a class, then value semantics were not a consideration to begin with. Ali
Apr 18 2013