June 16
https://issues.dlang.org/show_bug.cgi?id=24611

          Issue ID: 24611
           Summary: Cannot explicitly instantiate template function with
                    `auto ref`
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: qs.il.paperinik@gmail.com

```d
void f(T)(auto ref T x) {}

void main()
{
    int x;
    f(x); // infers T = int, auto ref = ref
    f(0); // infers T = int, auto ref = Ø
    f!int(x); // same as first
    f!int(0); // same as second
    auto fp = &f!int; // Error: cannot explicitly instantiate template function
with `auto ref`
    alias f_int = f!int; // Error: cannot explicitly instantiate template
function with `auto ref`
}
```

The spec nowhere says that one can’t explicitly instantiate function templates with `auto ref` parameters.

I suggest we extend template type parameters and let them be bound not just to
a type, but also, optionally, a `ref`. Any template type parameter is
effectively a bool–type pair where the bool says if `ref` was given as an
argument.
Supplying `ref` only makes a difference when the type parameter is used as a
function parameter type. In every other use, it is ignored. When a template
type parameter is `ref` and used as a function parameter type, that parameter
must be `auto ref`, otherwise it is an error. If it is an `auto ref` parameter,
it becomes `ref`. Explicit instantiations of function templates with `auto ref`
parameters become valid and if no `ref` is given for the template type
argument, the `auto ref` becomes pass-by-value.

As for IFTI, nothing changes. The `ref` as part of a template type argument
will be inferred even if the corresponding type of the bool–type pair is given.
(Unlike say in C++, where the information of being reference is part of the
type.)

Example:
```d
void f(T)(auto ref T x) {}

void main()
{
    int x;
    f(x); // infers T = ref int, therefore auto ref = ref
    f(0); // infers T = int, therefore auto ref = Ø
    f!int(x); // same as first, T = ref int, ref inferred
    f!int(0); // same as second, no ref inferred as argument is rvalue
    // nothing really changed up until here
    auto fp1 = &f!int; // Okay, T = int, pass-by-value
    auto fp2 = &f!(ref int); // T = ref int, pass-by-reference
    alias f_int = f!int; // Okay, T = int, pass-by-value
    alias f_ref_int = f!(ref int); // T = ref int, pass-by-reference
```

--