void foo(T)(ref auto T v) { }
alias foo!int bar; // Error: auto can only be used for template function parameters
While I understand this may be 'correct' in some sense, it makes templates a lot more difficult to use.
Comment #1 by hsteoh — 2014-08-18T18:53:41Z
Still happens on git HEAD.
Comment #2 by dlang-bugzilla — 2017-07-18T12:34:27Z
(In reply to dlang+issues from comment #0)
> void foo(T)(ref auto T v) { }
> alias foo!int bar; // Error: auto can only be used for template function
> parameters
What is the expected type of "bar" here? The compiler can't know whether the instantiated function should take its parameter by ref or not, so I'm not sure whether this issue is valid. What is the expected behaviour?
As a workaround, you can move the type to a separate outer template using the eponymous template pattern:
template foo(T)
{
void foo()(auto ref T v) { }
}
alias foo!int bar;
Unfortunately, this breaks calling foo (as in `foo(5)`). The type will need to be indicated explicitly (e.g. `foo!int(5)`).
Comment #3 by simen.kjaras — 2019-06-06T11:17:00Z
It's perfectly possible to get aliases to overload sets in D, so that's what bar should be.
Comment #4 by dfj1esp02 — 2019-06-07T08:43:00Z
auto ref is IFTI, not an overload set though
Comment #5 by simen.kjaras — 2019-06-07T11:32:53Z
That was my point. Instead of resolving to a single instantiation of the template, we could instantiate all possible ref/non-ref permutations and alias bar to the resultant overload set. Of course, when I think a bit more about that, the number of possible instantiations may well be too damn high.
The correct solution here is to issue a better error message.
Comment #6 by simen.kjaras — 2020-08-17T06:30:27Z
We could argue that foo!int should alias to the non-ref version, and foo!(ref int) (or, in valid D, foo!(Parameters!((ref int){}))) give the ref version. So far, so good.
However, auto ref functions are a strange breed, and this is perfectly valid:
void fun()(auto ref int){}
In this case there's no template argument to carry the information about refness, so no explicit instantiation can be made. In some cases we can add extra parameters and simply extract the refness from those, so the definition as seen by the compiler is more like this:
void fun(__Hidden)(transferRefness!(__Hidden, int)) {}
This, however, breaks for variadic templates, so is also not a real solution. All in all, there's no provision in the language today for explicitly instantiating auto ref functions, and no obvious point to extend to give this ability. A solution to this issue will likely require a DIP.
Comment #7 by b2.temp — 2020-09-04T10:06:12Z
There are tricks to generate the ref version or not:
---
void foo(T)(ref auto T v)
{
pragma(msg,__PRETTY_FUNCTION__);
}
alias intByVal = typeof(foo(0));
alias intByRef = typeof(foo(*new int));
struct S{}
alias sByVal = typeof(foo(S()));
alias sByRef = typeof(foo(*new S()));
---
> void runnable.foo!int.foo(int v)
> void runnable.foo!int.foo(ref int v)
> void runnable.foo!(S).foo(S v)
> void runnable.foo!(S).foo(ref S v)
But the error message is not encouraging.
Comment #8 by b2.temp — 2020-09-04T10:18:04Z
ignore my previous comment. Obviously the `typeof()` dont instanciate the functions at all.
Comment #9 by b2.temp — 2022-04-27T18:03:02Z
why not just instantiate all possible permutations of by value / by ref in an overload set ?
Comment #10 by submada — 2022-04-28T10:58:35Z
This problem has become worst.
`auto ref` inference is no longer only problem. `scope` and `return` parameter storage classes inference has similar problem.
Example how inference differ from manual template instantion:
```d
void foo(T)(T* ptr){
}
ref T bar(T)(ref T val){
static if(is(T == long))
return *new T(val);
else
return val;
}
static long* global_ptr;
void main()@safe{
{
//void function(int* ptr) pure nothrow @nogc @safe:
pragma(msg, typeof(&foo!int));
//void function(int* ptr) pure nothrow @nogc @safe:
foo(new int);
}
{
//void function(int* ptr) pure nothrow @nogc @safe:
pragma(msg, typeof(&foo!int));
//void function(scope int* ptr) pure nothrow @nogc @safe:
scope int* i;
foo(i);
}
{
//int function(ref int val) pure nothrow @nogc ref @safe:
pragma(msg, typeof(&bar!int));
//int function(return ref int val) pure nothrow @nogc ref @safe:
scope int x;
scope int* ptr = &bar(x);
}
{
//long function(ref long val) pure nothrow ref @safe:
pragma(msg, typeof(&bar!long));
//long function(scope ref long val) pure nothrow ref @safe:
scope long x;
global_ptr = &bar(x);
}
}
```
Comment #11 by nick — 2022-07-27T14:26:05Z
*** Issue 9204 has been marked as a duplicate of this issue. ***
Comment #12 by robert.schadek — 2024-12-13T18:00:22Z