digitalmars.D - [ref variables] Allow `auto ref`
- Quirin Schroll (19/19) Jul 29 In particular in generic code, `auto ref` variables that infer
- IchorDev (18/26) Jul 29 This makes a lot of sense. I’d also love it if `auto ref` worked
- Timon Gehr (7/22) Jul 30 Well, the `ref` and non-`ref` version of the function are two distinct
- swigy food (6/6) Jul 30 Hello
- Quirin Schroll (10/36) Jul 30 By virtue of how `auto ref` works (and is expected to work), this
- Timon Gehr (2/3) Jul 30 +1.
- Walter Bright (1/1) Jul 31 Sounds reasonable
- Quirin Schroll (3/4) Jul 31 Should the spec be updated, then, to reflect what ought to be?
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
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
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
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
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: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.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 30
On 7/29/24 17:26, Quirin Schroll wrote:In my opinion, this is an obvious no-brainer+1.
Jul 30
On Wednesday, 31 July 2024 at 19:38:23 UTC, Walter Bright wrote:Sounds reasonableShould the spec be updated, then, to reflect what ought to be? Possibly with a not that it’s not implemented yet…
Jul 31