Yes, because tuple.expand is directly the expression tuple stored inside Tuple!(...)
When you have a typetuple in a template, like this:
template List(T...)
{
}
The T... part is a typetuple: an array of types, if you wish. You can get its length, index it, slice it, iterate on it, etc.
You can have a variable with this strange 'type' and also get its length, etc.
template List(T...)
{
T t;
}
t is an expression tuple. std.typecons.Tuple is nothing more than the preceding List!(...), with a few more functionalities.
So, something interesting is that when you do tup.expand, you obtain a bunch of values of different types, all perfectly individually typed and usable. You can get one by indexing, slice it, etc.
So, given your new f, you can even do:
auto tup = tuple(42, 3.14);
f(tup.expand[0], 1, tup.expand[1]);
Though in this particular case, it's cleaner to do:
f(tup[0], 1, tup[1]);