www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - R-values and const ref

reply Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
A while back dmd stopped allowing rvalues as ref function arguments. I
entirely understand why it was done, but the same restriction applies to the
ref const function parameters. This causes a lot of pain and at the moment
makes me use pass-by-value parameters(most notably when using structs). C++
doesn't have any problem with const ref and rvalues. Can we please restore
this behavior for const ref?
Sep 09 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Eldar Insafutdinov:
 Can we please restore this behavior for const ref?

From what I have seen D is built on different principles, so I doubt that will change. Bye, bearophile
Sep 09 2010
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 09 Sep 2010 06:08:14 -0400, Eldar Insafutdinov  
<e.insafutdinov gmail.com> wrote:

 A while back dmd stopped allowing rvalues as ref function arguments. I
 entirely understand why it was done, but the same restriction applies to  
 the
 ref const function parameters. This causes a lot of pain and at the  
 moment
 makes me use pass-by-value parameters(most notably when using structs).  
 C++
 doesn't have any problem with const ref and rvalues. Can we please  
 restore
 this behavior for const ref?

auto ref is supposed to handle that. However, I think it only works on templates. The thing is, when you pass an rvalue by reference, it's more expensive than passing it by value. If passed by value, since it's an rvalue, the compiler knows that it no longer is needed elsewhere, so it can just store it on the stack in the place it will be passing it. I still think the design needs some work, and there are some compiler annoyances that can't be helped (like the compiler complaining that opEquals must take const ref T) that make it impossible to write correct code. -Steve
Sep 09 2010
next sibling parent reply Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
I agree that auto ref may be a better option here, but I still see no reason to
disallow it. It is a performance issue, not a safety one. And as you said this
only works for templates, virtual functions are out of the game here.

PS. opEquals issue is very annoying, indeed.
Sep 09 2010
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Steven Schveighoffer (schveiguy yahoo.com)'s article
 On Thu, 09 Sep 2010 11:24:14 -0400, Eldar Insafutdinov
 <e.insafutdinov gmail.com> wrote:
 I agree that auto ref may be a better option here, but I still see no
 reason to
 disallow it. It is a performance issue, not a safety one. And as you
 said this
 only works for templates, virtual functions are out of the game here.

 PS. opEquals issue is very annoying, indeed.

sense for virtual functions. The problem with allowing const ref rvalues is then you are not *able* to make a better performing function, because rvalues match against const ref as well as the non-ref version. -Steve

After Bug 4843 (the one I posted this morning about overloading ref vs. non-ref w/ structs) is fixed, it might be a good idea to allow auto ref for non-templated functions as shorthand for a ref function plus a non-ref function that binds to rvalues and forwards to the ref function. On the other hand this might be too much special casing just to save a little typing. It also might not fly w/ Walter and other people who care about low-level/ABI stuff because it breaks the idea that, unless something is explicitly a template, one function at source level should map to one function at the binary level.
Sep 09 2010
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/9/10 10:43 CDT, dsimcha wrote:
 == Quote from Steven Schveighoffer (schveiguy yahoo.com)'s article
 On Thu, 09 Sep 2010 11:24:14 -0400, Eldar Insafutdinov
 <e.insafutdinov gmail.com>  wrote:
 I agree that auto ref may be a better option here, but I still see no
 reason to
 disallow it. It is a performance issue, not a safety one. And as you
 said this
 only works for templates, virtual functions are out of the game here.

 PS. opEquals issue is very annoying, indeed.

sense for virtual functions. The problem with allowing const ref rvalues is then you are not *able* to make a better performing function, because rvalues match against const ref as well as the non-ref version. -Steve

After Bug 4843 (the one I posted this morning about overloading ref vs. non-ref w/ structs) is fixed, it might be a good idea to allow auto ref for non-templated functions as shorthand for a ref function plus a non-ref function that binds to rvalues and forwards to the ref function. On the other hand this might be too much special casing just to save a little typing. It also might not fly w/ Walter and other people who care about low-level/ABI stuff because it breaks the idea that, unless something is explicitly a template, one function at source level should map to one function at the binary level.

There's no need to map auto ref to two functions. It's only about relaxing the checking for rvalue parameters. The idea will "go" with Walter because it simply is a misunderstanding between design and implementation. Andrei
Sep 09 2010
prev sibling parent Max Samukha <spambox d-coding.com> writes:
On 09/09/2010 06:26 PM, Steven Schveighoffer wrote:

 Yes, I forgot that you are allowed to overload via ref. That would make
 sense for virtual functions.

That forces us to provide multiple overloads, each matching one of the possible combinations of rvalue/lvalue arguments. A function with n struct parameters would require 2^n overloads. The only way to avoid the mess is to implement a single function taking all struct arguments by value or use templates, which is unacceptable in the general case. There is also an unspecified part related to default arguments. For example, this compiles: struct S { } S bar() { return S(); } void foo(ref const S s = bar()) { } Is it safe to rely on this feature?
Sep 15 2010
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 9/9/10 6:32 CDT, Steven Schveighoffer wrote:
 On Thu, 09 Sep 2010 06:08:14 -0400, Eldar Insafutdinov
 <e.insafutdinov gmail.com> wrote:

 A while back dmd stopped allowing rvalues as ref function arguments. I
 entirely understand why it was done, but the same restriction applies
 to the
 ref const function parameters. This causes a lot of pain and at the
 moment
 makes me use pass-by-value parameters(most notably when using
 structs). C++
 doesn't have any problem with const ref and rvalues. Can we please
 restore
 this behavior for const ref?

auto ref is supposed to handle that. However, I think it only works on templates.

Indeed, auto ref must work with non-templates. Andrei
Sep 09 2010
prev sibling next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Eldar Insafutdinov (e.insafutdinov gmail.com)'s article
 A while back dmd stopped allowing rvalues as ref function arguments. I
 entirely understand why it was done, but the same restriction applies to the
 ref const function parameters. This causes a lot of pain and at the moment
 makes me use pass-by-value parameters(most notably when using structs). C++
 doesn't have any problem with const ref and rvalues. Can we please restore
 this behavior for const ref?

FWIW, if you can't use templates and auto ref, there is a (slightly verbose) solution. DMD apparently allows overloading ref vs. non-ref, so you can write a forwarding function to bind to rvalues. This example compiles and does what it looks like it should. Perhaps the spec needs to be clarified so that people know about this feature and can be sure they're not relying on an obscure implementation bug. import std.stdio; void doStuff(const ref int i) { writeln("Doing stuff by ref."); } // Note that i needs to be const b/c otherwise when forwarding // the non-ref version will look like the better match and // we'll get infinite recursion. void doStuff(const int i) { writeln("Forwarding to ref overload."); doStuff(i); } void main() { doStuff(1); }
Sep 09 2010
parent dsimcha <dsimcha yahoo.com> writes:
== Quote from dsimcha (dsimcha yahoo.com)'s article
 FWIW, if you can't use templates and auto ref, there is a (slightly verbose)
 solution.  DMD apparently allows overloading ref vs. non-ref, so you can write
a
 forwarding function to bind to rvalues.

...except that I just realized it's broken for structs. http://d.puremagic.com/issues/post_bug.cgi
Sep 09 2010
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 09 Sep 2010 11:24:14 -0400, Eldar Insafutdinov  
<e.insafutdinov gmail.com> wrote:

 I agree that auto ref may be a better option here, but I still see no  
 reason to
 disallow it. It is a performance issue, not a safety one. And as you  
 said this
 only works for templates, virtual functions are out of the game here.

 PS. opEquals issue is very annoying, indeed.

Yes, I forgot that you are allowed to overload via ref. That would make sense for virtual functions. The problem with allowing const ref rvalues is then you are not *able* to make a better performing function, because rvalues match against const ref as well as the non-ref version. -Steve
Sep 09 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 09 Sep 2010 13:03:17 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 9/9/10 6:32 CDT, Steven Schveighoffer wrote:
 On Thu, 09 Sep 2010 06:08:14 -0400, Eldar Insafutdinov
 <e.insafutdinov gmail.com> wrote:

 A while back dmd stopped allowing rvalues as ref function arguments. I
 entirely understand why it was done, but the same restriction applies
 to the
 ref const function parameters. This causes a lot of pain and at the
 moment
 makes me use pass-by-value parameters(most notably when using
 structs). C++
 doesn't have any problem with const ref and rvalues. Can we please
 restore
 this behavior for const ref?

auto ref is supposed to handle that. However, I think it only works on templates.

Indeed, auto ref must work with non-templates.

Hm... how is that possible? The generated code must surely be different, so it is in fact a template, even if it's not syntaxed as one. -Steve
Sep 09 2010