Const ref and rvalues again...

Era Scarecrow rtcvb32 at yahoo.com
Tue Nov 6 20:36:58 PST 2012


On Wednesday, 7 November 2012 at 04:05:32 UTC, martin wrote:
> int func(in ref int x);
> int func(int x) { return func(x); }
>
> The latter overload is for rvalues (no need to cast to const) 
> and wouldn't be required if the first one took rvalues directly 
> (having a _const_ ref parameter). That's not an example for 
> mutable references though, it's basically a shortcut so as to 
> not having to declare all rvalues for x manually.

  Maybe... But when working with non built-in types can you 
guarantee that behavior?

//same as 'const ref' basically, unless 'in ref' is accepted
struct S
//int func(in ref S x); //?
int func(const ref S x);
int func(S x) { return func(x); } //potentially infinitely self 
calling

>> compress(output, input, null);
>> compress(output2, input, state);
>
> Where's the rvalue? You're talking about an optional mutable 
> reference here, which is only doable via a pointer (references 
> cannot be null, not in C++ and not in D):

  Perhaps null is wrong in this case, but had it been Zlib.init or 
Zlib(), then it would still be applicable. Since it's a reference 
I would think it could accept a null pointer and realize to 
create a temporary which has it's default values.

> That would be correct. But you're completely missing the point 
> here. Let's assume you wanted to require a state to be passed:
>
> ZlibEnum compress(void[] output, void[] input, ref Zlib state);
>
> You could now use:
>
> Zlib state; // lvalue
> compress(output, input, state);
>
> but not:
>
> compress(output, input, Zlib()); // rvalue
>
> And that is most likely a good thing, since your state would be 
> lost after the compress() call. If you don't want it, you don't 
> pass it, and as I said, the only way to do that is to pass a 
> nullable pointer. So this is off-topic I'm afraid.

  True, but rather than having to create a temporary you don't 
plan on using just to satisfy the signature, and you know you 
don't NEED it afterwards, why do you have to go through the extra 
steps? How many wrappers are made in general just to work around 
minor issues like this?

  Quite often we ignore return types if they aren't interesting, 
but we can't ignore a rvalue we only need for one call (or just 
to satisfy the signature)? Say we have a divide function (who 
knows what for), and this is more efficient than normal. So...

  //perhaps '@ref int remainder = 0'?
  int divide(int number, int divisor, ref int remainder);

  Now in this case what if we don't care about the remainder? 
Create a temporary (or a wrapper function)?

  //satisfy remainder
  int divide(int number, int divisor) {
    int tmp; return divide(number, divisor, tmp);
  }

  int modulus(int number, int divisor) {
    int tmp; divide(number, divisor, tmp);
    return tmp;
  }

  But if we want the result of the division AND the remainder 
should we have to make a separate modulus function when the 
original divide can clearly give you the answer? This cuts closer 
to the instruction set as an example.


More information about the Digitalmars-d mailing list