Bug 1826 – TransitiveBaseTypeTuple skips interfaces implemented by base types

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
x86
OS
Linux
Creation time
2008-02-09T07:53:00Z
Last change time
2015-06-09T01:14:22Z
Assigned to
andrei
Creator
dhasenan

Comments

Comment #0 by dhasenan — 2008-02-09T07:53:33Z
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.
Comment #1 by andrei — 2008-02-09T11:08:07Z
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); }
Comment #2 by dhasenan — 2008-02-09T19:05:17Z
> ------- Comment #1 from [email protected] 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.
Comment #3 by andrei — 2008-03-07T00:31:12Z
Fixed in 2.012.