February 22, 2005
I ran into something unexpected today when dealing with variadic arguments. Basically, I get a different arguments passed to my function under different circumstances.

  Foo A  = new Foo(1,3,5);  // I get 3 args, all ints.

  Foo B += new Foo(1,3,5);  // I get 4 args, the first is 'TypeInfo'

I don't understand why a 'new' for a simple assignment is different from a 'new' in an opAddAssign.

I found a work around but its a bit of a kludge.

The source code to demonstrate this is a bit long, sorry about that.

<--------------- code ------------------->
import std.stdarg;
import std.stdio;

class Foo{
    static int baseid;
    int id;

    long[] Mem;

    this(...)
    {
        baseid++;
        id = baseid;
        for (int i = 0; i < _arguments.length; i++)
        {
            if (_arguments[i] is typeid(int))
            {
                Mem.length = Mem.length + 1;
                Mem[length-1] = cast(long)va_arg!(int)(_argptr);
            }
            else if (_arguments[i] is typeid(long))
            {
                Mem.length = Mem.length + 1;
                Mem[length-1] = va_arg!(long)(_argptr);
            }
            else
            {
                writefln(
                    "unknown data element '%s'"
                    " at position %d"
                    " length %d",
                    _arguments[i].toString,
                    std.string.toString(i),
                    std.string.toString(_arguments[i].tsize())
                    );

                // Skip over the bad data.
                if (_arguments[i].tsize() == 0)
                    _argptr += 8;  // Why is size 0 but I have to add 8?
                else
                    _argptr +=
                    ((_arguments[i].tsize() +
                      int.sizeof - 1) & ~(int.sizeof - 1));
                }
        };
    }

    // Does nothing special, just for the demo.
    Foo opAddAssign(Foo x)
    {
        if (x.Mem.length > Mem.length)
            Mem.length = x.Mem.length;
        foreach(inout long a; Mem)
            foreach(long b; x.Mem)
                a += b;

        return this;
    }

    // Debug display.
    void ShowMe()
    {
        writef("\nFoo #%d --> ", id);
        foreach(int i,long x; Mem)
        {
            writef("%d", x);
            if (i != Mem.length-1)
                writef(",");
        }
        writef("\n");
    }
}

void main()
{
    Foo A = new Foo;
    A.ShowMe();
    Foo B = new Foo;
    B.ShowMe();

    A = new Foo(cast(char)'a', 4.55, 1,2,3,"AA", B, 9,8,6);
    A.ShowMe();

    B = new Foo(1,2,3);
    B.ShowMe();
    B += A;
    B.ShowMe();

    B = new Foo(1,2,3);
    B.ShowMe();
    B += new Foo(cast(char)'a', 4.55, 1,2,3,"AA", B, 9,8,6);
    B.ShowMe();

}
<---------------------------------------->

-- 
Derek
Melbourne, Australia
22/02/2005 3:11:39 PM
February 25, 2005
That looks like a compiler bug. You should get the TypeInfo argument for both cases.