www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - auto ref and non-templated functions

reply Jonathan M Davis <jmdavisProg gmx.com> writes:
This has probably been discussed before, so someone has probably already 
explained why this is a bad idea, but I can't remember why that would be, so 
I'm going to ask:

Why can't we simply make auto ref work with non-templated functions by making 
it automatically generate both the ref and non-ref versions? So, if I do

auto foo(auto ref S s) { /*do stuff*/ }

I automatically get something like

auto foo(S s) { foo(s); }
auto foo(ref S s) { /*do stuff*/ }

and

auto foo(auto const ref S s) { /* do stuff* / }

becomes

auto foo(const S s) { foo(s); }
auto foo(ref const S s) { /* do stuff */ }

What problems does this cause? Why haven't we just done this already?

And if that doesn't work, can we simply make it so that the compiler 
automatically creates a variable when you pass an rvalue to a non-templated 
auto ref function? So, with

auto foo(auto ref S s) { /*do stuff*/ }

you get

auto foo(ref S s) { /* do stuff*/ }

but when you call it with an rvalue like with

S bar() { ... }
foo(bar());

you get something like

auto _rValue = bar();
foo(_rValue};

where _rValue leaves scope after the call to foo. Are there any problems that 
anyone can see with that?

It just seems to me that it should be relatively easy to come up with a 
solution to make auto ref work with non-templated functions, and then we can 
solve the whole const ref issue and be done with it.

- Jonathan M Davis
Dec 24 2012
next sibling parent "Robert Clipsham" <robert octarineparrot.com> writes:
On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M Davis 
wrote:
 This has probably been discussed before, so someone has 
 probably already
 explained why this is a bad idea, but I can't remember why that 
 would be, so
 I'm going to ask:

 Why can't we simply make auto ref work with non-templated 
 functions by making
 it automatically generate both the ref and non-ref versions? 
 So, if I do

 auto foo(auto ref S s) { /*do stuff*/ }

Is: auto foo()(auto ref S e) { /* do stuff */ } So hard to write? (It's Christmas Eve, and I can't be bothered giving real arguments against right now - I suppose someone else will do this later... Merry Christmas!) Robert
Dec 24 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, December 24, 2012 20:43:06 Robert Clipsham wrote:
 Is:
 
 auto foo()(auto ref S e) { /* do stuff */ }
 
 So hard to write?
 
 (It's Christmas Eve, and I can't be bothered giving real
 arguments against right now - I suppose someone else will do this
 later... Merry Christmas!)

If nothing else, it doesn't work for classes, because templated functions can't be virtual. Also, it forces you to put the entire function's implementation in a .di file if you use .di files, which makes it untentable for many of the folks who actually need to use .di files. We need a solution which doesn't involve templates. - Jonathan M Davis
Dec 24 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 If nothing else, it doesn't work for classes, because templated 
 functions
 can't be virtual. Also, it forces you to put the entire 
 function's
 implementation in a .di file if you use .di files, which makes 
 it untentable for
 many of the folks who actually need to use .di files.

 We need a solution which doesn't involve templates.

 - Jonathan M Davis

+1
Dec 24 2012
prev sibling next sibling parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M Davis 
wrote:
 Why can't we simply make auto ref work with non-templated 
 functions by making
 it automatically generate both the ref and non-ref versions?

 [snip]

 What problems does this cause? Why haven't we just done this 
 already?

What does this generate? auto foo(auto ref S a, auto ref S b, auto ref S c, auto ref S d) { ... } 16 different functions, one for each combination? Sounds like a bad idea.
 And if that doesn't work, can we simply make it so that the 
 compiler
 automatically creates a variable when you pass an rvalue to a 
 non-templated
 auto ref function?

I don't see any problems with this, but I admittedly haven't thought too much about it.
Dec 24 2012
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/25/12 12:34 AM, Zhenya wrote:
 On Tuesday, 25 December 2012 at 01:40:16 UTC, Peter Alexander wrote:
 On Tuesday, 25 December 2012 at 00:56:44 UTC, Peter Alexander wrote:
 On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M Davis wrote:
 And if that doesn't work, can we simply make it so that the compiler
 automatically creates a variable when you pass an rvalue to a
 non-templated
 auto ref function?

I don't see any problems with this, but I admittedly haven't thought too much about it.

If there are no problems with this way, then what I want to know is why the template version of auto ref wasn't implemented this way. The way auto ref is currently implemented for templates is a bit of a mess.

like this void foo(auto ref S s1,auto ref S s2,...,auto ref s10) compiler should generate 2^10 versions of function foo.

The compiler will only generate as many versions as there are compatible calls. Andrei
Dec 25 2012
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
12/25/2012 6:15 PM, Peter Alexander пишет:
 On Tuesday, 25 December 2012 at 14:09:13 UTC, Andrei Alexandrescu wrote:

 void foo(auto ref S s1,auto ref S s2,...,auto ref s10)

 compiler should generate 2^10 versions of function foo.

The compiler will only generate as many versions as there are compatible calls.

If it were a template. Jonathan's (first) proposal is that they are all generated eagerly, so that they can be used as virtual functions (among other things). Generating them lazily like template defeats the purpose of his proposal (to do that, just use templates!) The first proposal is a dead end. I think his second proposal is more interesting, so I will repeat it here: "Can we simply make it so that the compiler automatically creates a variable when you pass an rvalue to a non-templated auto ref function?" So non-template auto ref parameters are just like ref parameters, except they will automatically convert rvalues to lvalues on call by creating a local variable. Normal ref parameters will still need lvalues.

+1 I think that was pretty much the conclusion of the last ref-to-rvalue thread. Just make sure proper scoping rules are followed. -- Dmitry Olshansky
Dec 25 2012
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/25/12 5:36 AM, Jonathan M Davis wrote:
 On Tuesday, December 25, 2012 11:14:40 Namespace wrote:
 What does this generate?

 auto foo(auto ref S a, auto ref S b, auto ref S c, auto ref S
 d) { ... }

 16 different functions, one for each combination? Sounds like a
 bad idea.

In my opinion, this should produce only two functions: #1: auto foo(ref S a, ref S b, ref S c, ref S d) { ... } #2: auto foo(S a, S b, S c, S d) { ... }

So, you'd take the performance hit of copying all of your function arguments simply because one of them was an rvalue? No. I think that Peter's point shows exactly why this is a bad idea. However, creating only one version of the function which takes all refs and specifcally creating variables underneath the hood for any rvalues so that they can be passed to the function still seems like it could work.

Yes, that does work and is easy to implement. Andrei
Dec 25 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-12-25 15:11, Andrei Alexandrescu wrote:

 Yes, that does work and is easy to implement.

That's also what one needs to do now. -- /Jacob Carlborg
Dec 26 2012
prev sibling next sibling parent "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Tuesday, 25 December 2012 at 00:56:44 UTC, Peter Alexander 
wrote:
 On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M Davis 
 wrote:
 And if that doesn't work, can we simply make it so that the 
 compiler
 automatically creates a variable when you pass an rvalue to a 
 non-templated
 auto ref function?

I don't see any problems with this, but I admittedly haven't thought too much about it.

If there are no problems with this way, then what I want to know is why the template version of auto ref wasn't implemented this way. The way auto ref is currently implemented for templates is a bit of a mess.
Dec 24 2012
prev sibling next sibling parent "Zhenya" <zheny list.ru> writes:
On Tuesday, 25 December 2012 at 01:40:16 UTC, Peter Alexander 
wrote:
 On Tuesday, 25 December 2012 at 00:56:44 UTC, Peter Alexander 
 wrote:
 On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M Davis 
 wrote:
 And if that doesn't work, can we simply make it so that the 
 compiler
 automatically creates a variable when you pass an rvalue to a 
 non-templated
 auto ref function?

I don't see any problems with this, but I admittedly haven't thought too much about it.

If there are no problems with this way, then what I want to know is why the template version of auto ref wasn't implemented this way. The way auto ref is currently implemented for templates is a bit of a mess.

function like this void foo(auto ref S s1,auto ref S s2,...,auto ref s10) compiler should generate 2^10 versions of function foo.
Dec 24 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, December 25, 2012 01:56:42 Peter Alexander wrote:
 On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M Davis
 
 wrote:
 Why can't we simply make auto ref work with non-templated
 functions by making
 it automatically generate both the ref and non-ref versions?
 
 [snip]
 
 What problems does this cause? Why haven't we just done this
 already?

What does this generate? auto foo(auto ref S a, auto ref S b, auto ref S c, auto ref S d) { ... } 16 different functions, one for each combination? Sounds like a bad idea.

Excellent point.
 And if that doesn't work, can we simply make it so that the
 compiler
 automatically creates a variable when you pass an rvalue to a
 non-templated
 auto ref function?

I don't see any problems with this, but I admittedly haven't thought too much about it.

I hope that it's feasible (or something close to it anyway) so that we can actually solve this problem once and for all. - Jonathan M Davis
Dec 25 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 What does this generate?

 auto foo(auto ref S a, auto ref S b, auto ref S c, auto ref S 
 d) { ... }

 16 different functions, one for each combination? Sounds like a 
 bad idea.

In my opinion, this should produce only two functions: #1: auto foo(ref S a, ref S b, ref S c, ref S d) { ... } #2: auto foo(S a, S b, S c, S d) { ... }
Dec 25 2012
prev sibling next sibling parent Jens Mueller <jens.k.mueller gmx.de> writes:
Jonathan M Davis wrote:
 On Tuesday, December 25, 2012 01:56:42 Peter Alexander wrote:
 On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M Davis
 
 wrote:
 Why can't we simply make auto ref work with non-templated
 functions by making
 it automatically generate both the ref and non-ref versions?
 
 [snip]
 
 What problems does this cause? Why haven't we just done this
 already?

What does this generate? auto foo(auto ref S a, auto ref S b, auto ref S c, auto ref S d) { ... } 16 different functions, one for each combination? Sounds like a bad idea.

Excellent point.

I'm not sure but doesn't the compiler only create such a function when it is called. Still it may be confusing but it's similar to a function template. But here it's a template regarding passing convention. Jens
Dec 25 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, December 25, 2012 11:14:40 Namespace wrote:
 What does this generate?
 
 auto foo(auto ref S a, auto ref S b, auto ref S c, auto ref S
 d) { ... }
 
 16 different functions, one for each combination? Sounds like a
 bad idea.

In my opinion, this should produce only two functions: #1: auto foo(ref S a, ref S b, ref S c, ref S d) { ... } #2: auto foo(S a, S b, S c, S d) { ... }

So, you'd take the performance hit of copying all of your function arguments simply because one of them was an rvalue? No. I think that Peter's point shows exactly why this is a bad idea. However, creating only one version of the function which takes all refs and specifcally creating variables underneath the hood for any rvalues so that they can be passed to the function still seems like it could work. - Jonathan M Davis
Dec 25 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, December 25, 2012 11:12:43 Jens Mueller wrote:
 Jonathan M Davis wrote:
 On Tuesday, December 25, 2012 01:56:42 Peter Alexander wrote:
 On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M Davis
 
 wrote:
 Why can't we simply make auto ref work with non-templated
 functions by making
 it automatically generate both the ref and non-ref versions?
 
 [snip]
 
 What problems does this cause? Why haven't we just done this
 already?

What does this generate? auto foo(auto ref S a, auto ref S b, auto ref S c, auto ref S d) { ... } 16 different functions, one for each combination? Sounds like a bad idea.

Excellent point.

I'm not sure but doesn't the compiler only create such a function when it is called. Still it may be confusing but it's similar to a function template. But here it's a template regarding passing convention.

If it were a template, sure. But the whole point is that we need a solution which _isn't_ a template, which in this case would mean generating every possible combination regardless of whether they were used or not. So, I think that Peter has shown why that particular approach is untenable. - Jonathan M Davis
Dec 25 2012
prev sibling next sibling parent Jens Mueller <jens.k.mueller gmx.de> writes:
Jonathan M Davis wrote:
 On Tuesday, December 25, 2012 11:12:43 Jens Mueller wrote:
 Jonathan M Davis wrote:
 On Tuesday, December 25, 2012 01:56:42 Peter Alexander wrote:
 On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M Davis
 
 wrote:
 Why can't we simply make auto ref work with non-templated
 functions by making
 it automatically generate both the ref and non-ref versions?
 
 [snip]
 
 What problems does this cause? Why haven't we just done this
 already?

What does this generate? auto foo(auto ref S a, auto ref S b, auto ref S c, auto ref S d) { ... } 16 different functions, one for each combination? Sounds like a bad idea.

Excellent point.

I'm not sure but doesn't the compiler only create such a function when it is called. Still it may be confusing but it's similar to a function template. But here it's a template regarding passing convention.

If it were a template, sure. But the whole point is that we need a solution which _isn't_ a template, which in this case would mean generating every possible combination regardless of whether they were used or not. So, I think that Peter has shown why that particular approach is untenable.

And the solution needs to be non-template based because it needs to work with classes? Is that the only reason? Jens
Dec 25 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, December 25, 2012 11:44:45 Jens Mueller wrote:
 And the solution needs to be non-template based because it needs to work
 with classes? Is that the only reason?

That and if it's not non-templated, it's impossible to have auto ref functions which hide their implementation for those who need to use .di files to hide the implementation. It also might also be necessary if you need to be able to guarantee that the function exists. Basically, any situation where you can't use a template or where it's undesirable to use a template, the current auto ref doesn't work. But the big one is classes, as templated functions can't be virtual. Without a non-templated solution, virtual functions will never be able to do the equivalent of C++'s const& or anything like it, meaning that they'll incur overhead due to unnecessary copies in many cases. - Jonathan M Davis
Dec 25 2012
prev sibling next sibling parent "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Tuesday, 25 December 2012 at 14:09:13 UTC, Andrei Alexandrescu 
wrote:
 On 12/25/12 12:34 AM, Zhenya wrote:
 On Tuesday, 25 December 2012 at 01:40:16 UTC, Peter Alexander 
 wrote:
 On Tuesday, 25 December 2012 at 00:56:44 UTC, Peter Alexander 
 wrote:
 On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M 
 Davis wrote:
 And if that doesn't work, can we simply make it so that the 
 compiler
 automatically creates a variable when you pass an rvalue to 
 a
 non-templated
 auto ref function?

I don't see any problems with this, but I admittedly haven't thought too much about it.

If there are no problems with this way, then what I want to know is why the template version of auto ref wasn't implemented this way. The way auto ref is currently implemented for templates is a bit of a mess.

function like this void foo(auto ref S s1,auto ref S s2,...,auto ref s10) compiler should generate 2^10 versions of function foo.

The compiler will only generate as many versions as there are compatible calls.

If it were a template. Jonathan's (first) proposal is that they are all generated eagerly, so that they can be used as virtual functions (among other things). Generating them lazily like template defeats the purpose of his proposal (to do that, just use templates!) The first proposal is a dead end. I think his second proposal is more interesting, so I will repeat it here: "Can we simply make it so that the compiler automatically creates a variable when you pass an rvalue to a non-templated auto ref function?" So non-template auto ref parameters are just like ref parameters, except they will automatically convert rvalues to lvalues on call by creating a local variable. Normal ref parameters will still need lvalues.
Dec 25 2012
prev sibling next sibling parent "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Tuesday, 25 December 2012 at 14:11:14 UTC, Andrei Alexandrescu 
wrote:
 On 12/25/12 5:36 AM, Jonathan M Davis wrote:
 However, creating only one version of the function which takes 
 all refs and
 specifcally creating variables underneath the hood for any 
 rvalues so that
 they can be passed to the function still seems like it could 
 work.

Yes, that does work and is easy to implement.

Is there any reason this hasn't been implemented? And why aren't template auto ref functions implemented like that? It would be a bit of a shame if auto ref in template functions works differently to auto ref in non-template function.
Dec 25 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
 On 2012-12-25 15:11, Andrei Alexandrescu wrote:
 Yes, that does work and is easy to implement.


This also solves the problem of taking the address of the `auto ref` function or method. Two birds with one stone.
Dec 26 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
 Yes, that does work and is easy to implement.

 Andrei

And why isnt it in 2.061? ;)
Dec 26 2012
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 25 December 2012 at 14:09:13 UTC, Andrei Alexandrescu 
wrote:
 On 12/25/12 12:34 AM, Zhenya wrote:
 On Tuesday, 25 December 2012 at 01:40:16 UTC, Peter Alexander 
 wrote:
 On Tuesday, 25 December 2012 at 00:56:44 UTC, Peter Alexander 
 wrote:
 On Monday, 24 December 2012 at 17:40:54 UTC, Jonathan M 
 Davis wrote:
 And if that doesn't work, can we simply make it so that the 
 compiler
 automatically creates a variable when you pass an rvalue to 
 a
 non-templated
 auto ref function?

I don't see any problems with this, but I admittedly haven't thought too much about it.

If there are no problems with this way, then what I want to know is why the template version of auto ref wasn't implemented this way. The way auto ref is currently implemented for templates is a bit of a mess.

function like this void foo(auto ref S s1,auto ref S s2,...,auto ref s10) compiler should generate 2^10 versions of function foo.

The compiler will only generate as many versions as there are compatible calls. Andrei

In such a case, this is incompatible with virtual method.
Dec 26 2012
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 25 December 2012 at 14:11:14 UTC, Andrei Alexandrescu 
wrote:
 On 12/25/12 5:36 AM, Jonathan M Davis wrote:
 On Tuesday, December 25, 2012 11:14:40 Namespace wrote:
 What does this generate?

 auto foo(auto ref S a, auto ref S b, auto ref S c, auto ref S
 d) { ... }

 16 different functions, one for each combination? Sounds 
 like a
 bad idea.

In my opinion, this should produce only two functions: #1: auto foo(ref S a, ref S b, ref S c, ref S d) { ... } #2: auto foo(S a, S b, S c, S d) { ... }

So, you'd take the performance hit of copying all of your function arguments simply because one of them was an rvalue? No. I think that Peter's point shows exactly why this is a bad idea. However, creating only one version of the function which takes all refs and specifcally creating variables underneath the hood for any rvalues so that they can be passed to the function still seems like it could work.

Yes, that does work and is easy to implement. Andrei

Sound like the wayt o go for me. But is ato ref needed in such case ? Why not simply allow ref to behave that way ?
Dec 26 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, December 26, 2012 23:02:25 deadalnix wrote:
 Sound like the wayt o go for me. But is ato ref needed in such
 case ? Why not simply allow ref to behave that way ?

Because there's a very large difference between a function intended to take arguments by ref and one where you don't care. For instance, what if popFrontN suddenly accepted rvalues? Using it with rvalues would do nothing. We had problems with std.conv.parse precisely because there was a compiler bug that allowed you to pass string literals to it in spite of the fact that it takes its argument by ref and needs to mutate its argument. With auto ref, you're specifically saying that you don't care whether the function is given an lvalue or rvalue. You just want it to avoid unnecessary copies. That's very different. And auto ref then not only then protects you from cases of passing an rvalue to a function when it needs an lvalue, but it makes it clear in the function signature which is expected. - Jonathan M Davis
Dec 26 2012
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 26 December 2012 at 22:52:29 UTC, Jonathan M Davis 
wrote:
 On Wednesday, December 26, 2012 23:02:25 deadalnix wrote:
 Sound like the wayt o go for me. But is ato ref needed in such
 case ? Why not simply allow ref to behave that way ?

Because there's a very large difference between a function intended to take arguments by ref and one where you don't care. For instance, what if popFrontN suddenly accepted rvalues? Using it with rvalues would do nothing. We had problems with std.conv.parse precisely because there was a compiler bug that allowed you to pass string literals to it in spite of the fact that it takes its argument by ref and needs to mutate its argument.

That is a const bug not a ref bug.
 With auto ref, you're specifically saying that you don't care 
 whether the
 function is given an lvalue or rvalue. You just want it to 
 avoid unnecessary
 copies. That's very different. And auto ref then not only then 
 protects you
 from cases of passing an rvalue to a function when it needs an 
 lvalue, but it
 makes it clear in the function signature which is expected.

 - Jonathan M Davis

I suspect making the distinction is complicating uselessly the language for a benefit that isn't really clear.
Dec 26 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, December 27, 2012 06:26:38 deadalnix wrote:
 On Wednesday, 26 December 2012 at 22:52:29 UTC, Jonathan M Davis
 
 wrote:
 On Wednesday, December 26, 2012 23:02:25 deadalnix wrote:
 Sound like the wayt o go for me. But is ato ref needed in such
 case ? Why not simply allow ref to behave that way ?

Because there's a very large difference between a function intended to take arguments by ref and one where you don't care. For instance, what if popFrontN suddenly accepted rvalues? Using it with rvalues would do nothing. We had problems with std.conv.parse precisely because there was a compiler bug that allowed you to pass string literals to it in spite of the fact that it takes its argument by ref and needs to mutate its argument.

That is a const bug not a ref bug.

No, it's not. A function which takes its argument by ref is specifically intended to mutate its argument, otherwise it wouldn't take the argument by ref. Allowing such a parameter to be passed an rvalue makes it so that the function does not do what it's intended to do and will easily cause bugs. C++ made it so that const& would accept rvalues with the idea that if it were const, then you obviously didn't want to mutate the argument, and you could then use it as a means to avoid unnecessary copies. But with how restrictive const is in D, we really should have a means of declaring a function parameter such that it's intended to avoid unnecessary copies but isn't necessarily const and is obviously not intended to mutate the original (though as long as the parameter isn't const, mutation is obviously still a possibility, and const is required to guarantee that that doesn't happen - _that_ could be a const-related bug). But allowing ref functions to accept rvalues is an incredibly bad idea, because it's mixing two very different idioms - taking an argument by ref in order to mutate that argument and possibly taking an argument by ref in order to avoid a copy. It never makes sense to take an rvalue by ref. rvalue arguments need to use moves, not ref. The suggestion of creating a variable with limited scope which rvalues are assigned to with auto ref allows for you to only have one function overload and yet clearly separates it from functions which are intended to mutate their arguments.
 With auto ref, you're specifically saying that you don't care
 whether the
 function is given an lvalue or rvalue. You just want it to
 avoid unnecessary
 copies. That's very different. And auto ref then not only then
 protects you
 from cases of passing an rvalue to a function when it needs an
 lvalue, but it
 makes it clear in the function signature which is expected.
 
 - Jonathan M Davis

I suspect making the distinction is complicating uselessly the language for a benefit that isn't really clear.

Well, I strongly disagree. I think that making ref accept rvalues is just begging for bugs. Not even C++ allowed that. They restricted it specifically to const&. - Jonathan M Davis
Dec 26 2012
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Thursday, 27 December 2012 at 05:53:23 UTC, Jonathan M Davis 
wrote:
 No, it's not.

The example IS a const bug and have nothing to do with ref. You get a mutable reference from a literal, which is immutable in the first place.
 A function which takes its argument by ref is specifically
 intended to mutate its argument, otherwise it wouldn't take the 
 argument by
 ref. Allowing such a parameter to be passed an rvalue makes it 
 so that the
 function does not do what it's intended to do and will easily 
 cause bugs.

A function can use ref argument for performance reasons.
 C++ made it so that const& would accept rvalues with the idea 
 that if it were
 const, then you obviously didn't want to mutate the argument, 
 and you could
 then use it as a means to avoid unnecessary copies. But with 
 how restrictive
 const is in D, we really should have a means of declaring a 
 function parameter
 such that it's intended to avoid unnecessary copies but isn't 
 necessarily
 const and is obviously not intended to mutate the original 
 (though as long as
 the parameter isn't const, mutation is obviously still a 
 possibility, and
 const is required to guarantee that that doesn't happen - 
 _that_ could be a
 const-related bug). But allowing ref functions to accept 
 rvalues is an
 incredibly bad idea, because it's mixing two very different 
 idioms - taking an
 argument by ref in order to mutate that argument and possibly 
 taking an
 argument by ref in order to avoid a copy. It never makes sense 
 to take an
 rvalue by ref. rvalue arguments need to use moves, not ref.

I have read this argument many any times, but still have to experience it in actual code. But, thinking about it, isn't the need for an auto ref type necessary more than annotating every single function argument with ref/auto ref ?
Dec 26 2012
prev sibling next sibling parent "jerro" <a a.com> writes:
 "Can we simply make it so that the compiler automatically 
 creates a variable when you pass an rvalue to a non-templated 
 auto ref function?"

 So non-template auto ref parameters are just like ref 
 parameters, except they will automatically convert rvalues to 
 lvalues on call by creating a local variable. Normal ref 
 parameters will still need lvalues.

I made a pull requests that implements this: https://github.com/D-Programming-Language/dmd/pull/1428 I don't have a good knowledge of the DMD cod base, so there could be some problems with this that I am not aware of, but it does seem to work.
Jan 02 2013
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Wednesday, 26 December 2012 at 22:52:29 UTC, Jonathan M Davis 
wrote:
 On Wednesday, December 26, 2012 23:02:25 deadalnix wrote:
 Sound like the way to go for me. But is auto ref needed in such
 case ? Why not simply allow ref to behave that way ?

Because there's a very large difference between a function intended to take arguments by ref and one where you don't care.

 With auto ref, you're specifically saying that you don't care 
 whether the function is given an lvalue or rvalue. You just 
 want it to avoid unnecessary copies. That's very different. 
 And auto ref then not only then protects you from cases of 
 passing an rvalue to a function when it needs an lvalue, but 
 it makes it clear in the function signature which is expected.


Not to bring back something that might be considered closed, But is auto ref going to be allowed for non-template functions in an upcoming version? There's plenty of times I'd like to use ref when possible but don't want to write a forwarding function converting non-ref to ref.
Jan 18 2013
prev sibling next sibling parent "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
if a function's argument is const ref, what would be the problem 
of allowing it to to be passed const ref lvalues + rvalues?
Jan 18 2013
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
  Not to bring back something that might be considered closed, 
 But is auto ref going to be allowed for non-template functions 
 in an upcoming version? There's plenty of times I'd like to use 
 ref when possible but don't want to write a forwarding function 
 converting non-ref to ref.

The pull is still there (https://github.com/D-Programming-Language/dmd/pull/1019) but as I'm asking here: http://forum.dlang.org/thread/hlyospppnjiziyokfvdd forum.dlang.org#post-pvwbojrtygwrxxviwarv:40forum.dlang.org an official statement would be pleasant.
Jan 18 2013
prev sibling parent "Namespace" <rswhite4 googlemail.com> writes:
No response probably means "you get no official statement"? ;)
Jan 21 2013