www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - rvalue references

reply "Namespace" <rswhite4 gmail.com> writes:
Thanks to DIP 25 I think it's time to review this again. I would 
implement it (if no one else wants to do it), but there are still 
some unanswered questions:

1. Is 'auto ref' still the chosen syntax (I guess so)?
2. Should auto ref for templates act like auto ref for 
non-templates (creates a temporary and pass it by ref) or should 
the current behaviour stay (duplicate the function 2^N times)?
3. What's with return ref, should auto ref for non-templates 
include return ref (like auto ref for templates)?
4. What's with this constellation:

struct S { }

void ene(S) { }
void mene(ref S) { }
void muh(auto ref S) { }

should 'mene' (ref) interfere with 'muh' (auto ref)?
Jun 02 2015
next sibling parent "anonymous" <a b.cd> writes:
On Tuesday, 2 June 2015 at 16:02:56 UTC, Namespace wrote:
 Thanks to DIP 25 I think it's time to review this again. I 
 would implement it (if no one else wants to do it), but there 
 are still some unanswered questions:

 1. Is 'auto ref' still the chosen syntax (I guess so)?
 2. Should auto ref for templates act like auto ref for 
 non-templates (creates a temporary and pass it by ref) or 
 should the current behaviour stay (duplicate the function 2^N 
 times)?
 3. What's with return ref, should auto ref for non-templates 
 include return ref (like auto ref for templates)?
 4. What's with this constellation:

 struct S { }

 void ene(S) { }
 void mene(ref S) { }
 void muh(auto ref S) { }

 should 'mene' (ref) interfere with 'muh' (auto ref)?
Is there a final decision about rvalue references? Background: Is it still worth finishing and submitting a PR for https://issues.dlang.org/show_bug.cgi?id=11529 ? I did some experiments on how to fix this and then moved to other stuff. Now I have time for a second try, but fixing this if rvalue reference will be allowed in future is waste of time. Sorry for hijacking this thread...
Jun 02 2015
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, 2 June 2015 at 16:02:56 UTC, Namespace wrote:
 Thanks to DIP 25 I think it's time to review this again. I 
 would implement it (if no one else wants to do it), but there 
 are still some unanswered questions:

 1. Is 'auto ref' still the chosen syntax (I guess so)?
 2. Should auto ref for templates act like auto ref for 
 non-templates (creates a temporary and pass it by ref) or 
 should the current behaviour stay (duplicate the function 2^N 
 times)?
 3. What's with return ref, should auto ref for non-templates 
 include return ref (like auto ref for templates)?
 4. What's with this constellation:

 struct S { }

 void ene(S) { }
 void mene(ref S) { }
 void muh(auto ref S) { }

 should 'mene' (ref) interfere with 'muh' (auto ref)?
auto ref with templated functions needs to retain its current behavior. Changing it would not only break existing code, but it would lose what we have in terms of perfect forwarding (IIRC, it's not quite perfect forwarding, but it's close, and we'd be much farther from it without auto ref). If we want to have non-templated functions which can accept both rvalues and lvalues without copying the lvalues, then we need have a way to mark those parameters so that they're ref and then have an invisible, temporary variable inserted to hold a copy of an rvalue so that it can be passed by ref and accepted by the function as well instead of just accepting lvalues. If we want that to work with both non-templated and templated functions, then we need a new syntax. If we're willing to have them work with just non-templated functions, then we could reuse auto ref for that (and _maybe_ we could have the compiler optimize auto ref on templates to mean the same thing when it can determine that it's safe to do so and thus avoid extra template instantiations, but I question that that will happen). But then we only get it for non-templated functions, and auto ref means somethings slightly different for templated and non-templated functions, which sucks, but I'm not sure that it's ultimately all that big a deal. I _definitely_ think that it would be a huge mistake for ref in general to accept rvalues. If we did that, then suddenly, ref would be used everywhere, and you couldn't tell when someone wanted to actually set the ref argument to something or whether they were just trying to avoid extraneous copies of lvalues. I'd much rather have no way to have a parameter accept both rvalues and lvalues without copying the lvalues with non-templated functions than have ref accept rvalues. So, basically, I think that we have three options: 1. Do nothing. If you want a function parameter to accept both lvalues and rvalues efficently, then either duplicate it with various overloads to achieve that or templatize it and use auto ref so that the compiler will do that for you. 2. Extend auto ref so that it works with non-templated functions by inserting a temporary variable for rvalues so that they can be passed to the function by ref. Templated functions stay as they are. 3. Add a new attribute - e.g. rvalue ref - which inserts a temporary variable for rvalues so that they can be passed by ref, and it works with both templated and non-templated functions. Right now, we seem to be doing #1, and we have never officially decided whether that's permanent. Andrei in particular has resisted adding a new attribute, and to some extent, I agree that that's undesirable, but it _would_ allow us to solve this problem for both templated and non-templated functions, which we can't really do otherwise. So, I don't know how reasonable or feasible #3 is at this point. #2 probably wouldn't be that hard to get in, but then it only works with non-templated functions, and it complicates the meaning of auto ref in an already complicated language. Honestly, at this point, I don't know how much this issue really matters. It's annoying that we don't have rvalue references, but in general, we're living without them just fine, and we're heading toward templatizing almost everything for ranges anyway, in which case, the current version of auto ref will work just fine with most code (though that extraneous template bloat _is_ ugly). So, while I'd like to have rvalue references, I also think that we can get by just fine without them. If we _were_ going to add rvalue references, at this point, I'd probably lean towards a new attribute, because it's cleaner and more flexible that way, but it _does_ mean adding a new attribute, and I don't know if that's worth it. - Jonathan M Davis
Jun 02 2015
next sibling parent reply "Namespace" <rswhite4 gmail.com> writes:
 auto ref with templated functions needs to retain its current 
 behavior. Changing it would not only break existing code, but 
 it would lose what we have in terms of perfect forwarding 
 (IIRC, it's not quite perfect forwarding, but it's close, and 
 we'd be much farther from it without auto ref).
Ok, I thought so too
 If we want to have non-templated functions which can accept 
 both rvalues and lvalues without copying the lvalues, then we 
 need have a way to mark those parameters so that they're ref 
 and then have an invisible, temporary variable inserted to hold 
 a copy of an rvalue so that it can be passed by ref and 
 accepted by the function as well instead of just accepting 
 lvalues.
That is what auto ref for non-templates would do (and what I planned to do): if the passed argument is not an lvalue, a temporary is constructed which is passed by ref.
 If we want that to work with both non-templated and templated 
 functions, then we need a new syntax. If we're willing to have 
 them work with just non-templated functions, then we could 
 reuse auto ref for that (and _maybe_ we could have the compiler 
 optimize auto ref on templates to mean the same thing when it 
 can determine that it's safe to do so and thus avoid extra 
 template instantiations, but I question that that will happen). 
 But then we only get it for non-templated functions, and auto 
 ref means somethings slightly different for templated and 
 non-templated functions, which sucks, but I'm not sure that 
 it's ultimately all that big a deal.
AFAIK Andrei wanted 'auto ref' as the syntax which accepts both, lvalues and rvalues. That's why I'm asking if the current behaviour for auto ref for templates should change, or not. If not, we have (as you said) two meanings of auto ref, what is not optimal, but not so bad either (IMO). But if I had the choice, I would change it for both, so that both create a temporary variable for rvalues.
 I _definitely_ think that it would be a huge mistake for ref in 
 general to accept rvalues. If we did that, then suddenly, ref 
 would be used everywhere, and you couldn't tell when someone 
 wanted to actually set the ref argument to something or whether 
 they were just trying to avoid extraneous copies of lvalues.
I agree with that 100%.
 I'd much rather have no way to have a parameter accept both 
 rvalues and lvalues without copying the lvalues with 
 non-templated functions than have ref accept rvalues.

 So, basically, I think that we have three options:

 1. Do nothing. If you want a function parameter to accept both 
 lvalues and rvalues efficently, then either duplicate it with 
 various overloads to achieve that or templatize it and use auto 
 ref so that the compiler will do that for you.
But that means we get (at worst) 2^N functions. And note that each function contains the whole body, not just a call to one of the previous creations. That is really huge. If it would be only a call to one of the previous creations like: ---- struct S { } void test()(auto ref S s) { } test(S()); S s = S(); test(s); ---- is expaned to ---- void test(ref S s) { } void test(S s) { test(s); // Note that } ---- it would be fine. But not optimal either, since these functions can contain bugs which are never explored if your coverage is not 100%, because template methods are only instantiated if they are called. (Hope you know what I mean, my english is not that pretty....)
 2. Extend auto ref so that it works with non-templated 
 functions by inserting a temporary variable for rvalues so that 
 they can be passed to the function by ref. Templated functions 
 stay as they are.
This is what I wanted to do.
 3. Add a new attribute - e.g.  rvalue ref - which inserts a 
 temporary variable for rvalues so that they can be passed by 
 ref, and it works with both templated and non-templated 
 functions.

 Right now, we seem to be doing #1, and we have never officially 
 decided whether that's permanent. Andrei in particular has 
 resisted adding a new attribute, and to some extent, I agree 
 that that's undesirable, but it _would_ allow us to solve this 
 problem for both templated and non-templated functions, which 
 we can't really do otherwise. So, I don't know how reasonable 
 or feasible #3 is at this point. #2 probably wouldn't be that 
 hard to get in, but then it only works with non-templated 
 functions, and it complicates the meaning of auto ref in an 
 already complicated language.

 Honestly, at this point, I don't know how much this issue 
 really matters. It's annoying that we don't have rvalue 
 references, but in general, we're living without them just 
 fine, and we're heading toward templatizing almost everything 
 for ranges anyway, in which case, the current version of auto 
 ref will work just fine with most code (though that extraneous 
 template bloat _is_ ugly). So, while I'd like to have rvalue 
 references, I also think that we can get by just fine without 
 them.

 If we _were_ going to add rvalue references, at this point, I'd 
 probably lean towards a new attribute, because it's cleaner and 
 more flexible that way, but it _does_ mean adding a new 
 attribute, and I don't know if that's worth it.

 - Jonathan M Davis
Jun 02 2015
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, 2 June 2015 at 18:05:20 UTC, Namespace wrote:
 AFAIK Andrei wanted 'auto ref' as the syntax which accepts 
 both, lvalues and rvalues. That's why I'm asking if the current 
 behaviour for auto ref for templates should change, or not. If 
 not, we have (as you said) two meanings of auto ref, what is 
 not optimal, but not so bad either (IMO).
 But if I had the choice, I would change it for both, so that 
 both create a temporary variable for rvalues.
Andrei originally wanted auto ref to apply to non-templated functions, but Walter misunderstood what he meant and created what we have now - which is actually incredibly useful, because it allows you to forward the attributes of an argument - in particular, it's ref-ness. So, we definitely do _not_ want to lose that.
 So, basically, I think that we have three options:

 1. Do nothing. If you want a function parameter to accept both 
 lvalues and rvalues efficently, then either duplicate it with 
 various overloads to achieve that or templatize it and use 
 auto ref so that the compiler will do that for you.
But that means we get (at worst) 2^N functions. And note that each function contains the whole body, not just a call to one of the previous creations.
Yes. auto ref with templated functions results in a lot of template bloat if you use it heavily, which is part of why using auto ref with non-templated functions at this point isn't a particularly ideal solution, not unless we could actually make it so that the compiler could optimize the extraneous instantiations and use a temporary value for the rvalues when the attribute forwarding isn't actually needed, but I wouldn't really expect us to get that. - Jonathan M Davis
Jun 02 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/2/15 11:19 AM, Jonathan M Davis wrote:
 On Tuesday, 2 June 2015 at 18:05:20 UTC, Namespace wrote:
 AFAIK Andrei wanted 'auto ref' as the syntax which accepts both,
 lvalues and rvalues. That's why I'm asking if the current behaviour
 for auto ref for templates should change, or not. If not, we have (as
 you said) two meanings of auto ref, what is not optimal, but not so
 bad either (IMO).
 But if I had the choice, I would change it for both, so that both
 create a temporary variable for rvalues.
Andrei originally wanted auto ref to apply to non-templated functions, but Walter misunderstood what he meant and created what we have now - which is actually incredibly useful, because it allows you to forward the attributes of an argument - in particular, it's ref-ness. So, we definitely do _not_ want to lose that.
Yah, auto ref for templates is great. We only need to add auto ref for non-templates with the semantics "like ref, except (a) accepts rvalues on the caller side, (b) does not allow escaping the ref from the function". Note that __traits(isRef, param) doesn't work in an auto ref param in a non-template function (attempt to use must be a compile-time error). That's about it. Andrei
Jun 02 2015
next sibling parent reply "Namespace" <rswhite4 gmail.com> writes:
On Tuesday, 2 June 2015 at 21:20:49 UTC, Andrei Alexandrescu 
wrote:
 Yah, auto ref for templates is great. We only need to add auto 
 ref for non-templates with the semantics "like ref, except (a) 
 accepts rvalues on the caller side, (b) does not allow escaping 
 the ref from the function".
That would work once DIP 25 is fully implemented and if auto ref for non-templates would not include return ref. Or am I missing something?
 Note that __traits(isRef, param) doesn't work in an auto ref 
 param in a non-template function (attempt to use must be a 
 compile-time error).

 That's about it.


 Andrei
Jun 02 2015
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 6/2/15 2:28 PM, Namespace wrote:
 On Tuesday, 2 June 2015 at 21:20:49 UTC, Andrei Alexandrescu wrote:
 Yah, auto ref for templates is great. We only need to add auto ref for
 non-templates with the semantics "like ref, except (a) accepts rvalues
 on the caller side, (b) does not allow escaping the ref from the
 function".
That would work once DIP 25 is fully implemented and if auto ref for non-templates would not include return ref. Or am I missing something?
Sounds about right. -- Andrei
Jun 02 2015
prev sibling parent reply "Namespace" <rswhite4 gmail.com> writes:
I start working on a Pull 
(https://github.com/D-Programming-Language/dmd/pull/4717), but it 
fails the first check. The reason seems to be this: 
https://github.com/D-Programming-Language/dmd/pull/4717/files#diff-ffafa03255a57832dd09031af6cb915dR5945
I guess that this error happens because I cannot distinguish 
between template and non template auto ref. Does anyone have an 
idea?
Jun 05 2015
next sibling parent "Namespace" <rswhite4 gmail.com> writes:
On Friday, 5 June 2015 at 21:31:22 UTC, Namespace wrote:
 I start working on a Pull 
 (https://github.com/D-Programming-Language/dmd/pull/4717), but 
 it fails the first check. The reason seems to be this: 
 https://github.com/D-Programming-Language/dmd/pull/4717/files#diff-ffafa03255a57832dd09031af6cb915dR5945
 I guess that this error happens because I cannot distinguish 
 between template and non template auto ref. Does anyone have an 
 idea?
Hmm, the only problematic code is std.algorithm.mutation.swap on line 1956 - 1959 which calls doesPointTo from std.exception which is nothrow pure and nogc, but shouldn't. Without it, everything works.
Jun 05 2015
prev sibling parent reply "Namespace" <rswhite4 gmail.com> writes:
Finally all green! Now we need a review.
Jun 06 2015
parent reply bitwise <bitwise.pvt gmail.com> writes:
On Sat, 06 Jun 2015 14:05:54 -0400, Namespace <rswhite4 gmail.com> wrote:

 Finally all green! Now we need a review.
You're my hero. Bit
Jun 07 2015
parent reply "Namespace" <rswhite4 gmail.com> writes:
On Sunday, 7 June 2015 at 18:40:42 UTC, bitwise wrote:
 On Sat, 06 Jun 2015 14:05:54 -0400, Namespace 
 <rswhite4 gmail.com> wrote:

 Finally all green! Now we need a review.
You're my hero. Bit
Sounds ironic. o.O
Jun 07 2015
parent reply bitwise <bitwise.pvt gmail.com> writes:
On Mon, 08 Jun 2015 02:44:46 -0400, Namespace <rswhite4 gmail.com> wrote:

 On Sunday, 7 June 2015 at 18:40:42 UTC, bitwise wrote:
 On Sat, 06 Jun 2015 14:05:54 -0400, Namespace <rswhite4 gmail.com>  
 wrote:

 Finally all green! Now we need a review.
You're my hero. Bit
Sounds ironic. o.O
Ironic or Sarcastic? Neither. Bit
Jun 08 2015
parent reply bitwise <bitwise.pvt gmail.com> writes:
On Mon, 08 Jun 2015 11:29:56 -0400, bitwise <bitwise.pvt gmail.com> wrote:

 On Mon, 08 Jun 2015 02:44:46 -0400, Namespace <rswhite4 gmail.com> wrote:

 On Sunday, 7 June 2015 at 18:40:42 UTC, bitwise wrote:
 On Sat, 06 Jun 2015 14:05:54 -0400, Namespace <rswhite4 gmail.com>  
 wrote:

 Finally all green! Now we need a review.
You're my hero. Bit
Sounds ironic. o.O
Ironic or Sarcastic? Neither. Bit
One useful case for me: static Mat4 transform()(const auto ref Vec3 pos, const auto ref Vec3 scale, const auto ref Quat rot) { Mat4 m = Mat4(rot.matrix, 1); m.m00 *= scale.x; m.m01 *= scale.x; m.m02 *= scale.x; m.m10 *= scale.y; m.m11 *= scale.y; m.m12 *= scale.y; m.m20 *= scale.z; m.m21 *= scale.z; m.m22 *= scale.z; m.m30 = pos.x; m.m31 = pos.y; m.m32 = pos.z; return m; } Currently, my choices are template bloat, or pointless copying. Bit
Jun 08 2015
next sibling parent reply "Namespace" <rswhite4 gmail.com> writes:
 One useful case for me:

 static Mat4 transform()(const auto ref Vec3 pos, const auto ref 
 Vec3 scale, const auto ref Quat rot)
 {
     Mat4 m = Mat4(rot.matrix, 1);

     m.m00 *= scale.x;
     m.m01 *= scale.x;
     m.m02 *= scale.x;

     m.m10 *= scale.y;
     m.m11 *= scale.y;
     m.m12 *= scale.y;

     m.m20 *= scale.z;
     m.m21 *= scale.z;
     m.m22 *= scale.z;

     m.m30 = pos.x;
     m.m31 = pos.y;
     m.m32 = pos.z;

     return m;
 }

 Currently, my choices are template bloat, or pointless copying.

   Bit
Yes, the same goes for Dgame.
Jun 08 2015
parent reply bitwise <bitwise.pvt gmail.com> writes:
On Mon, 08 Jun 2015 16:17:33 -0400, Namespace <rswhite4 gmail.com> wrote:

 Yes, the same goes for Dgame.
closed-source projects can also accept rvalue-refs now ;) Bit
Jun 08 2015
next sibling parent reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 9 June 2015 at 08:58, bitwise via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On Mon, 08 Jun 2015 16:17:33 -0400, Namespace <rswhite4 gmail.com> wrote:

 Yes, the same goes for Dgame.
closed-source projects can also accept rvalue-refs now ;)
How?
Jun 08 2015
parent bitwise <bitwise.pvt gmail.com> writes:
On Mon, 08 Jun 2015 22:16:27 -0400, Manu via Digitalmars-d  
<digitalmars-d puremagic.com> wrote:

 On 9 June 2015 at 08:58, bitwise via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 On Mon, 08 Jun 2015 16:17:33 -0400, Namespace <rswhite4 gmail.com>  
 wrote:

 Yes, the same goes for Dgame.
closed-source projects can also accept rvalue-refs now ;)
How?
I mean that if this is implemented, your code doesn't have to be a template to use 'auto ref', so the code won't show up in a .di file. Bit
Jun 08 2015
prev sibling parent "Namespace" <rswhite4 gmail.com> writes:
On Monday, 8 June 2015 at 22:58:15 UTC, bitwise wrote:
 On Mon, 08 Jun 2015 16:17:33 -0400, Namespace 
 <rswhite4 gmail.com> wrote:

 Yes, the same goes for Dgame.
closed-source projects can also accept rvalue-refs now ;) Bit
Dgame is not closed-source. ;)
Jun 09 2015
prev sibling parent reply "kink" <noone nowhere.com> writes:
On Monday, 8 June 2015 at 20:16:13 UTC, bitwise wrote:
 static Mat4 transform()(const auto ref Vec3 pos, const auto ref 
 Vec3 scale, const auto ref Quat rot);
Horrific. static Mat4 transform(in Vec3 pos, in Vec3 scale, in Quat rot); would be so much better...
Jun 09 2015
parent bitwise <bitwise.pvt gmail.com> writes:
On Tue, 09 Jun 2015 08:26:46 -0400, kink <noone nowhere.com> wrote:

 On Monday, 8 June 2015 at 20:16:13 UTC, bitwise wrote:
 static Mat4 transform()(const auto ref Vec3 pos, const auto ref Vec3  
 scale, const auto ref Quat rot);
Horrific. static Mat4 transform(in Vec3 pos, in Vec3 scale, in Quat rot); would be so much better...
How do you figure? Bit
Jun 09 2015
prev sibling next sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 3 June 2015 at 07:21, Andrei Alexandrescu via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 On 6/2/15 11:19 AM, Jonathan M Davis wrote:
 On Tuesday, 2 June 2015 at 18:05:20 UTC, Namespace wrote:
 AFAIK Andrei wanted 'auto ref' as the syntax which accepts both,
 lvalues and rvalues. That's why I'm asking if the current behaviour
 for auto ref for templates should change, or not. If not, we have (as
 you said) two meanings of auto ref, what is not optimal, but not so
 bad either (IMO).
 But if I had the choice, I would change it for both, so that both
 create a temporary variable for rvalues.
Andrei originally wanted auto ref to apply to non-templated functions, but Walter misunderstood what he meant and created what we have now - which is actually incredibly useful, because it allows you to forward the attributes of an argument - in particular, it's ref-ness. So, we definitely do _not_ want to lose that.
Yah, auto ref for templates is great. We only need to add auto ref for non-templates with the semantics "like ref, except (a) accepts rvalues on the caller side, (b) does not allow escaping the ref from the function". Note that __traits(isRef, param) doesn't work in an auto ref param in a non-template function (attempt to use must be a compile-time error). That's about it.
You're killing me! I thought 'scope ref' was more-or-less agreed? auto ref makes no sense.
Jun 02 2015
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 06/02/2015 11:21 PM, Andrei Alexandrescu wrote:

 Yah, auto ref for templates is great. We only need to add auto ref for
 non-templates with the semantics "like ref, except (a) accepts rvalues
 on the caller side, (b) does not allow escaping the ref from the function".
What if one wants those semantics for some template function parameters? It seems arbitrary to introduce this feature for all functions except templated ones.
Jun 03 2015
prev sibling parent "Namespace" <rswhite4 gmail.com> writes:
 3. Add a new attribute - e.g.  rvalue ref - which inserts a 
 temporary variable for rvalues so that they can be passed by 
 ref, and it works with both templated and non-templated 
 functions.
We could also somehow use 'return ref' for that purpose, or we could get rid of the pointless 'const scope' alias 'in' and use 'in ref' as a new attribute. But somehow I would prefer 'auto ref', it's a more descriptive term.
Jun 02 2015
prev sibling next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Tuesday, 2 June 2015 at 16:02:56 UTC, Namespace wrote:
 Thanks to DIP 25 I think it's time to review this again. I 
 would implement it (if no one else wants to do it), but there 
 are still some unanswered questions:

 1. Is 'auto ref' still the chosen syntax (I guess so)?
Why not `scope ref` (or `in ref` == `const scope ref`)?
 2. Should auto ref for templates act like auto ref for 
 non-templates (creates a temporary and pass it by ref) or 
 should the current behaviour stay (duplicate the function 2^N 
 times)?
With `scope ref`, obviously it should stay as-is.
 3. What's with return ref, should auto ref for non-templates 
 include return ref (like auto ref for templates)?
Like above, no.
 4. What's with this constellation:

 struct S { }

 void ene(S) { }
 void mene(ref S) { }
 void muh(auto ref S) { }

 should 'mene' (ref) interfere with 'muh' (auto ref)?
If overloading on `scope` is allowed, then yes, else no.
Jun 02 2015
next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, 2 June 2015 at 17:22:07 UTC, Marc Schütz wrote:
 On Tuesday, 2 June 2015 at 16:02:56 UTC, Namespace wrote:
 Thanks to DIP 25 I think it's time to review this again. I 
 would implement it (if no one else wants to do it), but there 
 are still some unanswered questions:

 1. Is 'auto ref' still the chosen syntax (I guess so)?
Why not `scope ref` (or `in ref` == `const scope ref`)?
Because scope isn't even properly defined. Certainly, if we were to go that route, we'd have to finish working out what the heck scope is really supposed to do and mean. And we haven't done that yet. As it stands, everyone has their own ideas about what it means and/or should mean, but all the spec says for scope parameters is that "references in the parameter cannot be escaped (e.g. assigned to a global variable)", and right now, the only thing that scope affects is delegate parameters, and I'm not sure that even that works correctly yet or is properly ironed out. So, while maybe using scope ref for this would make sense, we have a _lot_ to figure out before we can really consider that.
 4. What's with this constellation:

 struct S { }

 void ene(S) { }
 void mene(ref S) { }
 void muh(auto ref S) { }

 should 'mene' (ref) interfere with 'muh' (auto ref)?
If overloading on `scope` is allowed, then yes, else no.
It's not currently allowed. But regardless, if the whole point of saying scope ref (or whatever attribute we picked) was to indicate that we wanted the parameter to accept both lvalues and rvalues, then it makes no sense whatsoever to overload the parameter on ref, and it would be ref underneath the hood anyway, because that's how it would have to be implemented. - Jonathan M Davis
Jun 02 2015
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Tuesday, 2 June 2015 at 17:31:56 UTC, Jonathan M Davis wrote:
 On Tuesday, 2 June 2015 at 17:22:07 UTC, Marc Schütz wrote:
 On Tuesday, 2 June 2015 at 16:02:56 UTC, Namespace wrote:
 Thanks to DIP 25 I think it's time to review this again. I 
 would implement it (if no one else wants to do it), but there 
 are still some unanswered questions:

 1. Is 'auto ref' still the chosen syntax (I guess so)?
Why not `scope ref` (or `in ref` == `const scope ref`)?
Because scope isn't even properly defined. Certainly, if we were to go that route, we'd have to finish working out what the heck scope is really supposed to do and mean. And we haven't done that yet. As it stands, everyone has their own ideas about what it means and/or should mean, but all the spec says for scope parameters is that "references in the parameter cannot be escaped (e.g. assigned to a global variable)", and right now, the only thing that scope affects is delegate parameters, and I'm not sure that even that works correctly yet or is properly ironed out. So, while maybe using scope ref for this would make sense, we have a _lot_ to figure out before we can really consider that.
That's what makes it an ideal choice in my opinion :-) Whatever semantics we give it is by definition not a breaking change... Besides, I do have a pretty good idea what `scope` should mean, including most of the finer details. I summarized it here: http://wiki.dlang.org/User:Schuetzm/scope3 The lack of progress on this topic is not because no solution is known.
 4. What's with this constellation:

 struct S { }

 void ene(S) { }
 void mene(ref S) { }
 void muh(auto ref S) { }

 should 'mene' (ref) interfere with 'muh' (auto ref)?
If overloading on `scope` is allowed, then yes, else no.
It's not currently allowed. But regardless, if the whole point of saying scope ref (or whatever attribute we picked) was to indicate that we wanted the parameter to accept both lvalues and rvalues, then it makes no sense whatsoever to overload the parameter on ref, and it would be ref underneath the hood anyway, because that's how it would have to be implemented.
There are use-cases for overloading on scope with value types, but there are other ways to achieve the same goals (see here: http://wiki.dlang.org/User:Schuetzm/scope3#scope_for_value_types_.26_overloading).
Jun 03 2015
prev sibling parent reply "Namespace" <rswhite4 gmail.com> writes:
On Tuesday, 2 June 2015 at 17:22:07 UTC, Marc Schütz wrote:
 On Tuesday, 2 June 2015 at 16:02:56 UTC, Namespace wrote:
 Thanks to DIP 25 I think it's time to review this again. I 
 would implement it (if no one else wants to do it), but there 
 are still some unanswered questions:

 1. Is 'auto ref' still the chosen syntax (I guess so)?
Why not `scope ref` (or `in ref` == `const scope ref`)?
See DIP 36
 2. Should auto ref for templates act like auto ref for 
 non-templates (creates a temporary and pass it by ref) or 
 should the current behaviour stay (duplicate the function 2^N 
 times)?
With `scope ref`, obviously it should stay as-is.
 3. What's with return ref, should auto ref for non-templates 
 include return ref (like auto ref for templates)?
Like above, no.
 4. What's with this constellation:

 struct S { }

 void ene(S) { }
 void mene(ref S) { }
 void muh(auto ref S) { }

 should 'mene' (ref) interfere with 'muh' (auto ref)?
If overloading on `scope` is allowed, then yes, else no.
Jun 02 2015
next sibling parent reply bitwise <bitwise.pvt gmail.com> writes:
On Tue, 02 Jun 2015 14:06:31 -0400, Namespace <rswhite4 gmail.com> wrote=
:

 On Tuesday, 2 June 2015 at 17:22:07 UTC, Marc Sch=FCtz wrote:
 On Tuesday, 2 June 2015 at 16:02:56 UTC, Namespace wrote:
 Thanks to DIP 25 I think it's time to review this again. I would  =
 implement it (if no one else wants to do it), but there are still so=
me =
 unanswered questions:

 1. Is 'auto ref' still the chosen syntax (I guess so)?
Why not `scope ref` (or `in ref` =3D=3D `const scope ref`)?
See DIP 36
I'm feeling like a bit of a troll here, but I can't help myself. 'in' is currently useless because scope is not defined properly, and con= st = is too restrictive. Also, because of DIP25, it's now even more useless. = It = seems a pretty sure bet that it will either continue to be completely = useless or be changed at some point anyways, so why not now? If it's onl= y = been around since 2.060, how bad could the code breakage really be? = Replace All a few times and you're done. A compiler warning could be = issued for the next few versions to notify users that the meaning of 'in= ' = has changed, if needed. So why not re-brand this awesomely concise and convenient keyword to be = = the "non-template auto ref"? Bit
Jun 02 2015
next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, 3 June 2015 at 01:57:21 UTC, bitwise wrote:
 On Tue, 02 Jun 2015 14:06:31 -0400, Namespace 
 <rswhite4 gmail.com> wrote:

 On Tuesday, 2 June 2015 at 17:22:07 UTC, Marc Schütz wrote:
 On Tuesday, 2 June 2015 at 16:02:56 UTC, Namespace wrote:
 Thanks to DIP 25 I think it's time to review this again. I 
 would implement it (if no one else wants to do it), but 
 there are still some unanswered questions:

 1. Is 'auto ref' still the chosen syntax (I guess so)?
Why not `scope ref` (or `in ref` == `const scope ref`)?
See DIP 36
I'm feeling like a bit of a troll here, but I can't help myself. 'in' is currently useless because scope is not defined properly, and const is too restrictive. Also, because of DIP25, it's now even more useless. It seems a pretty sure bet that it will either continue to be completely useless or be changed at some point anyways, so why not now? If it's only been around since 2.060, how bad could the code breakage really be? Replace All a few times and you're done. A compiler warning could be issued for the next few versions to notify users that the meaning of 'in' has changed, if needed. So why not re-brand this awesomely concise and convenient keyword to be the "non-template auto ref"?
Where on earth did you get the idea that in was introduced in 2.060? in existed in D1. Its meaning was slightly different then, but it was kept in D2 and its meaning changed in a manner that was intended to be reasonably compatible with D1 code. And folks _love_ using in, because they view it as the opposite of out. Almost always, it's really just const, since scope really only applies to delegates at this point, but in is used _heavily_ by many folks in the D community. I keep telling folks not to use in, because scope isn't well-defined yet, so who knows what's going to happen when we _do_ try and define it properly, but folks keep using it anyway. We can't just change the meaning and expect it not to break code. That's part of what's going to be so ugly about finishing scope. And there are folks who use in fully understanding the risks under the assumption that scope will be defined in a way that does what they want. So, many folks are relying on in being equivalent to const scope, and changing it to mean something else is just plain a bad idea. - Jonathan M Davis
Jun 02 2015
parent reply bitwise <bitwise.pvt gmail.com> writes:
On Tue, 02 Jun 2015 22:28:48 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:
 Where on earth did you get the idea that in was introduced in 2.060?
DIP36: "in ref has been allowed from 2.060 : http://d.puremagic.com/issues/show_bug.cgi?id=8105" Reading it more carefully this time, I understand what it's saying now =(
 And folks _love_ using in, because they view it as the opposite of out.
To be symmetrical with 'out' shouldn't 'in' == 'const scope ref'?
 Almost always, it's really just const, since scope really only applies
 to delegates at this point, but in is used _heavily_ by many folks in
 the D community.
I still think that it could be put to better use than an alias for const.
 I keep telling folks not to use in, because scope isn't well-defined  
 yet, so who knows what's going to happen when we _do_ try and define it  
 properly, but folks keep using it anyway.
Exactly my point, because it's awesomely convenient, which is why it should have a more useful meaning :)
 We can't just change the meaning and expect it not to break code. That's
 part of what's going to be so ugly about finishing scope. And there are
 folks who use in fully understanding the risks under the assumption that
 scope will be defined in a way that does what they want. So, many folks
 are relying on in being equivalent to const scope, and changing it to
 mean something else is just plain a bad idea.
I have seen a lot of posts on these forums about people being tired of breaking changes in D, and I understand that, but I believe 'in' should be an exception. It's kind of a 'beta' feature, and people should expect that it's subject to change, especially considering that googling 'dlang in ref' yields your warning as the second result :) "1. Don't use in." Anyways, moving forward with the assumption that the meaning of 'in' will not change, I still don't understand. Why couldn't 'in ref' be allowed to accept rvalues in addition to 'auto ref'? Bit
Jun 02 2015
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, 3 June 2015 at 03:20:48 UTC, bitwise wrote:
 Anyways, moving forward with the assumption that the meaning of 
 'in' will
 not change, I still don't understand. Why couldn't 'in ref' be 
 allowed to
 accept rvalues in addition to 'auto ref'?
For the same reasons that we can't have const ref accept rvalues, especially since in ref basically _is_ const ref in most cases right now. - Jonathan M Davis
Jun 02 2015
next sibling parent reply bitwise <bitwise.pvt gmail.com> writes:
On Tue, 02 Jun 2015 23:23:00 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On Wednesday, 3 June 2015 at 03:20:48 UTC, bitwise wrote:
 Anyways, moving forward with the assumption that the meaning of 'in'  
 will
 not change, I still don't understand. Why couldn't 'in ref' be allowed  
 to
 accept rvalues in addition to 'auto ref'?
For the same reasons that we can't have const ref accept rvalues, especially since in ref basically _is_ const ref in most cases right now. - Jonathan M Davis
Why can't const ref accept rvalues? const being too restrictive doesn't seem like a real reason, because although its undesirable for some cases, doesn't mean it can't be useful in a _lot_ of other cases. Also, with DIP25, isn't 'const ref' the same thing that 'const scope ref' was supposed to be anyways? I can't remember right now what the reasoning was for 'const ref' not to take rvalues in the first place. I think it was that you could escape the reference, but this isn't true anymore with DIP25 right? Bit
Jun 02 2015
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, 3 June 2015 at 03:43:09 UTC, bitwise wrote:
 I can't remember right now what the reasoning was for 'const 
 ref' not to take
 rvalues in the first place. I think it was that you could 
 escape the reference,
 but this isn't true anymore with DIP25 right?
The one to ask is Andrei. I can never remember all of the details, because it has to do with the details of how it causes problems in C++. IIRC, the problem stems from the fact that you can no longer tell whether the parameter represents an lvalue or a temporary. I don't know how big a deal it really is, but Andrei is emphatic about it. But regardless, because of how restrictive const is in D, requiring const to have a parameter accept both lvalues and rvalues is just too restrictive anyway. A lot of the same developers who are insistent on having rvalue references for efficiency are exactly the sort of developers who will avoid const, because it's physical const and not logical const and thus prevents stuff like caching or lazy loading. - Jonathan M Davis
Jun 02 2015
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 06/03/2015 05:43 AM, bitwise wrote:

 Why can't const ref accept rvalues?

 const being too restrictive doesn't seem like a real reason, because
 although its undesirable for some cases, doesn't mean it can't be useful
 in a _lot_ of other cases.
Its a real reason unless you endorse patchwork language design. This is an obvious hole. There is absolutely no valid reason to solve only part of the issue in a non-orthogonal fashion.
Jun 03 2015
prev sibling parent reply bitwise <bitwise.pvt gmail.com> writes:
I forgot to mention, in terms of this statement I made:

 I can't remember right now what the reasoning was for 'const ref' not to  
 take
 rvalues in the first place. I think it was that you could escape the  
 reference,
 but this isn't true anymore with DIP25 right?
I think someone brought this up about a weeks ago, and this was Andrei's response:
 Knee-jerk response: if no "return" attribute on a function it should be  
 safeto bind rvalues to ref parameters. Of course that's impractical as a  
 default
 so explicit "auto ref" would be needed. -- Andrei
What's impractical? Bit
Jun 02 2015
parent reply "Namespace" <rswhite4 gmail.com> writes:
On Wednesday, 3 June 2015 at 03:57:38 UTC, bitwise wrote:
 I forgot to mention, in terms of this statement I made:

 I can't remember right now what the reasoning was for 'const 
 ref' not to take
 rvalues in the first place. I think it was that you could 
 escape the reference,
 but this isn't true anymore with DIP25 right?
I think someone brought this up about a weeks ago,
That was me.
 and this was Andrei's response:

 Knee-jerk response: if no "return" attribute on a function it 
 should be safeto bind rvalues to ref parameters. Of course 
 that's impractical as a default
 so explicit "auto ref" would be needed. -- Andrei
What's impractical?
It's dangerous. If rvalues could be passed to normal ref parameter we would have a problem. Consider this: ---- struct Sprite { private Texture* _tex; this(ref Texture tex) { _tex = &tex; } } ---- This works because we accept a valid lvalue and store a pointer to it. If the CTor would accept also rvalues, then the pointer would be invalid, since the texture was just a temporary variable. Not the best example, but I think you understand what I mean.
Jun 03 2015
next sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 3 June 2015 at 07:09:09 UTC, Namespace wrote:
 On Wednesday, 3 June 2015 at 03:57:38 UTC, bitwise wrote:
 I forgot to mention, in terms of this statement I made:

 I can't remember right now what the reasoning was for 'const 
 ref' not to take
 rvalues in the first place. I think it was that you could 
 escape the reference,
 but this isn't true anymore with DIP25 right?
I think someone brought this up about a weeks ago,
That was me.
 and this was Andrei's response:

 Knee-jerk response: if no "return" attribute on a function it 
 should be safeto bind rvalues to ref parameters. Of course 
 that's impractical as a default
 so explicit "auto ref" would be needed. -- Andrei
What's impractical?
It's dangerous. If rvalues could be passed to normal ref parameter we would have a problem. Consider this: ---- struct Sprite { private Texture* _tex; this(ref Texture tex) { _tex = &tex; } } ---- This works because we accept a valid lvalue and store a pointer to it. If the CTor would accept also rvalues, then the pointer would be invalid, since the texture was just a temporary variable. Not the best example, but I think you understand what I mean.
This code needs to be disallowed under DIP25 (or whatever the final DIP will be), of course.
Jun 03 2015
parent reply "Namespace" <rswhite4 gmail.com> writes:
 This code needs to be disallowed under DIP25 (or whatever the 
 final DIP will be), of course.
But should work with return ref instead.
Jun 03 2015
parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Wednesday, 3 June 2015 at 09:53:36 UTC, Namespace wrote:
 This code needs to be disallowed under DIP25 (or whatever the 
 final DIP will be), of course.
But should work with return ref instead.
It can even be allowed with an extension to DIP25: struct Sprite { private Texture* _tex; this(ref Texture tex return(this)) { _tex = &tex; } } `return(param)` (or e.g. `out(param)`) means that the reference can escape through `param`. The method can't accept an rvalue ref then, of course.
Jun 03 2015
prev sibling parent bitwise <bitwise.pvt gmail.com> writes:
On Wed, 03 Jun 2015 03:09:06 -0400, Namespace <rswhite4 gmail.com> wrote:

 On Wednesday, 3 June 2015 at 03:57:38 UTC, bitwise wrote:
 I forgot to mention, in terms of this statement I made:

 I can't remember right now what the reasoning was for 'const ref' not  
 to take
 rvalues in the first place. I think it was that you could escape the  
 reference,
 but this isn't true anymore with DIP25 right?
I think someone brought this up about a weeks ago,
That was me.
 and this was Andrei's response:

 Knee-jerk response: if no "return" attribute on a function it should  
 be safeto bind rvalues to ref parameters. Of course that's impractical  
 as a default
 so explicit "auto ref" would be needed. -- Andrei
What's impractical?
It's dangerous. If rvalues could be passed to normal ref parameter we would have a problem. Consider this: ---- struct Sprite { private Texture* _tex; this(ref Texture tex) { _tex = &tex; } } ---- This works because we accept a valid lvalue and store a pointer to it. If the CTor would accept also rvalues, then the pointer would be invalid, since the texture was just a temporary variable. Not the best example, but I think you understand what I mean.
Hmm.... Indeed. It seems I misunderstood DIP25. I didn't think that was allowed. It appears that even this is allowed: private Texture* _tex; struct Sprite { this(ref Texture tex) { _tex = &tex; } } Is DIP25 intended to eventually prevent these examples? Wouldn't it have made more sense for DIP25 prevent _all_ escaping, including pointers? or is that not possible? Then, instead of 'return ref' it could be 'escape ref' or something. Anyways, moot point I suppose. Bit
Jun 03 2015
prev sibling parent "kinke" <noone nowhere.com> writes:
On Wednesday, 3 June 2015 at 01:57:21 UTC, bitwise wrote:
 'in' is currently useless because scope is not defined 
 properly, and const is too restrictive. Also, because of DIP25, 
 it's now even more useless. It seems a pretty sure bet that it 
 will either continue to be completely useless or be changed at 
 some point anyways, so why not now?
 ...
 So why not re-brand this awesomely concise and convenient 
 keyword to be the "non-template auto ref"?
I see the point in some sort of `auto ref`/`scope ref` parameters binding to rvalues in cases where one's not interested in a function's side effect applied to a non-escapable rvalue argument. But what I need 99% of the time is some means to express my intention to pass an argument the most efficient way possible as the callee is only gonna read from it and won't let it escape. This is only relevant for non-primitive value types, i.e., structs. Like many others, I love the neat little `in` keyword, and would like for it to have exactly these semantics, for both templates and normal functions: * the callee has read-only access to the parameter, i.e., it is const; * since it's declared as normal function parameter (`in T arg`), it cannot escape (`scope` or however we wanna call this); * depending on type and hardware, value types are either passed by value (POD type whose size <= [2*]size_t.sizeof) or by reference (non-POD type and/or size > threshold); reference types (class instances) are always passed by ref * if a value type is passed by reference, an rvalue argument is allowed to safely bind to the const, non-escapable reference. This would be particularly useful for generic templates, e.g., containers, where primitive and small POD types T are ideally passed by value, and other Ts by reference.
Jun 06 2015
prev sibling parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Tuesday, 2 June 2015 at 18:06:32 UTC, Namespace wrote:
 On Tuesday, 2 June 2015 at 17:22:07 UTC, Marc Schütz wrote:
 On Tuesday, 2 June 2015 at 16:02:56 UTC, Namespace wrote:
 Thanks to DIP 25 I think it's time to review this again. I 
 would implement it (if no one else wants to do it), but there 
 are still some unanswered questions:

 1. Is 'auto ref' still the chosen syntax (I guess so)?
Why not `scope ref` (or `in ref` == `const scope ref`)?
See DIP 36
I don't see an argument against `scope ref` in DIP36, quite the opposite...
Jun 03 2015
parent "Namespace" <rswhite4 gmail.com> writes:
On Wednesday, 3 June 2015 at 10:07:41 UTC, Marc Schütz wrote
 I don't see an argument against `scope ref` in DIP36, quite the 
 opposite...
I know I was one of the authors. But it was rejected.
Jun 03 2015
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Apologies if I've missed something - I haven't had much time to keep up with
the 
discussions lately.

What is the use case for rvalue references in a garbage-collected language?

To me, it sounds like people want this feature for D purely because C++ has it.

Stewart.

-- 
My email address is valid but not my primary mailbox and not checked regularly.
 Please 
keep replies on the 'group where everybody may benefit.
Jun 09 2015
next sibling parent reply "Namespace" <rswhite4 gmail.com> writes:
On Tuesday, 9 June 2015 at 11:04:43 UTC, Stewart Gordon wrote:
 Apologies if I've missed something - I haven't had much time to 
 keep up with the discussions lately.

 What is the use case for rvalue references in a 
 garbage-collected language?

 To me, it sounds like people want this feature for D purely 
 because C++ has it.

 Stewart.
What does this have to do with "garbage-collected language"? If I have a big struct, e.g. ---- struct Matrix { float[16] values = [...]; } ---- I always want to pass it by ref because a move or a copy would be too slow.
Jun 09 2015
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/9/15 8:14 AM, Namespace wrote:
 On Tuesday, 9 June 2015 at 11:04:43 UTC, Stewart Gordon wrote:
 Apologies if I've missed something - I haven't had much time to keep
 up with the discussions lately.

 What is the use case for rvalue references in a garbage-collected
 language?

 To me, it sounds like people want this feature for D purely because
 C++ has it.

 Stewart.
What does this have to do with "garbage-collected language"? If I have a big struct, e.g. ---- struct Matrix { float[16] values = [...]; } ---- I always want to pass it by ref because a move or a copy would be too slow.
It's actually faster to pass an rvalue by value, because it's constructed on the stack anyway. The real reason for this I think is to avoid building multiple functions that have identical implementation. -Steve
Jun 09 2015
parent reply "kink" <noone nowhere.com> writes:
On Tuesday, 9 June 2015 at 13:13:53 UTC, Steven Schveighoffer 
wrote:
 It's actually faster to pass an rvalue by value, because it's 
 constructed on the stack anyway.
I seriously doubt that's true for a large struct, e.g., something containing a large static array. Why move/copy the damn thing if I'm only going to read a tiny portion of it? And please don't forget the ABI in that regard. E.g., on Win64, only POD types <= 64 bits (and whose size is a power of 2) are really passed by value (in a register or on the stack); all other types are passed as reference to a dedicated copy allocated on the caller's stack. So in this case, the indirection is enforced by the ABI anyway. If the callee is not going to modify the parameter, the copy should obviously be elided, falling back to classical byref passing.
Jun 09 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/9/15 10:53 AM, kink wrote:
 On Tuesday, 9 June 2015 at 13:13:53 UTC, Steven Schveighoffer wrote:
 It's actually faster to pass an rvalue by value, because it's
 constructed on the stack anyway.
I seriously doubt that's true for a large struct, e.g., something containing a large static array. Why move/copy the damn thing if I'm only going to read a tiny portion of it?
Because it's not moved. It's written in the stack where it will be passed to the next function. Then access to the data is done via stack pointer offsets instead of an extra indirection. -Steve
Jun 09 2015
parent reply "kink" <noone nowhere.com> writes:
On Tuesday, 9 June 2015 at 15:08:07 UTC, Steven Schveighoffer 
wrote:
 Because it's not moved. It's written in the stack where it will 
 be passed to the next function.
Hmm, you mean the callee's function parameters stack? That's not always going to work, e.g., on Win64 the first 4 args are passed in registers, always. And, as I said, that ABI doesn't support byval passing of types > 64 bits (let's exclude vector types here), so rvalues > 64 bits can sadly not be constructed in-place without violating the Win64 ABI - they'll have to be passed byref.
Jun 09 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 6/9/15 12:23 PM, kink wrote:
 On Tuesday, 9 June 2015 at 15:08:07 UTC, Steven Schveighoffer wrote:
 Because it's not moved. It's written in the stack where it will be
 passed to the next function.
Hmm, you mean the callee's function parameters stack? That's not always going to work, e.g., on Win64 the first 4 args are passed in registers, always.
If that's what's required, that's what we do. I'm not strictly saying that we will *always* do stack passing in spite of the ABI. But passing a large rvalue by value does not involve any moving of data, and can be abstracted to a pass by ref if needed. It's never less performing than an explicit pass by ref.
 And, as I said, that ABI doesn't support byval passing of types
  > 64 bits (let's exclude vector types here), so rvalues > 64 bits can
 sadly not be constructed in-place without violating the Win64 ABI -
 they'll have to be passed byref.
I don't think we violate the Win64 ABI. So if it requires pass by ref, it requires pass by ref. I am not an expert in this matter. You may want to try some disassembly and see what D does. -Steve
Jun 09 2015
parent reply "kinke" <noone nowhere.com> writes:
On Tuesday, 9 June 2015 at 17:38:00 UTC, Steven Schveighoffer 
wrote:
 But passing a large rvalue by value does not involve any moving 
 of data, and can be abstracted to a pass by ref if needed. It's 
 never less performing than an explicit pass by ref.
Thanks Steve. The problem I see here on Win64 is that the current `auto ref` implementation for templates, i.e., 2^N function instantiations for N lvalue/rvalue combinations, seems totally useless for value types for which the ABI enforces pass-by-ref anyway. In essence, `auto ref T` for templated functions on Win64 boils down to a simple `ref` accepting rvalue arguments iff T cannot be passed by value. All what's needed is constructing the rvalue on the caller's stack and destroying it after the call; the callee isn't affected at all, so no need for 2^N function versions, 1 is enough. Note that I haven't inspected the DMD code yet, but I assume it makes no exception for Win64 in that regard. No opinions on the semantics for `in` I proposed earlier? `in T` would be something like a non-escapable `const auto ref T` accepting rvalues without codebloat and avoiding the indirection for small POD types T. Wouldn't that eliminate 99% of the use cases for `auto ref`, improve readability substantially and be the solution for all the C++ guys missing the rvalue-bindability of `const T&`?
Jun 09 2015
parent reply "Namespace" <rswhite4 gmail.com> writes:
 No opinions on the semantics for `in` I proposed earlier? `in 
 T` would be something like a non-escapable `const auto ref T` 
 accepting rvalues without codebloat and avoiding the 
 indirection for small POD types T. Wouldn't that eliminate 99% 
 of the use cases for `auto ref`, improve readability 
 substantially and be the solution for all the C++ guys missing 
 the rvalue-bindability of `const T&`?
'in' means 'const scope' and 'scope ref' together with 'in ref' was proposed in DIP 36 which was rejected. Let's see if Andrei thinks that my current work is satisfying. I hope so. :)
Jun 09 2015
parent reply "kink" <noone nowhere.com> writes:
On Tuesday, 9 June 2015 at 20:25:28 UTC, Namespace wrote:
 No opinions on the semantics for `in` I proposed earlier? `in 
 T` would be something like a non-escapable `const auto ref T` 
 accepting rvalues without codebloat and avoiding the 
 indirection for small POD types T. Wouldn't that eliminate 99% 
 of the use cases for `auto ref`, improve readability 
 substantially and be the solution for all the C++ guys missing 
 the rvalue-bindability of `const T&`?
'in' means 'const scope' and 'scope ref' together with 'in ref' was proposed in DIP 36 which was rejected. Let's see if Andrei thinks that my current work is satisfying. I hope so. :)
Can you point me to the justifications for the rejection? It should be pretty obvious that something like that is required. Personally, I'd go with `ref` being non-escapable by default and hence providing implicit rvalue-bindability, and having to use `escapable ref` if the parameter may escape and disallowing rvalues for these parameters. I know it's never gonna happen, it's just what I'd prefer. I know what `in` currently means. Your proposed `in ref T` syntax is imo not much better than C++ `const T&`, so I'd prefer a simple and convenient `in T`. Semantics would be identical to your `in ref` with the additional optimization for small POD types. And for beginners, one could simply describe it as: 'Use the in keyword for a parameter if you're not going to mutate it. Don't rely on its identity as the argument may be passed by value or reference, whatever seems more efficient for the compiler and the target platform.'
Jun 10 2015
parent bitwise <bitwise.pvt gmail.com> writes:
On Wed, 10 Jun 2015 04:52:46 -0400, kink <noone nowhere.com> wrote:

 I know what `in` currently means. Your proposed `in ref T` syntax is imo  
 not much better than C++ `const T&`, so I'd prefer a simple and  
 convenient `in T`. Semantics would be identical to your `in ref` with  
 the additional optimization for small POD types. And for beginners, one  
 could simply describe it as:
 'Use the in keyword for a parameter if you're not going to mutate it.  
 Don't rely on its identity as the argument may be passed by value or  
 reference, whatever seems more efficient for the compiler and the target  
 platform.'
+1 Bit
Jun 11 2015
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
On 09/06/2015 13:14, Namespace wrote:
<snip>
 What does this have to do with "garbage-collected language"?
 If I have a big struct, e.g.
 ----
 struct Matrix {
      float[16] values = [...];
 }
 ----
 I always want to pass it by ref because a move or a copy would be too slow.
That seems to me a matter more of having something that behaves like C++ const T&, than of rvalue references as such. Stewart. -- My email address is valid but not my primary mailbox and not checked regularly. Please keep replies on the 'group where everybody may benefit.
Jun 12 2015
parent "Namespace" <rswhite4 gmail.com> writes:
On Friday, 12 June 2015 at 19:39:25 UTC, Stewart Gordon wrote:
 On 09/06/2015 13:14, Namespace wrote:
 <snip>
 What does this have to do with "garbage-collected language"?
 If I have a big struct, e.g.
 ----
 struct Matrix {
      float[16] values = [...];
 }
 ----
 I always want to pass it by ref because a move or a copy would 
 be too slow.
That seems to me a matter more of having something that behaves like C++ const T&, than of rvalue references as such. Stewart.
Yes, you could say that. It is implemented in this manner.
Jun 12 2015
prev sibling next sibling parent bitwise <bitwise.pvt gmail.com> writes:
On Tue, 09 Jun 2015 07:04:36 -0400, Stewart Gordon <smjg_1998 yahoo.com>  
wrote:

 Apologies if I've missed something - I haven't had much time to keep up  
 with the discussions lately.

 What is the use case for rvalue references in a garbage-collected  
 language?

 To me, it sounds like people want this feature for D purely because C++  
 has it.

 Stewart.
If you have a function that takes a huge struct, like, as Namespace says, containing a float[16], you would want to pass by reference. Currently, given the following code, struct Mat4 { float elements[16]; } void TakeMatrix(ref Mat4 m) { } Then you must use it like this: Mat4 tmp = Mat4(); TakeMatrix(tmp); With r-value references(auto ref), you can do the following, and 'tmp' will be 'auto'matically created for you: TakeMatrix(Mat4()); Bit
Jun 09 2015
prev sibling parent bitwise <bitwise.pvt gmail.com> writes:
On Tue, 09 Jun 2015 07:04:36 -0400, Stewart Gordon <smjg_1998 yahoo.com>  
wrote:
 To me, it sounds like people want this feature for D purely because C++  
 has it.

 Stewart.
That's actually not a bad reason ;) Suppose we wanted to write bindings for some C++ code which made use of const-ref parameters: http://help.autodesk.com/view/FBX/2015/ENU/?guid=__cpp_ref_class_fbx_a_matrix_html Bit
Jun 09 2015