UFCS functions with both pointers and refs

Q. Schroll qs.il.paperinik at gmail.com
Tue Dec 15 19:45:50 UTC 2020


On Sunday, 13 December 2020 at 19:02:34 UTC, Dave P. wrote:
> On Sunday, 13 December 2020 at 18:44:20 UTC, Mike Parker wrote:
>> On Sunday, 13 December 2020 at 18:31:54 UTC, Dave P. wrote:
>>> Do I have to write both and have one forward to the other for 
>>> more
>>> complicated functions?
>>
>> For free functions, yes.
>
> Is there any way to write the function as a template that is 
> generic over a parameter being a pointer or a reference, but 
> does not allow passing a copy?

I'm not sure what you mean by a reference. D doesn't have 
references in general, only class references that are just 
glorified pointers. There are also `ref` parameters, but those 
aren't generally referred to as "references" and are inside the 
function almost indiscernible from non-ref parameters. So, I'll 
ignore that.

Copying only takes place under one circumstance: When an lvalue 
is passed to a function that does not take that argument by 
`ref`. So one possibility is to just define that overload and 
@disable it. You don't even need a template for this:

     void f(    X x); // matches lvalues and rvalues
     void f(ref X x); // matches lvalues only

The latter is a better match than the former for lvalues. 
@disable'ing it will do the job. On the other hand, not 
@disable'ing it will make `f` work with any argument by moving 
rvalues to the former overload and referencing lvalues using the 
second one.

On templates, those can be unified by slapping `auto ref` before 
the parameter. You can also use `auto ref` (which infers `ref` 
from the passed argument) and check it with an `if` template 
constraint:

     void f(T)(auto ref T arg)
         if (!__tratis(isRef, arg)) // only accepts non-ref args
     { /* your code here */ }

The constraint can easily be flipped.


More information about the Digitalmars-d-learn mailing list