Thread overview
[ref variables] Allow `auto ref`
Jul 30
IchorDev
July 29

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.

July 30

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:

struct S(T){
  this(auto ref T x){}
}

But I’d get an error:

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.

July 30
On 7/29/24 17:26, Quirin Schroll wrote:
> In my opinion, this is an obvious no-brainer

+1.
July 30
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?
July 30

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:

struct S(T){
  this(auto ref T x){}
}

But I’d get an error:

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.

July 31
Sounds reasonable
July 31

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…