digitalmars.D.learn - opAssign and const?
- Era Scarecrow (30/30) May 03 2012 I have the following dilemma. Hopefully I have this right.
- Jonathan M Davis (6/45) May 03 2012 I believe that the issue is that x2 isn't const, so when the compiler de...
- Era Scarecrow (7/12) May 03 2012 I figured that was the case too. But I get the feeling that's
- Era Scarecrow (3/4) May 03 2012 Hmmm suppose to be OpAssign. Nothing quite like a bug in your
- Jonathan M Davis (3/16) May 03 2012 If you make the one which isn't a ref const as well, it'll probably work...
- Era Scarecrow (5/7) May 03 2012 Yeah I think so too. It will just be either a direct copy or I
- Jonathan M Davis (7/15) May 03 2012 With the last beta, there was a discussion in changing how ref and const...
- Era Scarecrow (6/12) May 04 2012 I'll be looking forward to how that works out. I'm trying to be
- Steven Schveighoffer (7/14) May 04 2012 I don't think it will make a copy of a temporary even if it's cast to
- Era Scarecrow (37/41) May 04 2012 Well the result seems to be true enough.. It also seems to work
- Era Scarecrow (45/48) May 04 2012 As I look at my code I realize why now. Pointers and arrays...
- Steven Schveighoffer (7/54) May 04 2012 y[] = x2.y[];
- Era Scarecrow (8/12) May 04 2012 That may deal with the language requirements, but the ideal was
- Steven Schveighoffer (6/13) May 04 2012 OK, I see what you are trying to do. I'll have to think about it some
- Era Scarecrow (27/41) May 04 2012 Well let's see if we can recap it into perspective so we're on
- Jonathan M Davis (11/38) May 04 2012 As I understand it, you don't need to do _anything_ special to avoid hav...
- Era Scarecrow (53/64) May 04 2012 That's what I originally thought too... But when I'm dealing
- Jonathan M Davis (26/105) May 04 2012 If you've declared an opAssign, I'd be very surprised if _any_ assignme=
- Era Scarecrow (11/31) May 04 2012 I guess there's one question left. Where does the struct live?
- Era Scarecrow (8/21) May 04 2012 Hmm maybe it should have a preference for Lvalue vs Rvalue...
- Jonathan M Davis (15/37) May 04 2012 ed)
- Era Scarecrow (4/22) May 04 2012 Your probably right.. Thanks, I'll repost this portion over
- Era Scarecrow (24/32) May 04 2012 TDPL pg. 145
- Jonathan M Davis (21/59) May 04 2012 You need to define enough that you can pass any X to one of them. Gener=
I have the following dilemma. Hopefully I have this right. struct X { ref X opAssign(X x2); ref X opAssign(ref X x2); } X fn(); void func(){ X x, x2; x = x2; //uses ref x = fn(); //without ref } According to the book, this is how it is suppose to be. const is a added promise not to modify anything. So... if i changed the ref to ref const... it won't call unless the item input was const as well. //same as above except.. struct X { ref X opAssign(X x2); ref X opAssign(ref const X x2); //const added } void func(){ X x, x2; const X x3; x = x2; //without ref??? x = x3; //ref } Since the input is intended to be read only anyways, why won't it work as expected with x = x2? This seems like a bug. If it's not, then I need to make two ref versions so it will behave properly. (If you need I can past actual working example)
May 03 2012
On Friday, May 04, 2012 07:49:29 Era Scarecrow wrote:I have the following dilemma. Hopefully I have this right. struct X { ref X opAssign(X x2); ref X opAssign(ref X x2); } X fn(); void func(){ X x, x2; x = x2; //uses ref x = fn(); //without ref } According to the book, this is how it is suppose to be. const is a added promise not to modify anything. So... if i changed the ref to ref const... it won't call unless the item input was const as well. //same as above except.. struct X { ref X opAssign(X x2); ref X opAssign(ref const X x2); //const added } void func(){ X x, x2; const X x3; x = x2; //without ref??? x = x3; //ref } Since the input is intended to be read only anyways, why won't it work as expected with x = x2? This seems like a bug. If it's not, then I need to make two ref versions so it will behave properly. (If you need I can past actual working example)I believe that the issue is that x2 isn't const, so when the compiler decides which of the two overloads to use, it picks the one which doesn't use const. If the const ref version were the only one, then it would work with x2, but since it isn't, the other one gets picked because it's deemed a better match. - Jonathan M Davis
May 03 2012
On Friday, 4 May 2012 at 06:15:21 UTC, Jonathan M Davis wrote:I believe that the issue is that x2 isn't const, so when the compiler decides which of the two overloads to use, it picks the one which doesn't use const. If the const ref version were the only one, then it would work with x2, but since it isn't, the other one gets picked because it's deemed a better match.I figured that was the case too. But I get the feeling that's wrong in this case. I was hoping to have only two declared opAssing's, one for temporaries (without ref) and one for copying. Kinda like the difference between saying a=b and a[]=b[] for an array. Be annoying if I had to force the cast to be const to do what I wanted; Right?
May 03 2012
On Friday, 4 May 2012 at 06:32:41 UTC, Era Scarecrow wrote:opAssing'sHmmm suppose to be OpAssign. Nothing quite like a bug in your automatic text converter right?
May 03 2012
On Friday, May 04, 2012 08:32:40 Era Scarecrow wrote:On Friday, 4 May 2012 at 06:15:21 UTC, Jonathan M Davis wrote:If you make the one which isn't a ref const as well, it'll probably work. - Jonathan M DavisI believe that the issue is that x2 isn't const, so when the compiler decides which of the two overloads to use, it picks the one which doesn't use const. If the const ref version were the only one, then it would work with x2, but since it isn't, the other one gets picked because it's deemed a better match.I figured that was the case too. But I get the feeling that's wrong in this case. I was hoping to have only two declared opAssing's, one for temporaries (without ref) and one for copying. Kinda like the difference between saying a=b and a[]=b[] for an array. Be annoying if I had to force the cast to be const to do what I wanted; Right?
May 03 2012
On Friday, 4 May 2012 at 06:48:40 UTC, Jonathan M Davis wrote:If you make the one which isn't a ref const as well, it'll probably work.Yeah I think so too. It will just be either a direct copy or I cast the object as const and pass it through. Seems like extra work to me and should be handled by the compiler. Anyways, thanks for looking at the problem with me.
May 03 2012
On Friday, May 04, 2012 08:52:49 Era Scarecrow wrote:On Friday, 4 May 2012 at 06:48:40 UTC, Jonathan M Davis wrote:With the last beta, there was a discussion in changing how ref and const ref works to allow rvalues while disallowing whatever use cases it is that causes problems with that in C++. If that gets sorted out and fully implemented, then you'd only need one overload. As it stands, the closest that you could get would be to use auto ref, but that only works with templated functions. - Jonathan M DavisIf you make the one which isn't a ref const as well, it'll probably work.Yeah I think so too. It will just be either a direct copy or I cast the object as const and pass it through. Seems like extra work to me and should be handled by the compiler. Anyways, thanks for looking at the problem with me.
May 03 2012
On Friday, 4 May 2012 at 06:55:47 UTC, Jonathan M Davis wrote:With the last beta, there was a discussion in changing how ref and const ref works to allow rvalues while disallowing whatever use cases it is that causes problems with that in C++. If that gets sorted out and fully implemented, then you'd only need one overload. As it stands, the closest that you could get would be to use auto ref, but that only works with templated functions.I'll be looking forward to how that works out. I'm trying to be contentious of what code I can label as const (usable) and what I can't. I know there will be cases where I am using my struct as const, and having this minor oddity come out of the woodwork is one of the first real issues I've found that wasn't my own fault.
May 04 2012
On Fri, 04 May 2012 02:52:49 -0400, Era Scarecrow <rtcvb32 yahoo.com> wrote:On Friday, 4 May 2012 at 06:48:40 UTC, Jonathan M Davis wrote:I don't think it will make a copy of a temporary even if it's cast to const. I think marking the non-ref version as const will solve the problem how you wish (as long as the argument really *isn't* modified inside that function). -SteveIf you make the one which isn't a ref const as well, it'll probably work.Yeah I think so too. It will just be either a direct copy or I cast the object as const and pass it through. Seems like extra work to me and should be handled by the compiler. Anyways, thanks for looking at the problem with me.
May 04 2012
On Friday, 4 May 2012 at 12:42:54 UTC, Steven Schveighoffer wrote:I don't think it will make a copy of a temporary even if it's cast to const. I think marking the non-ref version as const will solve the problem how you wish (as long as the argument really *isn't* modified inside that function).Well the result seems to be true enough.. It also seems to work if both are const. Why didn't I consider that before? Maybe it should be noted in the next TDPL book. import std.stdio; import std.conv; struct X { int x; int y; this (int x1, int y1) { x = x1; y = y1; } ref X opAssign(const X x2) { writeln("from temporary?"); x=x2.x; y=x2.y; return this; } ref X opAssign(const ref X x2) { writeln("copy specific values?"); x=x2.x; return this; } } //from temporary X fn() { return X(1,2); } void main() { X x = X(3,4); X y = X(5,6); x = y; // 5,4 or 5,6? writeln("Should selectively copy (5,4) - ", to!string(x)); x = fn(); // 1,2 writeln("should overwrite all (1,2)- ", to!string(x)); }
May 04 2012
On Friday, 4 May 2012 at 20:35:57 UTC, Era Scarecrow wrote:Well the result seems to be true enough.. It also seems to work if both are const. Why didn't I consider that before? Maybe it should be noted in the next TDPL book.As I look at my code I realize why now. Pointers and arrays... that's why... test.d(16): Error: cannot implicitly convert expression (x2.y) of type const(int[]) to int[] Which is why I was trying to suggest the ref was const since I wasn't modifying and could ensure it (just copying between buffers) but the temporary I'm taking over.. So that doesn't work now. This means I'll likely need 2 copies of the ref; 1 const and 1 non-const. import std.stdio; import std.conv; struct X { int x; int[] y; this (int x1, int y1) { x = x1; y ~= y1; } //const here won't work. ref X opAssign(const X x2) { writeln("from temporary?"); x=x2.x; y=x2.y; //breaks here return this; } ref X opAssign(ref const X x2) { writeln("copy specific values?"); x=x2.x; y[]=x2.y[]; return this; } } X fn() { return X(1,2); } void main() { X x = X(3,4); X y = X(5,6); x = y; writeln("Should selectively copy (ref)- ", to!string(x)); x = fn(); writeln("should overwrite all - ", to!string(x)); }
May 04 2012
On Fri, 04 May 2012 16:47:07 -0400, Era Scarecrow <rtcvb32 yahoo.com> wrote:On Friday, 4 May 2012 at 20:35:57 UTC, Era Scarecrow wrote:y[] = x2.y[]; // as you did belowWell the result seems to be true enough.. It also seems to work if both are const. Why didn't I consider that before? Maybe it should be noted in the next TDPL book.As I look at my code I realize why now. Pointers and arrays... that's why... test.d(16): Error: cannot implicitly convert expression (x2.y) of type const(int[]) to int[] Which is why I was trying to suggest the ref was const since I wasn't modifying and could ensure it (just copying between buffers) but the temporary I'm taking over.. So that doesn't work now. This means I'll likely need 2 copies of the ref; 1 const and 1 non-const. import std.stdio; import std.conv; struct X { int x; int[] y; this (int x1, int y1) { x = x1; y ~= y1; } //const here won't work. ref X opAssign(const X x2) { writeln("from temporary?"); x=x2.x; y=x2.y; //breaks herereturn this; } ref X opAssign(ref const X x2) { writeln("copy specific values?"); x=x2.x; y[]=x2.y[]; return this; } } X fn() { return X(1,2); } void main() { X x = X(3,4); X y = X(5,6); x = y; writeln("Should selectively copy (ref)- ", to!string(x)); x = fn(); writeln("should overwrite all - ", to!string(x)); }btw, are you sure the lengths will always be identical? Otherwise, you may want to do y.length = x2.y.length first. -Steve
May 04 2012
On Friday, 4 May 2012 at 21:12:55 UTC, Steven Schveighoffer wrote:y[] = x2.y[]; // as you did belowThat may deal with the language requirements, but the ideal was to take over the temporary; If not the ref would copy the contents. I wonder if I will need to have 2 copies of each opAssign to satisfy everything.btw, are you sure the lengths will always be identical? Otherwise, you may want to do y.length = x2.y.length first.This example code doesn't cover that, but yes I have checks in place for such an occurrence. Likely 99% of the time copying will be between identical sizes.
May 04 2012
On Fri, 04 May 2012 17:26:02 -0400, Era Scarecrow <rtcvb32 yahoo.com> wrote:On Friday, 4 May 2012 at 21:12:55 UTC, Steven Schveighoffer wrote:OK, I see what you are trying to do. I'll have to think about it some more. I'm very concerned that you could potentially end up calling this function with an lvalue, which would make this a disasterous strategy. -Stevey[] = x2.y[]; // as you did belowThat may deal with the language requirements, but the ideal was to take over the temporary; If not the ref would copy the contents. I wonder if I will need to have 2 copies of each opAssign to satisfy everything.
May 04 2012
On Friday, 4 May 2012 at 21:29:14 UTC, Steven Schveighoffer wrote:On Fri, 04 May 2012 17:26:02 -0400, Era ScarecrowOn Friday, 4 May 2012 at 21:12:55 UTC, Steven Schveighoffer wrote:y[] = x2.y[]; // as you did belowThat may deal with the language requirements, but the ideal was to take over the temporary; If not the ref would copy the contents. I wonder if I will need to have 2 copies of each opAssign to satisfy everything.OK, I see what you are trying to do. I'll have to think about it some more. I'm very concerned that you could potentially end up calling this function with an lvalue, which would make this a disastrous strategy.Well let's see if we can recap it into perspective so we're on the same Page. I'm trying to make a struct that on assignment will copy it's contents. On opAssign In both cases the mutable and const/immutable rvalue will copy it's contents. If it's a temporary (which is always returned as mutable) I want to take it over rather than copy the contents. The contents are likely referenced elsewhere already. Here's a stripped version of my struct, obviously with lots of missing unneeded stuff. struct X { ubyte[] buffer; //from temporary being returned. ref X opAssign(X rhs) { this.buffer = rhs.buffer; return this; } //copying from right side to left. ref X opAssign(ref X rhs) { if (buffer.length != rhs.length) { buffer.length = rhs.buffer.length; ptr = buffer.ptr; } buffer[] = rhs.buffer[]; return this; } }
May 04 2012
On Saturday, May 05, 2012 01:18:13 Era Scarecrow wrote:On Friday, 4 May 2012 at 21:29:14 UTC, Steven Schveighoffer wrote:As I understand it, you don't need to do _anything_ special to avoid having a temporary copied when passed to your function. Because it's a temporary, it should be moved into the function parameter, not copied. No postblit or opAssign will be executed. It's only when it's _not_ a temporary that a copy will be made. And even in _that_ case, it should be a move if that function call is the last place that the variable is used. So, I believe that you're trying to avoid copies that will never happen anyway. They would if you were dealing with C++ - particularly C++98 - but not in D (C++11 fixes the problem via move constructors). - Jonathan M DavisOn Fri, 04 May 2012 17:26:02 -0400, Era ScarecrowWell let's see if we can recap it into perspective so we're on the same Page. I'm trying to make a struct that on assignment will copy it's contents. On opAssign In both cases the mutable and const/immutable rvalue will copy it's contents. If it's a temporary (which is always returned as mutable) I want to take it over rather than copy the contents. The contents are likely referenced elsewhere already.On Friday, 4 May 2012 at 21:12:55 UTC, Steven Schveighoffer wrote:OK, I see what you are trying to do. I'll have to think about it some more. I'm very concerned that you could potentially end up calling this function with an lvalue, which would make this a disastrous strategy.y[] = x2.y[]; // as you did belowThat may deal with the language requirements, but the ideal was to take over the temporary; If not the ref would copy the contents. I wonder if I will need to have 2 copies of each opAssign to satisfy everything.
May 04 2012
On Saturday, 5 May 2012 at 02:21:06 UTC, Jonathan M Davis wrote:As I understand it, you don't need to do _anything_ special to avoid having a temporary copied when passed to your function. Because it's a temporary, it should be moved into the function parameter, not copied. No postblit or opAssign will be executed. It's only when it's _not_ a temporary that a copy will be made. And even in _that_ case, it should be a move if that function call is the last place that the variable is used.That's what I originally thought too... But when I'm dealing with the temporary there's something broken. So if I only have only the ref. Error: function X.opAssign (ref X rhs) is not callable using argument types (X) so; struct X { ref X opAssign(ref X rhs); } X func(); struct Y { X x; this() { x = func(); } } Unless there's a default it drops back to, it is only seeing the one assign function.So, I believe that you're trying to avoid copies that will never happen anyway. They would if you were dealing with C++ - particularly C++98 - but not in D (C++11 fixes the problem via move constructors).I'm not trying to avoid copying (Blocks are small so it's likely a tiny cost); I'm trying to keep arrays separate. Let's add to my example; I Hope I got it right based on the behavior I'm seeing. struct X { ubyte[] buffer; this(ubyte[] b) { buffer = b; } ref X opAssign(ref X rhs); } X func() { return X(new ubyte[5]); } void func2(){ ubyte[15] buff; X x1 = X(buff[0 .. 5]); X x2 = X(buff[5 .. 10]); const X x3 = X(buff[10 .. $]); x1 = x2; //should use ref, opAssign required to keep addresses separate assert(x1.buff !is x2.buff); //must pass, else value semantics I'm using breaks x1 = func(); //default copy can work, but fails due to opAssign(ref X) existing. Works with opAssign(X) x1 = x3; //should fail and needs a (const X) or (ref const X). //but if you change to (ref const X), x1 = x2; //then opAssign(X) runs, making arrays x1 & x2 point to the same place; not what i want. } In my thinking i make (ref const X) then mutable versions should work too; but somehow it's deciding to use (X) instead of (ref const X). I'm promising I won't change the data, not requiring the data can't be changed.
May 04 2012
On Saturday, May 05, 2012 05:15:00 Era Scarecrow wrote:On Saturday, 5 May 2012 at 02:21:06 UTC, Jonathan M Davis wrote:If you've declared an opAssign, I'd be very surprised if _any_ assignme= nt=20 worked which didn't work with the opAssign that you declared. Once you'= ve=20 declared an opAssign, you've taken over the assignment operator, and yo= u need=20 to define it for all of the types that you want it to work with.As I understand it, you don't need to do _anything_ special to avoid having a temporary copied when passed to your function. Because it's a temporary, it should be moved into the function parameter, not copied. No postblit or opAssign will be executed. It's only when it's _not_ a temporary that a copy will be made. And even in _that_ case, it should be a move if that function call is the last place that the variable is used.=20 That's what I originally thought too... But when I'm dealing with the temporary there's something broken. So if I only have only the ref. =20 Error: function X.opAssign (ref X rhs) is not callable using argument types (X) =20 so; struct X { ref X opAssign(ref X rhs); } =20 X func(); =20 struct Y { X x; this() { x =3D func(); } } =20 Unless there's a default it drops back to, it is only seeing the one assign function.According to http://dlang.org/function.html: --------- Func=C2=ADtions are over=C2=ADloaded based on how well the ar=C2=ADgu=C2= =ADments to a func=C2=ADtion=20 can match up with the pa=C2=ADra=C2=ADme=C2=ADters. The func=C2=ADtion = with the best match is se=C2=AD lected. The lev=C2=ADels of match=C2=ADing are:=20 1. no match 2. match with im=C2=ADplicit con=C2=ADver=C2=ADsions 3. match with con=C2=ADver=C2=ADsion to const 4. exact match --------- It picks opAssign(X) over opAssign(ref const X) with an argument of typ= e X,=20 )=20 - Jonathan M DavisSo, I believe that you're trying to avoid copies that will never happen anyway. They would if you were dealing with C++ - particularly C++98 - but not in D (C++11 fixes the problem via move constructors).=20 I'm not trying to avoid copying (Blocks are small so it's likely a tiny cost); I'm trying to keep arrays separate. Let's add to my example; I Hope I got it right based on the behavior I'm seeing. =20 struct X { ubyte[] buffer; this(ubyte[] b) { buffer =3D b; } ref X opAssign(ref X rhs); } =20 X func() { return X(new ubyte[5]); } =20 void func2(){ ubyte[15] buff; X x1 =3D X(buff[0 .. 5]); X x2 =3D X(buff[5 .. 10]); const X x3 =3D X(buff[10 .. $]); =20 x1 =3D x2; //should use ref, opAssign required to keep addresses separate assert(x1.buff !is x2.buff); //must pass, else value semantics I'm using breaks =20 x1 =3D func(); //default copy can work, but fails due to opAssign(ref X) existing. Works with opAssign(X) =20 x1 =3D x3; //should fail and needs a (const X) or (ref const X). =20 //but if you change to (ref const X), x1 =3D x2; //then opAssign(X) runs, making arrays x1 & x2 point to the same place; not what i want. } =20 In my thinking i make (ref const X) then mutable versions should work too; but somehow it's deciding to use (X) instead of (ref const X). I'm promising I won't change the data, not requiring the data can't be changed.
May 04 2012
On Saturday, 5 May 2012 at 03:32:06 UTC, Jonathan M Davis wrote:If you've declared an opAssign, I'd be very surprised if _any_ assignment worked which didn't work with the opAssign that you declared. Once you've declared an opAssign, you've taken over the assignment operator, and you need to define it for all of the types that you want it to work with.So define all four... gotcha...According to http://dlang.org/function.html: --------- Functions are overloaded based on how well the arguments to a function can match up with the parameters. The function with the best match is selected. The levels of matching are: 1. no match 2. match with implicit conversions 3. match with conversion to const 4. exact match --------- It picks opAssign(X) over opAssign(ref const X) with an whereas opAssign(ref const X)requires a conversion to constI guess there's one question left. Where does the struct live? If it closes at ending of the scope I believed that meant the stack, but then this would be illegal: ref X func() { return X(new ubyte[5]); //reference to local variable! } If it lives on the heap too rather than the stack, that'd good to know. I don't recall it specifying in TDPL, but it would be easy enough to assume it does (Coming from C).
May 04 2012
On Saturday, 5 May 2012 at 03:32:06 UTC, Jonathan M Davis wrote:Hmm maybe it should have a preference for Lvalue vs Rvalue... So... Walter or Andrei? 1. no match 2. match with implicit conversions (Lvalue required) 3. match with conversion to const (Lvalue required) 4. match with implicit conversions 5. match with conversion to const 6. exact match--------- Functions are overloaded based on how well the arguments to a function can match up with the parameters. The function with the best match is selected. The levels of matching are: 1. no match 2. match with implicit conversions 3. match with conversion to const 4. exact match ---------
May 04 2012
On Saturday, May 05, 2012 05:50:26 Era Scarecrow wrote:tch isOn Saturday, 5 May 2012 at 03:32:06 UTC, Jonathan M Davis wrote:--------- Func=C2=ADtions are over=C2=ADloaded based on how well the ar=C2=ADgu=C2=ADments to a func=C2=ADtion can match up with the pa=C2=ADra=C2=ADme=C2=ADters. The func=C2=ADtion with the best ma=ed)=20 Hmm maybe it should have a preference for Lvalue vs Rvalue... So... Walter or Andrei? =20 1. no match 2. match with im=C2=ADplicit con=C2=ADver=C2=ADsions (Lvalue requir=se=C2=ADlected. The lev=C2=ADels of match=C2=ADing are: =20 1. no match 2. match with im=C2=ADplicit con=C2=ADver=C2=ADsions 3. match with con=C2=ADver=C2=ADsion to const 4. exact match ---------3. match with con=C2=ADver=C2=ADsion to const (Lvalue required) 4. match with im=C2=ADplicit con=C2=ADver=C2=ADsions 5. match with con=C2=ADver=C2=ADsion to const 6. exact matchThis will likely be _very_ relevant to the proposed changes which make = ref and=20 const ref work with rvalues (the details on that are still being sorted= out, I=20 believe). However, I don't believe that either Walter or Andrei pays at= tention=20 to D.Learn, so if you want to bring it up for discussion, post about it= in the=20 main newsgroup (not to mention, your post is buried enough in this thre= ad that=20 many who _do_ pay attention to D.Learn wouldn't see it). - Jonathan M Davis
May 04 2012
On Saturday, 5 May 2012 at 04:15:21 UTC, Jonathan M Davis wrote:On Saturday, May 05, 2012 05:50:26 Era Scarecrow wrote:Your probably right.. Thanks, I'll repost this portion over there, I think I saw a topic already present that was this (or closely related) to this.Hmm maybe it should have a preference for Lvalue vs Rvalue... So... Walter or Andrei? 1. no match 2. match with implicit conversions (Lvalue required) 3. match with conversion to const (Lvalue required) 4. match with implicit conversions 5. match with conversion to const 6. exact matchThis will likely be _very_ relevant to the proposed changes which make ref and const ref work with rvalues (the details on that are still being sorted out, I believe). However, I don't believe that either Walter or Andrei pays attention to D.Learn, so if you want to bring it up for discussion, post about it in the main newsgroup (not to mention, your post is buried enough in this thread that many who _do_ pay attention to D.Learn wouldn't see it).
May 04 2012
On Saturday, 5 May 2012 at 04:15:21 UTC, Jonathan M Davis wrote:This will likely be _very_ relevant to the proposed changes which make ref and const ref work with rvalues (the details on that are still being sorted out, I believe). However, I don't believe that either Walter or Andrei pays attention to D.Learn, so if you want to bring it up for discussion, post about it in the main newsgroup (not to mention, your post is buried enough in this thread that many who _do_ pay attention to D.Learn wouldn't see it).TDPL pg. 145 1) If there's one exact match, take that 2) Select a set of candidates that would accept the call if no other overloads are present. Here is where type deductions deduces types and if clauses are evaluated. 3) If the set has size zero, issue "no match" error. 4) If all functions are not in the same module, issue "attempt at cross-module overloading" error. 5) From that set eliminate all functions that are less specialized than any others in the set; that is, keep only the most specialized functions. 6) If the remaining set has size greater than one, issue "ambiguous call" error 7) The sole element of the set is the winner. void transmogrify(uint){} void transmogrify(long){} ... the first is more specialized so it is entitled to win. -- I get the feeling the 'ref' in our current discussion isn't being considered as how specialized it is (step 5). Maybe, but it's something to comment on. We'll see what Walter/Andrei have to say. my proposed Lvalue required steps are likely a better help than the rest of this though.
May 04 2012
On Saturday, May 05, 2012 05:43:43 Era Scarecrow wrote:On Saturday, 5 May 2012 at 03:32:06 UTC, Jonathan M Davis wrote:You need to define enough that you can pass any X to one of them. Gener= ally,=20 you probably just need opAssign(const X) and opAssign(const ref X), but= since=20 you're trying to have more particular semantics about whether resources= get=20 transferred or not, you may need all four.If you've declared an opAssign, I'd be very surprised if _any_ assignment worked which didn't work with the opAssign that you declared. Once you've declared an opAssign, you've taken over the assignment operator, and you need to define it for all of the types that you want it to work with.=20 So define all four... gotcha...ch isAccording to http://dlang.org/function.html: =20 --------- Func=C2=ADtions are over=C2=ADloaded based on how well the ar=C2=ADgu=C2=ADments to a func=C2=ADtion can match up with the pa=C2=ADra=C2=ADme=C2=ADters. The func=C2=ADtion with the best mat=That code _should_ be illegal. It's as bad as X* func() { X x; return &x; } I think that there's an enhancement request about making it an error li= ke my=20 example is, but I can't find it at the moment. Temporaries definitely g= o on the=20 stack. - Jonathan M Davisse=C2=ADlected. The lev=C2=ADels of match=C2=ADing are: =20 1. no match 2. match with im=C2=ADplicit con=C2=ADver=C2=ADsions 3. match with con=C2=ADver=C2=ADsion to const 4. exact match --------- =20 It picks opAssign(X) over opAssign(ref const X) with an whereas opAssign(ref const X)requires a conversion to const=20 I guess there's one question left. Where does the struct live? If it closes at ending of the scope I believed that meant the stack, but then this would be illegal: =20 ref X func() { return X(new ubyte[5]); //reference to local variable! } =20 If it lives on the heap too rather than the stack, that'd good to know. I don't recall it specifying in TDPL, but it would be easy enough to assume it does (Coming from C).
May 04 2012