www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - const ref rvalues

reply dsimcha <dsimcha yahoo.com> writes:
I mentioned this deep in another thread, but I think it deserves its own
thread.  Can we get something like:

void doStuff(T)(const ref T val) {
    // do stuff.
}

T getVal() {
    return someValue;
}

void main() {
    doStuff(getVal());  // Doesn't currently work.
}

For non-const ref parameters, it's understandable that passing rvalues in
doesn't work because this is likely a bug that the compiler should catch.
However, for const ref parameters, can't the compiler just implicitly put the
value on the caller's stack frame and convert it to an lvalue rather than
forcing the programmer to write the boilerplate to do this manually?  This
would result in:

doStuff(getVal()); -->

auto __temp = getVal();
doStuff(__temp);
Dec 14 2009
next sibling parent reply Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
dsimcha Wrote:

 I mentioned this deep in another thread, but I think it deserves its own
 thread.  Can we get something like:
 
 void doStuff(T)(const ref T val) {
     // do stuff.
 }
 
 T getVal() {
     return someValue;
 }
 
 void main() {
     doStuff(getVal());  // Doesn't currently work.
 }
 
 For non-const ref parameters, it's understandable that passing rvalues in
 doesn't work because this is likely a bug that the compiler should catch.
 However, for const ref parameters, can't the compiler just implicitly put the
 value on the caller's stack frame and convert it to an lvalue rather than
 forcing the programmer to write the boilerplate to do this manually?  This
 would result in:
 
 doStuff(getVal()); -->
 
 auto __temp = getVal();
 doStuff(__temp);

My vote for it.
Dec 14 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Eldar Insafutdinov wrote:
 dsimcha Wrote:
 
 I mentioned this deep in another thread, but I think it deserves its own
 thread.  Can we get something like:

 void doStuff(T)(const ref T val) {
     // do stuff.
 }

 T getVal() {
     return someValue;
 }

 void main() {
     doStuff(getVal());  // Doesn't currently work.
 }

 For non-const ref parameters, it's understandable that passing rvalues in
 doesn't work because this is likely a bug that the compiler should catch.
 However, for const ref parameters, can't the compiler just implicitly put the
 value on the caller's stack frame and convert it to an lvalue rather than
 forcing the programmer to write the boilerplate to do this manually?  This
 would result in:

 doStuff(getVal()); -->

 auto __temp = getVal();
 doStuff(__temp);

My vote for it.

Binding rvalues to const references was probably the single most hurtful design decisions for C++. I don't have time to explain now, but in short I think all of the problems that were addressed by rvalue references, and most of the aggravation within the design of rvalue references, are owed by that one particular conversion. If we ever allow automatic conversion of an rvalue to a ref, we should know very well what we're doing. Andrei
Dec 14 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Denis Koroskin wrote:
 On Mon, 14 Dec 2009 22:15:06 +0300, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Eldar Insafutdinov wrote:
 dsimcha Wrote:

 I mentioned this deep in another thread, but I think it deserves its 
 own
 thread.  Can we get something like:

 void doStuff(T)(const ref T val) {
     // do stuff.
 }

 T getVal() {
     return someValue;
 }

 void main() {
     doStuff(getVal());  // Doesn't currently work.
 }

 For non-const ref parameters, it's understandable that passing 
 rvalues in
 doesn't work because this is likely a bug that the compiler should 
 catch.
 However, for const ref parameters, can't the compiler just 
 implicitly put the
 value on the caller's stack frame and convert it to an lvalue rather 
 than
 forcing the programmer to write the boilerplate to do this 
 manually?  This
 would result in:

 doStuff(getVal()); -->

 auto __temp = getVal();
 doStuff(__temp);


Binding rvalues to const references was probably the single most hurtful design decisions for C++. I don't have time to explain now, but in short I think all of the problems that were addressed by rvalue references, and most of the aggravation within the design of rvalue references, are owed by that one particular conversion. If we ever allow automatic conversion of an rvalue to a ref, we should know very well what we're doing. Andrei

What about allowing binding rvalue to final ref const(T) (final would mean tail-const and wouldn't allow taking address of that variable)? Wouldn't that allow the feature while side-stepping all the issues?

It might (though I personally think not), but it would complicate the language. My opinion: if a function wants a ref, give it a ref. Andrei
Dec 14 2009
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 14 Dec 2009 22:15:06 +0300, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Eldar Insafutdinov wrote:
 dsimcha Wrote:

 I mentioned this deep in another thread, but I think it deserves its  
 own
 thread.  Can we get something like:

 void doStuff(T)(const ref T val) {
     // do stuff.
 }

 T getVal() {
     return someValue;
 }

 void main() {
     doStuff(getVal());  // Doesn't currently work.
 }

 For non-const ref parameters, it's understandable that passing rvalues  
 in
 doesn't work because this is likely a bug that the compiler should  
 catch.
 However, for const ref parameters, can't the compiler just implicitly  
 put the
 value on the caller's stack frame and convert it to an lvalue rather  
 than
 forcing the programmer to write the boilerplate to do this manually?   
 This
 would result in:

 doStuff(getVal()); -->

 auto __temp = getVal();
 doStuff(__temp);


Binding rvalues to const references was probably the single most hurtful design decisions for C++. I don't have time to explain now, but in short I think all of the problems that were addressed by rvalue references, and most of the aggravation within the design of rvalue references, are owed by that one particular conversion. If we ever allow automatic conversion of an rvalue to a ref, we should know very well what we're doing. Andrei

What about allowing binding rvalue to final ref const(T) (final would mean tail-const and wouldn't allow taking address of that variable)? Wouldn't that allow the feature while side-stepping all the issues?
Dec 14 2009
prev sibling next sibling parent reply Jason House <jason.james.house gmail.com> writes:
dsimcha Wrote:

 I mentioned this deep in another thread, but I think it deserves its own
 thread.  Can we get something like:
 
 void doStuff(T)(const ref T val) {
     // do stuff.
 }
 
 T getVal() {
     return someValue;
 }
 
 void main() {
     doStuff(getVal());  // Doesn't currently work.
 }
 
 For non-const ref parameters, it's understandable that passing rvalues in
 doesn't work because this is likely a bug that the compiler should catch.
 However, for const ref parameters, can't the compiler just implicitly put the
 value on the caller's stack frame and convert it to an lvalue rather than
 forcing the programmer to write the boilerplate to do this manually?  This
 would result in:
 
 doStuff(getVal()); -->
 
 auto __temp = getVal();
 doStuff(__temp);

If T is a class, I agree it should work. If T is a struct, you'll need a stronger argument. Maybe scope const ref T would make sense. IMHO, non- scope ref T for structs is already a questionable practice, and I don't mind the compiler making that scenario tougher for me.
Dec 14 2009
parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Jason House (jason.james.house gmail.com)'s article
 If T is a class, I agree it should work. If T is a struct, you'll need a

T for structs is already a questionable practice, and I don't mind the compiler making that scenario tougher for me. Since when does scope even have any meaning for structs?
Dec 14 2009
prev sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 14 Dec 2009 21:06:20 +0300, dsimcha <dsimcha yahoo.com> wrote:

 I mentioned this deep in another thread, but I think it deserves its own
 thread.  Can we get something like:

 void doStuff(T)(const ref T val) {
     // do stuff.
 }

 T getVal() {
     return someValue;
 }

 void main() {
     doStuff(getVal());  // Doesn't currently work.
 }

 For non-const ref parameters, it's understandable that passing rvalues in
 doesn't work because this is likely a bug that the compiler should catch.
 However, for const ref parameters, can't the compiler just implicitly  
 put the
 value on the caller's stack frame and convert it to an lvalue rather than
 forcing the programmer to write the boilerplate to do this manually?   
 This
 would result in:

 doStuff(getVal()); -->

 auto __temp = getVal();
 doStuff(__temp);

I agree it hurts a lot. I faced the same problem implementing RefCounted: you can't return RefCounted object from one function and pass it by reference to another one. Passing it by value is not a good option.
Dec 14 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Denis Koroskin wrote:
 On Mon, 14 Dec 2009 21:06:20 +0300, dsimcha <dsimcha yahoo.com> wrote:
 
 I mentioned this deep in another thread, but I think it deserves its own
 thread.  Can we get something like:

 void doStuff(T)(const ref T val) {
     // do stuff.
 }

 T getVal() {
     return someValue;
 }

 void main() {
     doStuff(getVal());  // Doesn't currently work.
 }

 For non-const ref parameters, it's understandable that passing rvalues in
 doesn't work because this is likely a bug that the compiler should catch.
 However, for const ref parameters, can't the compiler just implicitly 
 put the
 value on the caller's stack frame and convert it to an lvalue rather than
 forcing the programmer to write the boilerplate to do this manually?  
 This
 would result in:

 doStuff(getVal()); -->

 auto __temp = getVal();
 doStuff(__temp);

I agree it hurts a lot. I faced the same problem implementing RefCounted: you can't return RefCounted object from one function and pass it by reference to another one. Passing it by value is not a good option.

The compiler will optimize that case. Andrei
Dec 14 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Denis Koroskin wrote:
 On Mon, 14 Dec 2009 23:38:34 +0300, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Denis Koroskin wrote:
 On Mon, 14 Dec 2009 21:06:20 +0300, dsimcha <dsimcha yahoo.com> wrote:

 I mentioned this deep in another thread, but I think it deserves its 
 own
 thread.  Can we get something like:

 void doStuff(T)(const ref T val) {
     // do stuff.
 }

 T getVal() {
     return someValue;
 }

 void main() {
     doStuff(getVal());  // Doesn't currently work.
 }

 For non-const ref parameters, it's understandable that passing 
 rvalues in
 doesn't work because this is likely a bug that the compiler should 
 catch.
 However, for const ref parameters, can't the compiler just 
 implicitly put the
 value on the caller's stack frame and convert it to an lvalue rather 
 than
 forcing the programmer to write the boilerplate to do this 
 manually?  This
 would result in:

 doStuff(getVal()); -->

 auto __temp = getVal();
 doStuff(__temp);

RefCounted: you can't return RefCounted object from one function and pass it by reference to another one. Passing it by value is not a good option.

The compiler will optimize that case. Andrei

How can it optimize away a function with a side effect (RefCounted ctor/dtor invokes an interlocked increment/decrement that theoretically may destroy an object, but wouldn't in practice)? Make it special for compiler?

The compiler can optimize away all copies followed by the destruction of the source. It suffices to just move memory. Andrei
Dec 14 2009
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 14 Dec 2009 23:38:34 +0300, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Denis Koroskin wrote:
 On Mon, 14 Dec 2009 21:06:20 +0300, dsimcha <dsimcha yahoo.com> wrote:

 I mentioned this deep in another thread, but I think it deserves its  
 own
 thread.  Can we get something like:

 void doStuff(T)(const ref T val) {
     // do stuff.
 }

 T getVal() {
     return someValue;
 }

 void main() {
     doStuff(getVal());  // Doesn't currently work.
 }

 For non-const ref parameters, it's understandable that passing rvalues  
 in
 doesn't work because this is likely a bug that the compiler should  
 catch.
 However, for const ref parameters, can't the compiler just implicitly  
 put the
 value on the caller's stack frame and convert it to an lvalue rather  
 than
 forcing the programmer to write the boilerplate to do this manually?   
 This
 would result in:

 doStuff(getVal()); -->

 auto __temp = getVal();
 doStuff(__temp);

RefCounted: you can't return RefCounted object from one function and pass it by reference to another one. Passing it by value is not a good option.

The compiler will optimize that case. Andrei

How can it optimize away a function with a side effect (RefCounted ctor/dtor invokes an interlocked increment/decrement that theoretically may destroy an object, but wouldn't in practice)? Make it special for compiler?
Dec 14 2009