www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - [ref variables] Allow `auto ref`

reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
In particular in generic code, `auto ref` variables that infer 
`ref` if and only if the initializer is an lvalue could be quite 
valuable. The same is true for `foreach` over ranges, where the 
foreach variable would infer `ref` if `front` is an lvalue (be it 
a variable or a function that returns by reference) and lastly, 
for conditions, `if (auto ref x = f())` could infer `ref` from 
the value category of the initializer, like any other variable.

In my opinion, this is an obvious no-brainer because generic code 
can’t know if a type is expensive to copy or even copyable, and 
taking lvalues by reference and rvalues by value is the obvious 
right way.

In contrast to function parameters, `auto ref` for local 
variables, foreach variables, and if condition variables requires 
no template context and could be a way for a programmer to 
express: Just store the value, don’t (needlessly) copy it, 
similar to C++’s `auto&&`, which, too, works for local variables, 
loop variables, etc. and not only function template parameters.

The same way `__traits(isRef)` works for `auto ref` function 
template parameters, it should work for local variables, too.
Jul 29
next sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Monday, 29 July 2024 at 15:26:39 UTC, Quirin Schroll wrote:
 In particular in generic code, `auto ref` variables that infer 
 `ref` if and only if the initializer is an lvalue could be 
 quite valuable. The same is true for `foreach` over ranges, 
 where the foreach variable would infer `ref` if `front` is an 
 lvalue (be it a variable or a function that returns by 
 reference) and lastly, for conditions, `if (auto ref x = f())` 
 could infer `ref` from the value category of the initializer, 
 like any other variable.
This makes a lot of sense. I’d also love it if `auto ref` worked inside all templates, not just template functions. Often I want to do this: ```d struct S(T){ this(auto ref T x){} } ``` But I’d get an error: ```d S!long x; //Error: cannot explicitly instantiate template function with `auto ref` parameter ``` If I make `this` a template function it works. For template functions, even explicit instantiation works just fine. This requirement feels rather silly and leads to a lot of unnecessary parameter-less templates.
Jul 29
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 7/30/24 07:43, IchorDev wrote:
 I’d also love it if `auto ref` worked inside all templates, not just 
 template functions. Often I want to do this:
 ```d
 struct S(T){
    this(auto ref T x){}
 }
 ```
 But I’d get an error:
 ```d
 S!long x; //Error: cannot explicitly instantiate template function with 
 `auto ref` parameter
 ```
 If I make `this` a template function it works. For template functions, 
 even explicit instantiation works just fine. This requirement feels 
 rather silly and leads to a lot of unnecessary parameter-less templates.
Well, the `ref` and non-`ref` version of the function are two distinct instantiations of the function, while when instantiating `S` I would only expect to get one instance of the constructor. I guess your proposal would be that all combinations of ref-ness of the constructor parameters are automatically expanded as soon as `S` is instantiated? Why does this need a template at all?
Jul 30
parent swigy food <hamza1r3g3h gmail.com> writes:
Hello
The ref and non-ref versions are distinct because they handle 
parameters differently. Expanding all combinations of ref 
parameters automatically when instantiating S would indeed 
simplify usage but requires templates to handle these variations 
efficiently.
Jul 30
prev sibling parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Tuesday, 30 July 2024 at 05:43:24 UTC, IchorDev wrote:
 On Monday, 29 July 2024 at 15:26:39 UTC, Quirin Schroll wrote:
 In particular in generic code, `auto ref` variables that infer 
 `ref` if and only if the initializer is an lvalue could be 
 quite valuable. The same is true for `foreach` over ranges, 
 where the foreach variable would infer `ref` if `front` is an 
 lvalue (be it a variable or a function that returns by 
 reference) and lastly, for conditions, `if (auto ref x = f())` 
 could infer `ref` from the value category of the initializer, 
 like any other variable.
This makes a lot of sense. I’d also love it if `auto ref` worked inside all templates, not just template functions. Often I want to do this: ```d struct S(T){ this(auto ref T x){} } ``` But I’d get an error: ```d S!long x; //Error: cannot explicitly instantiate template function with `auto ref` parameter ``` If I make `this` a template function it works. For template functions, even explicit instantiation works just fine. This requirement feels rather silly and leads to a lot of unnecessary parameter-less templates.
By virtue of how `auto ref` works (and is expected to work), this doesn't make sense. It determines if the parameter is `ref` from the argument passed to the function at IFTI. You can't have IFTI if your function isn't a template. I can only guess what you actually want and it might be what I proposed in one of the *DIP Ideas* forum, which I called ` universal ref`. It does not infer anything from the argument, but binds lvalues normally by reference and materializes rvalues at the caller side and passes them by reference as well.
Jul 30
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 7/29/24 17:26, Quirin Schroll wrote:
 In my opinion, this is an obvious no-brainer
+1.
Jul 30
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
Sounds reasonable
Jul 31
parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Wednesday, 31 July 2024 at 19:38:23 UTC, Walter Bright wrote:
 Sounds reasonable
Should the spec be updated, then, to reflect what ought to be? Possibly with a not that it’s not implemented yet…
Jul 31