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.

Reply via email to