On Tuesday, 11 February 2014 at 14:47:31 UTC, Carl Sturtivant
wrote:
With a class you can do this:
class Data
{
string s;
this(string s)
{
this.s = s;
}
}
void f(Data x ...)
{
import std.stdio;
writeln(x.s);
}
void main()
{
f("hello"); //convert argument implicitly to type `data`.
}
See Typesafe Variadic Functions at
http://dlang.org/function.html
I don't know why you can't do it with a struct.
As a workaround, you can do this:
class Construct(T)
{
T t;
this(Q)(Q q)
{
static if(is(Q : T))
{
t = q;
}
else
{
this.t = T(q);
}
}
}
struct Data
{
string s;
}
void f(Construct!Data xC ...) //construct the wrapper class
{
auto x = xC.t; //get the contents.
import std.stdio;
writeln(x.s);
}
void main()
{
f("hello");
f(Data("world"));
}
Overall it's probably best to define f as:
void f(Data x)
{
import std.stdio;
writeln(x.s);
}
void f(Construct!Data xC ...)
{
.f(xC.t);
}
To avoid any overhead when calling normally as well as
separating the definition of the real function from the
concern of automatic construction/conversion.
Nice technique, I'll remember that. Presumably this can't be
extended to functions with more than one Data parameter.
You are correct, although you can of course just create a normal
D-style variadic function overload that does any conversions
necessary and then forwards to the original function, but you get
less of a helping hand from the language. In general it's harder
as you could have multiple constructors that take different
numbers of arguments. My example above should work for any number
of args, but if you restrict yourself to 1 to 1 conversions:
void g(A a, B b) {}
void g(TL ...)(TL args)
if(TL.length == 2)
{
//do conversions if possible and pass the converted args to
//g(A,B).
}
In all of this I haven't taken any care over ref-ness. In order
to get that correct you likely need to use auto ref and maybe
std.algorithm.forward, I haven't thought much about it.