Struct Flattening

Max Samukha samukha at voliacable.com.removethis
Thu Apr 23 03:08:50 PDT 2009


On Thu, 23 Apr 2009 10:45:01 +0200, Max Samukha
<samukha at voliacable.com.removethis> wrote:

>
>You could do it like this:
>
>struct Joint(T...)
>{
>    T ranges;
>}
>
>template isJoint(T)
>{
>    enum isJoint = is(typeof(T.ranges)); // or whatever means you
>choose to identify a Joint
>}
>
>template JointRetType(T...)
>{
>    static if (T.length)
>    {
>        static if (isJoint!(T[0]))
>            alias Joint!(typeof(T[0].ranges),
>typeof(JointRetType!(T[1..$]).ranges)) JointRetType;
>        else
>            alias Joint!(T[0], typeof(JointRetType!(T[1..$]).ranges))
>JointRetType;
>    }
>    else
>        alias Joint!() JointRetType;
>}
>
>private /+ auto +/ Joint!(T) flatJoint(T...)(T args)
>{
>    return Joint!(T)(args);
>}
>
>/+ auto +/ JointRetType!(T) joint(T...)(T args)
>{
>    static if (T.length)
>    {
>        static if (is(typeof(T[0].ranges)))
>            return flatJoint(args[0].ranges,
>joint(args[1..$]).ranges);
>        else
>            return flatJoint(args[0], joint(args[1..$]).ranges);
>    }
>    else
>        return Joint!()();
>}
>
>void main()
>{
>
>    Joint!(uint[], uint[]) r1;
>    uint[] r2;
>    auto result = joint(r1, r2);
>    static assert(is(typeof(result) == Joint!(uint[], uint[],
>uint[])));
>}
>
>Could be optimized to eliminate excessive copying. JointRetType is
>necessary because you can't use 'auto'
>(http://d.puremagic.com/issues/show_bug.cgi?id=2863)

Without recursive calls:

template StaticTuple(T...)
{
    alias T StaticTuple;
}

struct Joint(T...)
{
    T ranges;
}

template isJoint(T)
{
    enum isJoint = is(typeof(T.ranges)); // or whatever means you
choose to identify a Joint
}

private template JointArgs(T...)
{
    static if (T.length)
    {
        static if (isJoint!(T[0]))
            alias StaticTuple!(typeof(T[0].ranges),
JointArgs!(T[1..$])) JointArgs;
        else
            alias StaticTuple!(T[0], JointArgs!(T[1..$])) JointArgs;
    }
    else
        alias StaticTuple!() JointArgs;
}

private template targetIndexes(size_t index, T...)
{
    static if (T.length)
    {
        static if (isJoint!(T[0]))
            alias StaticTuple!(index, targetIndexes!(index +
typeof(T[0].ranges).length, T[1..$])) targetIndexes;
        else
            alias StaticTuple!(index, targetIndexes!(index + 1,
T[1..$])) targetIndexes;
    }
    else
        alias StaticTuple!() targetIndexes;

}

Joint!(JointArgs!(T)) joint(T...)(T args)
{
    typeof(return) ret;

    foreach (i, _i; T)
    {
        enum targetIndex = targetIndexes!(0, T)[i];
        static if (isJoint!(T[i]))
        {
            foreach (j, _j; typeof(T[i].ranges))
                ret.ranges[targetIndex + j] = args[i].ranges[j];
        }
        else
            ret.ranges[targetIndex] = args[i];
    }

    return ret;
}

void main()
{

    auto r1 = Joint!(uint[], uint[])([1, 2], [3, 4]);
    uint[] r2 = [5, 6];
    auto result = joint(r1, r2);
    static assert(is(typeof(result) == Joint!(uint[], uint[],
uint[])));
    assert (result.ranges[0] == [1u, 2][]);
    assert (result.ranges[1] == [3u, 4][]);
    assert (result.ranges[2] == [5u, 6][]);
}



More information about the Digitalmars-d mailing list