DIP 1016--ref T accepts r-values--Final Review

Steven Schveighoffer schveiguy at gmail.com
Mon Nov 19 15:23:14 UTC 2018


On 11/18/18 10:55 AM, Rubn wrote:
> On Saturday, 17 November 2018 at 14:49:26 UTC, kinke wrote:
>> On Saturday, 17 November 2018 at 13:01:12 UTC, Rubn wrote:
>>> For this what about if there are multiple parameters? How many 
>>> overloads do you have to define to get this behavior?
>>
>> I'd assume a single one. It should be analogous to this:
>>
>> ```
>> void lval_only(uint x, short y) @disable;
>> void lval_only(int x, int y);
>>
>> void main()
>> {
>>     byte y = 1;
>>     lval_only(100_000, y);
>> }
>> ```
>>
>> The disabled function is preferred, so this doesn't compile. As 
>> by-value params are to be preferred for rvalue args in overload 
>> resolution, the single overload should do in your example.
>>
>> ---
>>
>> I'm a huge fan of this DIP and have been wanting this in the language 
>> literally since the day I wrote my first D code, immediately stumbling 
>> into this limitation (but fortunately not losing much interest due to 
>> numerous advantages and syntax loveliness).
> 
> If that's the case then it'll look something like this, for just 3 
> parameters if you want the old behavior:
> 
>      void lval_only(int x, int y, int z) @disable;
>      void lval_only(int x, int y, ref int z) @disable;
>      void lval_only(int x, ref int y, ref int z) @disable;
>      void lval_only(ref int x, int y, ref int z) @disable;
>      void lval_only(ref int x, ref int y, int z) @disable;
>      void lval_only(int x, ref int y, int z) @disable;
>      void lval_only(ref int x, int y, ref int z) @disable;
> 
>      void lval_only(ref int x, ref int y, ref int z);
> 
> Not really ideal, I might be missing one, hard to tell.
> 

We can reduce to linear growth using auto ref:

void lval_only()(int x, auto ref int y, auto ref int z) @disable
void lval_only()(ref int, int, auto ref int) @disable
void lval_only(ref int, ref int, int) @disable

Still not ideal though. I tried auto ref for all 3, but that means it 
will match both the template and the real function.

I tried using a constraint, but not sure how to get the parameter 
ref-ness in a neat way inside the constraint. This does work:

void lval_only()(auto ref int x, auto ref int y, auto ref int z) 
@disable if (!__traits(isRef, x) || !__traits(isRef, y) || 
!__traits(isRef, z))

But it is a bit ugly.

Another option is to use a variadic template, verify the parameters 
match the lvalue version, and then use some testing on the parameter 
tuple. Or use a mixin based on the original function.

Probably the mixin could work something like:

mixin(disableNonRef!lval_only);

-Steve


More information about the Digitalmars-d mailing list