On Thursday, 9 May 2019 at 09:52:21 UTC, XavierAP wrote:
What are the benefits of alias parameters, compared to
specifying the template parameters fully?
https://dlang.org/spec/template.html#aliasparameters
In most examples, at places in Phobos, and in Andrei's and
Ali’s books, alias parameters are used for functions (in the
general sense). Why this instead of specifying and typing the
parameter functions or delegates?
Genericity, for one. This code will work with functions,
delegates, templated functions, lambdas, and functors:
void call(alias fun)() {
fun();
}
This brings another question, why is it so widespread in Phobos
etc. to template these function parameters instead of declaring
them as run-time parameters? Is this really always considered
beneficial, why?
The compiler can optimize calls to compile-time parameters, but
not run-time parameters. Also, as said above, alias parameters
support a greater variety of types. If instead run-time
parameters were used there'd have to be multiple overloads, or a
templated function that accepts all the different callables.
For one it looks like it saves a lot of typing and makes the
whole declaration more readable (not to mention possible
attribute soups); but the type-checking code just moves to
additional template constraints.
The type checking tends to be a lot looser though - more along
the lines of 'Can I call f with these parameters?', rather than
'Is f a function taking two ints and a string, returning a bool,
and adorned with @safe and @nogc?'. There are tradeoffs there, of
course, and you should use whichever is more correct for your use
case.
And finally what’s the advantage of alias parameters in
general, besides function/delegates? But I don’t see other uses
in practice, although they’re possible.
Templates can be passed in alias parameters. This is used quite
extensively in std.meta. In fact, alias parameters accept
anything* with a name. This makes it easy to build templates that
operate on any type or scope (e.g. a module) with the exact same
code, and passing them from one template to the other without
having to rewrite them to operate on specific types of objects.
Another use case is to pass a value of an unknown type. Without
alias parameters, you'd have to pass the type as well, something
like foo!(int, 3) instead of foo!3, or use a template sequence
parameter and a template constraint:
template foo(Value...) if (Value.length == 1) {}
This is clearly untenable for more than a single such parameter.
In my own code, I've almost exclusively used alias parameters for
templates, with functions being the second most common, and one
or two examples of the module/types mentioned above.
* except built-in primitive types
--
Simen