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.