www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - match class specialization

reply mandel <mandel mailinator.com> writes:
I like to test if a type is a specialization of a template.
The following code does not work/compile but may
show my intention.

class A(T) {}

void main() {
   alias A!(int) foo;
   if(is(foo : A) {
       /* */
   }
}

I also cannot alter class A(T){} because it's part of a library.
If A would inherit from a non template class/interface B, is(A : B) would
do the job, but that's not the case.
Any ideas?
Apr 25 2007
parent reply BCS <BCS pathlink.com> writes:
mandel wrote:
 I like to test if a type is a specialization of a template.
 The following code does not work/compile but may
 show my intention.
 
 class A(T) {}
 
 void main() {
    alias A!(int) foo;
    if(is(foo : A) {
        /* */
    }
 }
 
 I also cannot alter class A(T){} because it's part of a library.
 If A would inherit from a non template class/interface B, is(A : B) would
 do the job, but that's not the case.
 Any ideas?

template TestA(U : A!(T)) { const bool TestA = true; } template TestA(U) { const bool TestA = false; } static if(TestA!(foo)) I haven't even tried to run that so...
Apr 25 2007
next sibling parent reply mandel <mandel mailinator.com> writes:
BCS Wrote:
 
 template TestA(U : A!(T))
 {
 	const bool TestA = true;
 }
 
 template TestA(U)
 {
 	const bool TestA = false;
 }
 
 
 static if(TestA!(foo))
 
 
 I haven't even tried to run that so...

I didn't thought the compiler let you use TestA(U : A!(T)) without explicitly declaring T a template variable. Well, you code works fine when foo is A!(T) no matter what T is, but it doesn't work when foo inherits from A!(T). So, the problem still remains.. class A(T) { } class B(T) : A!(T) { } template TestA(U : A!(T)) { const bool TestA = true; } template TestA(U) { const bool TestA = false; } void main() { alias B!(int) foo; //doesn't work //alias A!(int) foo;//work static if(TestA!(foo)) { Stdout("is A(T)\n"); } }
Apr 25 2007
next sibling parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
mandel wrote:
 Well, you code works fine when foo is A!(T) no matter what T is,
 but it doesn't work when foo inherits from A!(T).
 So, the problem still remains..

The code provided doesn't compile on GDC ("Error: identifier 'T' is not defined")[1] Therefore, the following is for DMD only: To walk up the inheritance tree: ----- import std.stdio; class A(T) {} class B(T) : A!(T) {} template TestA(U : A!(T)) { const TestA = true; } template TestA(U) { static if (is(U Bases == super) && is(Bases[0] == class)) const TestA = TestA!(Bases[0]); else const TestA = false; } void test(U)() { writef(typeid(U)); static if(TestA!(U)) { writefln("\t: A(T)"); } else { writefln("\t: not A(T)"); } } class C {} void main() { test!(B!(int)); test!(A!(int)); test!(int); test!(C); } ----- Assumptions: * A!(whatever) is a class, not an interface. * The first element of the tuple 'returned' by "is(X Tuple == super)" is the base class, if any. I'm not sure if this is guaranteed, but it seems to be the case anyway. If you want to be sure, modify the test to recurse over all base classes. Also note that like the original, it doesn't compile with GDC. [1]: Does anyone know if that's a) a bug in GDC, b) a bug in DMD, c) a consequence of GDC being at DMD v1.007 instead of v1.013, or d) something else? I don't feel like digging into the spec to find out what, if anything, it says about this.
Apr 25 2007
prev sibling parent reply BCS <BCS pathlink.com> writes:
mandel wrote:
 
 Thank you for your quick reply!
 I didn't thought the compiler let you use TestA(U : A!(T)) without explicitly
declaring T
 a template variable.
 Well, you code works fine when foo is A!(T) no matter what T is,
 but it doesn't work when foo inherits from A!(T).
 So, the problem still remains..
 

template TestA(U : A!(T)) { const bool TestA = true; } template TestA(U) { static if(is(U.superof)) const bool TestA = TestA!(U.superof); else const bool TestA = false; } This compiles but doesn't work. I seem to recall that there is no way to get the base class of a type at compile time (that is what .superof is supposed to be doing) If that can be replaced with something that acutely works, the above would work, I think.
Apr 25 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
BCS wrote:
 template TestA(U : A!(T))
 {
     const bool TestA = true;
 }
 
 template TestA(U)
 {
     static if(is(U.superof))
         const bool TestA = TestA!(U.superof);
     else
         const bool TestA = false;
 }
 
 This compiles but doesn't work.

There's no mention in the spec (at least, that I or Google can find) of a "superof" property. Google did find two previous threads where it's mentioned mentioning in the newsgroup archives, but the only post claiming it should already work seems to be posted by you... By the way, above code probably only compiles because .superof is only mentioned in an is() expression (which therefore evaluates to false) and a syntactically-correct declaration in the false branch of a static if.
 I seem to recall that there is no way to
 get the base class of a type at compile time (that is what .superof is 
 supposed to be doing) If that can be replaced with something that 
 acutely works, the above would work, I think.

As I posted just before you (you probably missed it while posting), this seems to work: --- static if (is(U Bases == super) && is(Bases[0] == class)) // Bases[0] is th base class } ---
Apr 25 2007
parent reply BCS <BCS pathlink.com> writes:
Frits van Bommel wrote:
 BCS wrote:
 
 template TestA(U : A!(T))
 {
     const bool TestA = true;
 }

 template TestA(U)
 {
     static if(is(U.superof))
         const bool TestA = TestA!(U.superof);
     else
         const bool TestA = false;
 }

 This compiles but doesn't work.

There's no mention in the spec (at least, that I or Google can find) of a "superof" property. Google did find two previous threads where it's mentioned mentioning in the newsgroup archives, but the only post claiming it should already work seems to be posted by you... By the way, above code probably only compiles because .superof is only mentioned in an is() expression (which therefore evaluates to false) and a syntactically-correct declaration in the false branch of a static if.

Exactly, I only said that it "compiles but doesn't work", ... for the exact reason you stated. I only wish it worked.
 I seem to recall that there is no way to
 get the base class of a type at compile time (that is what .superof is 
 supposed to be doing) If that can be replaced with something that 
 acutely works, the above would work, I think.

As I posted just before you (you probably missed it while posting), this seems to work: --- static if (is(U Bases == super) && is(Bases[0] == class)) // Bases[0] is th base class } ---

where dos that come from?? googel gets nothing
Apr 25 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS pathlink.com> wrote in message 
news:f0o7hp$29rs$1 digitalmars.com...
 Frits van Bommel wrote:

 where dos that come from?? googel gets nothing

Have a look at Expressions/IsExpressions, number 6. That feature's been around for quite some time now. std.traits.BaseTypeTuple looks a little nicer though.
Apr 25 2007
prev sibling parent mandel <mandel mailinator.com> writes:
BCS Wrote:
 
 
 template TestA(U : A!(T))
 {
 	const bool TestA = true;
 }
 
 template TestA(U)
 {
 	const bool TestA = false;
 }
 
 
 static if(TestA!(foo))
 
 
 I haven't even tried to run that so...

Your code works when foo is A!(T) for every T, but it doesn't work when foo inherits A!(T): class A(T) { } class B(T) : A!(T) { } template TestA(U : A!(T)) { const bool TestA = true; } template TestA(U) { const bool TestA = false; } void main() { alias B!(int) foo; //doesn't work //alias A!(int) foo;//work static if(TestA!(foo)) { Stdout("is A(T)\n"); } }
Apr 25 2007