www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 1826] New: TransitiveBaseTypeTuple skips interfaces implemented by base types

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1826

           Summary: TransitiveBaseTypeTuple skips interfaces implemented by
                    base types
           Product: D
           Version: 2.008
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Phobos
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: dhasenan gmail.com


import std.traits;

interface I1 {}
class C1 : I1 {}
class C2 : C1 {}

pragma (msg, TransitiveBaseTypeTuple!(C2).stringof);
// outputs (C1, Object) -- should output (C1, Object, I1) in some order

It's possible that that's intended, but it makes TransitiveBaseTypeTuple a lot
less useful.


-- 
Feb 09 2008
next sibling parent reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1826


andrei metalanguage.com changed:

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




------- Comment #1 from andrei 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);
}


-- 
Feb 09 2008
parent Christopher Wright <dhasenan gmail.com> writes:
 ------- Comment #1 from andrei 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.

Thanks! I'm not in a hurry, really -- since Tango doesn't have the equivalent, I'm implementing it anyway.
Feb 09 2008
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1826


andrei metalanguage.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED




------- Comment #3 from andrei metalanguage.com  2008-03-07 00:31 -------
Fixed in 2.012.


-- 
Mar 06 2008