```
/// Add a single line to an existing header
auto addLine(T...)(RecordType type, T kvargs)
if(kvargs.length > 0 && isSomeString!(T[0]))
{
static assert (kvargs.length %2 == 0); // K-V pairs => even
number of variadic args
string varargMagic(size_t len)
{
string args = "sam_hdr_add_line(this.h, type.ptr, ";
for(int i=0; i<len; i++)
args ~= "toStringz(kvargs[" ~ i.to!string ~ "]), ";
args ~= "null)";
return args;
}
return mixin(varargMagic(kvargs.length));
}
```
[...]
Question:
If a variadic template, despite presenting to the user a "dynamic
array", MUST know its parameter list at compile-time, is there a way
(other than with mixins as shown) to pass this parameter list to
extern(C) linkage function with variadic parameters?
Easy peasy:
import std.meta: Repeat;
Repeat!(kvargs.length, const(char)*) zs;
foreach (i, ref z; zs) z = toStringz(kvargs[i]);
return sam_hdr_add_line(this.h, type.ptr, zs, null);
By the way, `kvargs` is not a dynamic array. Its length is not dynamic,
and it's not an array.
Also, you don't just want to pass the parameters forward. That would be
trivial: `sam_hdr_add_line(this.h, type.ptr, kvargs, null)`. You want to
run them through another function first. That's where the difficulty
comes from.
(bonus question: if yes, can it be done with typesafe variadic function
where I believe parameter list is known at either compile time OR
runtime, depending on how called)
I don't see when it would matter how the function is called, but you can
declare it in two different ways:
1) True typesafe variadic:
auto addLine(RecordType type, string[] kvargs ...)
2) Template + typesafe variadic:
auto addLine(size_t n)(RecordType type, string[n] kvargs ...)
In the first one, `kvargs.length` is a dynamic value. You can't use it
to generate the arguments for a `sam_hdr_add_line` call.
In the second one, `kvargs.length` is a static value. So you can do the
same things as in the `T...` template. And just like the `T...`
template, it will generate a new function for every distinct
`kvargs.length`.