November 07, 2012
On Wednesday, 7 November 2012 at 00:47:04 UTC, Jonathan M Davis wrote:
> No, because that would be doing the same thing as C++, which Walter and Andrei
> have already rejected. They specifically do _not_ want there to be any
> ambiguity between whether a const ref variable is an lvalue or rvalue. If they
> were willing to make const ref work the same as C++'s const&, then we would
> never have had this problem in the first place. We specifically need something
> other than const ref. The const ref can continue to work as it does now, but
> we'll have a way to get semantics similar to C++'s const& when we want them.

Wow, now this finally sheds some light on this topic. Do you have any links regarding their reasoning?
I simply and utterly fail to comprehend the need for a compiler to distinguish between a const reference to a named variable and a const reference to an unnamed temporary/literal (which the compiler is free to allocate wherever it makes most sense). Especially since the compiler could simply allocate and name the original rvalue as local variable on the caller's stack before the function call and hence transform it automatically to an lvalue, i.e., do that, what currently most of us have to painfully do by hand.
November 07, 2012
On Wednesday, November 07, 2012 02:15:26 martin wrote:
> Wow, now this finally sheds some light on this topic. Do you have any links regarding their reasoning?

The most recent discussion where Walter and Andrei were part of the discussion was here:

http://forum.dlang.org/post/4F84D6DD.5090405@digitalmars.com

A key component of the problem is that conversions cause problems. Also, IIRC allowing const ref to take rvalues causes some issues with overloading.

Making some changes to ref with regards to escaping apparently could change the situation a bit, and there's even some discussion in there of allowing ref to take rvalues if certain other things in the language are changed, but it's all up in the air at this point. Certainly, it's not a simple matter of just making const ref work with rvalues like most of the people coming from C++ want and expect.

- Jonathan M Davis
November 07, 2012
On Wednesday, 7 November 2012 at 00:32:04 UTC, martin wrote:
> So we do not really need 'auto ref' for non-templated functions or a new, even more confusing keyword which you, Jonathan, seem to insist on - 'const ref' (or, more elegantly 'in ref') is all we need. We simply want the compiler to automatically declare rvalues passed to 'const ref' parameters as local lvalues - problem solved for the majority of cases. For the remaining few which care about the involved cost for rvalue arguments, allow them to provide a function overload for rvalues (either manually or via 'auto ref' templates) - problem solved completely in my point of view. And that is actually exactly what the thread starter Malte proposes (and I already pointed that out in an earlier post).

 'in ref' may work, but what it implies doesn't quite make sense. 'auto ref' already being used for templates should be able to carry over to functions, however auto in the same section along with type declaration may seem a little confusing. Let's glance at a few of how they would be called.

//either
void func(int x);
void func(const int x);

//lvalue
void func(ref int x);
void func(const ref int x);

//either? auto ref/in ref
void func(auto ref int x);
void func(const auto ref int x);
void func(in ref int x);

 Assuming auto can't be used to do type referencing the 'const auto ref int' seems rather long. alternatively perhaps inout? (accepts any type, partially skewed?)

void func(inout ref int x);
void func(const inout ref int x);

 At this point for const it's just as large as the const auto ref.. So..

void func(inout ref int x); //mutable
void func(in ref int x);    //const version

void func(out ref int x);   //optional write-only variable

 'out ref int x' could then be legal..  Somehow reminds me of zlib's compress utility function that returns how many bytes the output buffer used but sometimes you didn't care. So.. if we defined and used...


void func(out ref int x) {
  x = 100;
}

int x;
func(x);
assert(x == 100);

func(0);    //0 and null (and legal) basically ignored.
func(null);

November 07, 2012
On Wednesday, 7 November 2012 at 01:15:27 UTC, martin wrote:
> I simply and utterly fail to comprehend the need for a compiler to distinguish between a const reference to a named variable and a const reference to an unnamed temporary/literal (which the compiler is free to allocate wherever it makes most sense).

Let me be more precise: I don't see why a called function would need to know whether a passed const reference is named or unnamed at the caller's site. The developer's reasoning for a const reference is simply to avoid costly copying of the argument to be passed (only applicable for lvalues) which is guaranteed not to be modified by the callee. Decorating such a parameter with 'const ref' seems as logical as it gets (don't pass me a copy of the real thing, pass me a reference instead - I'm not going to modify it).
The only reason I can think of to distinguish between lvalues and rvalues at the callee is the slight performance hit due to pointer indirection for rvalues. And that would be addressable by preferring by-value-passing of rvalues when selecting between function overloads.
November 07, 2012
On Tuesday, 6 November 2012 at 23:37:25 UTC, martin wrote:
>
> void func(T)(in auto ref T m);
>
> This template, as I understand it, gets expanded to:
>
> void func(T)(in ref T m); // for lvalues
> void func(T)(in T m);     // for rvalues
>
> So for non-templated functions, I suggest 2 options:
>
> 1) The previously described auto-templates (identical 'auto ref' semantics), where a function with 'auto ref' parameters is treated as implicit template. This may lead to code-bloating (for larger functions) and/or higher performance for rvalue arguments (rvalues passed to value arguments are moved, not copied; we therefore gain nothing by passing a reference, but incur a slight performance hit due to pointer indirection instead of accessing directly the rvalue on the stack). OR
> 2) Simple under-the-hood temporary lvalue declaration by the compiler (for rvalues passed to 'const ref' parameters) - that would be a handy implementation of the first workaround.
>
> I hope you get my point. :)

What about the case where we want to pass a source argument either by reference or as a copy depending on the l/r value situation?

eg
void f( ref a );
void f( a );

--rt

November 07, 2012
On Wednesday, 7 November 2012 at 01:33:49 UTC, Jonathan M Davis wrote:
> The most recent discussion where Walter and Andrei were part of the discussion
> was here:
>
> http://forum.dlang.org/post/4F84D6DD.5090405@digitalmars.com

That thread is quite misleading and, I'm sad to say, not very useful (rather damaging to this discussion) in my opinion - especially because the distinction between rvalue => 'const ref' and rvalue => ref is largely neglected, and that distinction is of extremely high importance, I can't stress that enough. Walter's 3 C++ examples (2 of them invalid anyway afaik) don't relate to _const_ references. The implicit type conversion problem in that thread isn't a problem for _const_ references, just to point out one tiny aspect.
rvalue => ref/out propagation makes no sense imho, as does treating literals as lvalues (proposed by Walter iirc). The current 'auto ref' semantics also fail to cover the special role of _const_ references for rvalues (also illustrated by Scarecrow's post).

> Certainly, it's not a simple matter of just making const
> ref work with rvalues like most of the people coming from
> C++ want and expect.

Well I absolutely do _not_ share this point of view. It just seems so logical to me. I'm still waiting for a plausible argument to prove me wrong. All the required info is in this thread, e.g., we covered the escaping issue you mentioned.
November 07, 2012
On Wednesday, 7 November 2012 at 02:06:09 UTC, Rob T wrote:
> What about the case where we want to pass a source argument either by reference or as a copy depending on the l/r value situation?
>
> eg
> void f( ref a );
> void f( a );
>
> --rt

I don't get what you mean - that's why the 2 overloads are for (you forgot the const/in keyword - beware! :))

void f( in ref T a );
void f( in T a );

rvalue binds to the latter overload (argument not copied, but moved directly).
lvalue binds to the first overload (reference).
Works with v2.060.
November 07, 2012
On Tuesday, 6 November 2012 at 23:37:25 UTC, martin wrote:
> 1) The previously described auto-templates (identical 'auto ref' semantics), where a function with 'auto ref' parameters is treated as implicit template. This may lead to code-bloating (for larger functions) and/or higher performance for rvalue arguments (rvalues passed to value arguments are moved, not copied; we therefore gain nothing by passing a reference, but incur a slight performance hit due to pointer indirection instead of accessing directly the rvalue on the stack). OR
> 2) Simple under-the-hood temporary lvalue declaration by the compiler (for rvalues passed to 'const ref' parameters) - that would be a handy implementation of the first workaround.

Please discard option 1, I'm afraid it creates too much confusion and was not well thought through. The objective was to expand 'auto ref T' to either 'in ref T' for lvalues or 'in T' for rvalues (i.e., only for const parameters!), but then its caption would be horribly misleading (and something like 'in auto ref' would be way too ambiguous).

November 07, 2012
On Wednesday, 7 November 2012 at 02:45:15 UTC, martin wrote:
> Please discard option 1, I'm afraid it creates too much confusion and was not well thought through. The objective was to expand 'auto ref T' to either 'in ref T' for lvalues or 'in T' for rvalues (I.e., only for const parameters!), but then its caption would be horribly misleading (and something like 'in auto ref' would be way too ambiguous).


 Maybe a very simple change/addition; Like perhaps @ref? (Attribute ref, Alternate ref, auto ref.. All sorta fit for it's meaning).

 So...

 void func1(ref int x);  //D lvalue-only ref
 void func2(@ref int x); //works like c++'s ref

 Seems fairly easy to tell apart, and still leaves const-ness as an option.
November 07, 2012
On Wednesday, 7 November 2012 at 02:58:57 UTC, Era Scarecrow wrote:
> Maybe a very simple change/addition; Like perhaps @ref? (Attribute ref, Alternate ref, auto ref.. All sorta fit for it's meaning).
>
> So...
>
> void func1(ref int x);  //D lvalue-only ref
> void func2(@ref int x); //works like c++'s ref
>
> Seems fairly easy to tell apart, and still leaves const-ness as an option.

Afaik C++ doesn't allow rvalues to be passed to _mutable_ references (T&), only to const references, making perfect sense imo. I really do not see the point for an additional syntax for C++-like const references (const T&) which would also take rvalues.
Please give me an example where you want to pass an rvalue to a _mutable_ reference parameter. I would simply continue to disallow that, since that would mean that changes to the referenced rvalue would not be visible for the caller (a temporary/literal is changed - how could someone possibly want that?).