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