rvalues -> ref (yup... again!)

Rubn where at is.this
Sat Mar 24 22:59:06 UTC 2018


On Saturday, 24 March 2018 at 11:57:25 UTC, John Colvin wrote:
> I understand what you want, but I'm struggling to understand 
> why it's such a huge deal.
>
> The reason you want to pass by reference is for performance, to 
> avoid copying the data at the call boundary.

It's pretty simple:

float foo() { ... }
ref float bar() { ... }

void someFunc(ref float);

someFunc(bar()); // ok

float temp = foo();
someFunc(temp); // Have to create a temporary anyways for the 
function to work
someFunc(foo()); // Compile error, need to use the hideous code 
above


So there really isn't any performance penalty cause if you want 
to call that function you are going to have to create a temporary 
variable anyways, but now you can't just call the function in one 
line. It requires multiple lines and a temporary variable name.

This becomes especially horrible for math libraries:

void someFunc(ref Vector3) { ... }

someFunc(a + b); // Can't do this

Vector3 temp = a + b;
someFunc(temp); // Have to do this

So there's no performance penalty for what he is requesting, but 
allows for a cleaner syntax to do the exact same thing.

> So there are 2 cases: an lvalue needs to be passed, or an 
> rvalue needs to be passed.
>
> 1. The address of the lvalue is passed.
>
> 2. The rvalue is copied to a local, then the address of that 
> local is passed.
>
> So in the rvalue case, you're not getting the performance 
> benefit of passing by reference, because you have to copy to a 
> local anyway.
>
> What I would do in D currently to get the same performance and 
> API:
>
> void foo(float[32] v) { foo(v); }
> void foo(ref float[32] v) { ... }
>
> or
>
> void foo()(auto ref float[32] v) { ... }
>
> What is so totally unacceptable about those solutions? I 
> personally like the second because it scales better to multiple 
> parameters. I know you have said it's not relevant and annoying 
> that people bring up auto ref, but I dont' get how or why. It's 
> exactly D's solution to the problem.

It doesn't scale better, that's part of the problem:

void foo()(auto ref MyType1, auto ref MyType2, auto ref MyType3, 
auto ref MyType4) { ... }

The above has the possibility of generating 16 different 
functions that basically all do the exact same thing. It creates 
excessive bloat, and now what if you want to take the address of 
the function? You can't cause you have to choose between one of 
the 16 variants.

This is template bloat at it's finest, except it isn't even doing 
anything useful. I can only imagine telling someone they have to 
code gen 16 identical functions just to be able to call a 
function without having to create useless temporary variables in 
the scope a function is being called in.



More information about the Digitalmars-d mailing list