On 9/13/20 2:35 PM, Paul Backus wrote:
On Sunday, 13 September 2020 at 17:23:42 UTC, Steven Schveighoffer wrote:
On 9/13/20 12:55 PM, James Blachly wrote:
```
/// 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));
}
```
Interestingly, compilation fails if the mixin consists only of the
comma-separated parameters ("Comma expression" [1])
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?
Was just talking about this exact problem with Adam Ruppe.
Unfortunately, because the parameters are an expression tuple, and not
a compile-time tuple, you can't use stuff like staticMap.
You actually can, if you define the right kind of helper function:
/// 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
immtuable(char)* argToStringz(alias arg)()
{
return toStringz(arg);
}
return sam_hdr_add_line(this.h, this.ptr,
staticMap!(argToStringz, kvargs), null);
}
The clever trick here is that, because of optional parentheses [1],
`argToStringz!(kvargs[i])` can be interpreted either as the name of a
function or a function call, depending on the context it appears in.
That's cool. And horrific at the same time :) I mean the templates that
you have to instantiate for this...
I would prefer the mixin solution, even though it's uglier. I think
something that abstracts that out would be a nice thing to have for
std.meta.
-Steve