[Issue 1826] TransitiveBaseTypeTuple skips interfaces implemented by base types

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sat Feb 9 09:08:09 PST 2008


http://d.puremagic.com/issues/show_bug.cgi?id=1826


andrei at metalanguage.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         AssignedTo|bugzilla at digitalmars.com    |andrei at metalanguage.com




------- Comment #1 from andrei at metalanguage.com  2008-02-09 11:08 -------
That was pretty silly of me; thanks for the report. I fixed the bug by adding
InterfacesTuple!(T) to return all interfaces directly or indirectly inherited
by T (without duplicates), and by using that in TransitiveBaseTypesTuple!(T).
In case you are in a hurry, I paste the two templates (the new one and the
modified one) below.

/**
 * Get a $(D_PARAM TypeTuple) of $(I all) interfaces directly or
 * indirectly inherited by this class or interface. Interfaces do not
 * repeat if multiply implemented. $(D_PARAM InterfacesTuple!(Object))
 * yields the empty type tuple.
 *
 * Example:
 * ---
 * import std.traits, std.typetuple, std.stdio;
 * interface I1 { }
 * interface I2 { }
 * class A : I1, I2 { }
 * class B : A, I1 { }
 * class C : B { }
 *
 * void main()
 * {
 *     alias InterfacesTuple!(C) TL;
 *     writeln(typeid(TL));     // prints: (I1, I2)
 * }
 * ---
 */

template InterfacesTuple(T)
{
    static if (is(T == Object))
    {
        alias TypeTuple!() InterfacesTuple;
    }
    static if (is(BaseTypeTuple!(T)[0] == Object))
    {
        alias TypeTuple!(BaseTypeTuple!(T)[1 .. $]) InterfacesTuple;
    }
    else
    {
        alias NoDuplicates!(
            TypeTuple!(BaseTypeTuple!(T)[1 .. $], // direct interfaces
                       InterfacesTuple!(BaseTypeTuple!(T)[0])))
            InterfacesTuple;
    }
}

unittest
{
    {
        // doc example
        interface I1 { }
        interface I2 { }
        class A : I1, I2 { }
        class B : A, I1 { }
        class C : B { }
        alias InterfacesTuple!(C) TL;
        assert(is(TL[0] == I1) && is(TL[1] == I2));
    }
    interface I1 {}
    interface I2 {}
    class B1 : I1, I2 {}
    class B2 : B1, I1 {}
    class B3 : B2, I2 {}
    alias InterfacesTuple!(B3) TL;
    //
    assert(TL.length == 2);
    assert(is (TL[0] == I2));
    assert(is (TL[1] == I1));
}

/**
 * Get a $(D_PARAM TypeTuple) of $(I all) base classes of $(D_PARAM
 * T), in decreasing order, followed by $(D_PARAM T)'s
 * interfaces. $(D_PARAM TransitiveBaseTypeTuple!(Object)) yields the
 * empty type tuple.
 *
 * Example:
 * ---
 * import std.traits, std.typetuple, std.stdio;
 * interface I { }
 * class A { }
 * class B : A, I { }
 * class C : B { }
 *
 * void main()
 * {
 *     alias TransitiveBaseTypeTuple!(C) TL;
 *     writeln(typeid(TL));     // prints: (B,A,Object,I)
 * }
 * ---
 */

template TransitiveBaseTypeTuple(T)
{
    static if (is(T == Object))
        alias TypeTuple!() TransitiveBaseTypeTuple;
    else
        alias TypeTuple!(BaseClassesTuple!(T),
            InterfacesTuple!(T))
            TransitiveBaseTypeTuple;
}

unittest
{
    interface I1 {}
    interface I2 {}
    class B1 {}
    class B2 : B1, I1, I2 {}
    class B3 : B2, I1 {}
    alias TransitiveBaseTypeTuple!(B3) TL;
    assert(TL.length == 5);
    assert(is (TL[0] == B2));
    assert(is (TL[1] == B1));
    assert(is (TL[2] == Object));
    assert(is (TL[3] == I1));
    assert(is (TL[4] == I2));

    assert(TransitiveBaseTypeTuple!(Object).length == 0);
}


-- 



More information about the Digitalmars-d-bugs mailing list