DIP proposal: Enum parameters

Quirin Schroll qs.il.paperinik at gmail.com
Mon Sep 26 11:00:50 UTC 2022


Sorry in advance for the long answer.

On Saturday, 24 September 2022 at 01:25:17 UTC, Nicholas Wilson 
wrote:
> Regarding Prior Art, this reminds me a lot of C++'s `auto` 
> function parameters that make the function a template function 
> without the need of the syntax overhead that comes with C++.

The key difference here is that C++ template syntax is verbose 
and `auto` is a syntax sugar.
I thought about having functions with `enum` parameters be 
templates implicitly. I decided against that. For one, it could 
be allowed later if deemed useful, for second, making a function 
a function template in D requires adding `()` between the name 
and the parameter list. I.e.
```d
void f(enum int i) { } // error, f is not a template
void g()(enum int i) { } // this is how it’s done
```

> It also reminds me of SPIR-V specialisation constants, which 
> serve a different purpose of late binding values for the 
> optimiser.

I know nothing about SPIR-V. If you don’t mind, you can explain 
it to me or send me a link to a description.

> Those are two incompatible meanings, and it is not entirely 
> clear which one the DIP wants to be. I think the best option 
> would be to have a static opSlice be something else and have 
> enum parameters be values that must resolve at compile time.

Do you mean that that they must resolve at compile-time and then 
be run-time values? That would throw away valuable information 
with virtually no gain.

> This DIP makes no mention of what one can do with an enum 
> parameter.

It does, three examples are provided: format, regex, static 
indexing. You can do with them whatever you can do with template 
value parameters.

> In particular it would be very useful to be able to use CTFE 
> with it, and do static assertions (e.g. check signatures of 
> format strings). and (not that I'm sure there is any easy way 
> to do it) being able to differentiate (and let the compiler 
> know, probably more of a problem for DMD) if the intention is 
> to reduce template bloat (in the case of format) or use the 
> value as a specialisation constant.

That is exactly the specified semantics. I thought about defining 
the feature in terms or rewrites. Those would make the proposal 
more understandable, but also constrain the implementation. Also, 
it would define things to be a certain way that could be depended 
upon.

Potential rewrite implementation examples for
```d
void f(T)(enum T x, T y) { /+impl+/ }
```

(A) Append the `enum` parameters to the template argument list 
(cf. C++ `auto` parameters).
```d
void f(T, T x)(T y) { /+impl+/ }
// which in turn is actually
template f(T, T x)
{
     void f(T y) { /+impl+/ }
}
```
```d
f(10, 20) // equivalently, 10.f(20)
// is actually
f!(int, 10)(20)
```

(B) Nested template
```d
template f(T)
{
     template f(T x)
     {
         void f(T y) { /+impl+/ }
     }
}
```
```d
f(10, 20)
// is actually
(f!int)!10(20) // note: syntactically invalid,
// i.e. in code, it must be:
Instantiate!(f!int, 10)(20)
```

I guess both have their upsides and downsides. I did not 
investigate this further. Again, it need not be a rewrite at all, 
and I don’t think it will be, unless someone has a great idea 
that has no weird semantics.

>> cf. a ref parameter only binds to lvalues
>
> This is not the case, for C++ interop reasons (among others) 
> `const ref` can bind rvalues.

I tried on run.dlang.io/nightly, this statement is wrong; `const 
ref` parameters cannot bind rvalues.
You can, however, use `in` instead of `const ref`. With 
[`-preview=in`](https://dlang.org/changelog/2.094.0.html#preview-in), [`in` on parameters of an `extern(C++)` function]((https://dlang.org/changelog/pending.html#previewInLink)) means what `const&` means in C++.
Example:
```d
extern(C++) void f(const ref int x) { }
extern(C++) void g(in int x) { }
void main()
{
     f(1); // error
     g(1); // good
}
```

[DIP 
1016](https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1016.md) wanted `ref` to be able to bind rvalues. It was rejected.


More information about the Digitalmars-d mailing list