In the standard D library it seems missing a function to modify tuple modifiers.
Consider the following:
alias t = AliasSeq!(int, float); // create tuple (int, float) of two types
alias tc = addTupleModifiers!("const shared", t);
static assert(is(tc[1] == const shared float)); // check that "const shared" was added to the second element of the tuple
Here addTupleModifiers
is a template that adds modifiers (in this example “const shared”) to each element of a tuple. (So tc
becomes a tuple (const shared int, const shared float)
.)
Note that in D adding an already present tuple modifier is a no-op. So if it were:
alias t = AliasSeq!(int, const float);
the result would be the same.
Also note that if we write instead:
alias tc = const shared(t);
this does not work in DMD v2.085.1, it does not work (without any error messages const shared
is not added). Not sure if this is a compiler bug. I’ve reported it.
Now I will show my implementation of addTupleModifiers
:
template addTupleModifiers(string modifiers, T...) {
private template addModifier(T1) {
mixin("alias addModifier = " ~ modifiers ~ " T1;");
}
alias addTupleModifiers = staticMap!(addModifier, T);
}
This implementation uses a string mixin (a construct which creates code from a string calculated at compile time) to create the template addModifier
(eponymous template, what in this case means that addModifier.addModifier
can be shortened to just addModifier
, because the member has the same name as this tempalte) and the template std.meta.staticMap
from the standard library to apply the template addModifier
to each element of the tuple.
Also note that it uses the construct T...
(a variadic template) to provide an arbitrary number of types as arguments to our template.
The above code is present in my short library tuple-modifiers
(which you can install with DUB, see also https://github.com/vporton/tuple-modifiers-dlang) under the Apache 2.0 license.
One possible usage of this template is to create a function g()
having the same arguments as function f()
but with const
added to every argument (this is useful mostly in templates, especially ones with variadic arguments):
import std.traits;
string f(int x, float y) { return "xxx"; }
ReturnType!f g(addTupleModifiers!("const", Parameters!f) args) { return f(args); }
Here they are used the templates ReturnType
and Parameters
from std.meta
which return correspondingly the return type and parameters types tuple for a function.