Thread overview
match class specialization
Apr 25, 2007
mandel
Apr 25, 2007
BCS
Apr 25, 2007
mandel
Apr 25, 2007
Frits van Bommel
Apr 25, 2007
BCS
Apr 25, 2007
Frits van Bommel
Apr 25, 2007
BCS
Apr 25, 2007
mandel
April 25, 2007
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?
April 25, 2007
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...
April 25, 2007
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...
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..

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");
	}
}
April 25, 2007
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...
Thank you for your quick reply!
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");
	}
}
April 25, 2007
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.
April 25, 2007
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.
April 25, 2007
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
}
---
April 25, 2007
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



April 25, 2007
"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.