| Thread overview | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 30, 2008 Test for self referential templated Class | ||||
|---|---|---|---|---|
| ||||
Seems, that tests for the type of a self referential templated class are impossible, because recursive expansion is forbidden.
Am I missing something?
Example:
import std.metastrings;
class C(T){
pragma( msg, Format!(is(T:C!(int))));
//pragma( msg, Format!(is(T:C!(C!(int))))); //recursive expansion
forbidden
}
void main(){
auto c1= new C!( C!(int));
auto c2= new C!( C!( C!(int)));
}
-manfred
| ||||
June 30, 2008 Re: Test for self referential templated Class | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manfred Nowak | Manfred Nowak wrote:
> Seems, that tests for the type of a self referential templated class are impossible, because recursive expansion is forbidden.
>
> Am I missing something?
>
> Example:
>
> import std.metastrings;
> class C(T){
> pragma( msg, Format!(is(T:C!(int))));
> //pragma( msg, Format!(is(T:C!(C!(int))))); //recursive expansion forbidden
> }
> void main(){
> auto c1= new C!( C!(int));
> auto c2= new C!( C!( C!(int)));
> }
>
> -manfred
pragma( msg, Format!(is(T:C!(--> C!(int) <--- )))); //recursive expansion
C!(int) will call itself forever. You need a stopping condition like template specialization or an static if.
| |||
June 30, 2008 Re: Test for self referential templated Class | ||||
|---|---|---|---|---|
| ||||
Posted in reply to janderson | janderson wrote:
> You need a stopping condition like template specialization or an static if.
... but if this is true, then I have to implement a stopping condition or a static if for _every possible_ actual type ( int, uint, ...)---and the generic achievenment is lost.
-manfred
| |||
June 30, 2008 Re: Test for self referential templated Class | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manfred Nowak | On Mon, 30 Jun 2008 10:53:34 +0400, Manfred Nowak <svv1999@hotmail.com> wrote: > janderson wrote: > >> You need a stopping condition like >> template specialization or an static if. > > ... but if this is true, then I have to implement a stopping condition > or a static if for _every possible_ actual type ( int, uint, ...)---and > the generic achievenment is lost. > > -manfred > Use tango.core.Variant.isAtomicType!(T) template to test against builtin types. | |||
June 30, 2008 Re: Test for self referential templated Class | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Koroskin Denis | Koroskin Denis wrote:
> Use tango.core.Variant.isAtomicType!(T) template to test against
> builtin types.
.. this does not help for user defined types.
One seem's to need something like
class C(T){
//...
!is( T == C!( ... ))
But this casts one into infinite recursion.
-manfred
| |||
June 30, 2008 Re: Test for self referential templated Class | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manfred_Nowak | Manfred_Nowak wrote:
> Koroskin Denis wrote:
>
>> Use tango.core.Variant.isAtomicType!(T) template to test against
>> builtin types.
>
> .. this does not help for user defined types.
>
> One seem's to need something like
> class C(T){
> //...
> !is( T == C!( ... ))
>
> But this casts one into infinite recursion.
>
> -manfred
Make it derive from a (non-templated) interface and test for that.
| |||
June 30, 2008 Re: Test for self referential templated Class | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Robert Fraser | Robert Fraser wrote:
> Make it derive from a (non-templated) interface and test for that.
Yes, this seems to be a part of the solution. With this hack every instance can check whether the given type T belongs to any instance of C's family of instances. But it seems still not possible to identify an instance on a specified non trivial depth of recursion:
import std.metastrings;
interface Hack{};
class C(T):Hack{
pragma( msg, Format!(is( T: Hack)));
pragma( msg, Format!(is( T== int)));
pragma( msg, Format!(is( T== C!( int))));
//pragma( msg, Format!(is( T== C!( C!( int))))); //recursion
//pragma( msg, Format!(is( T== C!( C!( C!( int)))))); //recursion
}
//class C(T:C!( C!(int))){ }
void main(){
auto c1= new C!(int);
pragma( msg, "c1 done");
auto c2= new C!( C!(int));
pragma( msg, "c2 done");
auto c3= new C!( C!( C!(int)));
pragma( msg, "c3 done");
}
-manfred
| |||
June 30, 2008 Re: Test for self referential templated Class | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manfred_Nowak | On 2008-06-30 03:56:54 -0400, "Manfred_Nowak" <svv1999@hotmail.com> said: > One seem's to need something like > > class C(T){ > //... > !is( T == C!( ... )) > > But this casts one into infinite recursion. You could add a dummy member in C!(T) and check for its presence. Something like: struct IsCTemplate {} class C(T) { static const IsCTemplate isCTemplate; //... } Then you can use this go check if you have a C!(...) or not: is(T.isCTemplate == IsCTemplate) -- Michel Fortin michel.fortin@michelf.com http://michelf.com/ | |||
June 30, 2008 Re: Test for self referential templated Class | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | Michel Fortin wrote:
> You could add a dummy member in C!(T) and check for its presence.
Yes. That seems to be less hackish than what Robert suggested. But still no possibility to fetch a non trivial depth of recursion.
import std.metastrings;
private typedef int TID; // TypeID for checking purposes
class C(T){
alias .TID TID;
pragma( msg, Format!(is( T.TID== TID)));
}
class D{
private typedef int TID;
}
void main(){
auto d= new C!( D);
pragma( msg, "d done");
auto c1= new C!(int);
pragma( msg, "c1 done");
auto c2= new C!( C!(int));
pragma( msg, "c2 done");
auto c3= new C!( C!( C!(int)));
pragma( msg, "c3 done");
}
-manfred
| |||
June 30, 2008 Re: Test for self referential templated Class | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Manfred_Nowak | Manfred_Nowak wrote: > Michel Fortin wrote: > >> You could add a dummy member in C!(T) and check for its presence. > > Yes. That seems to be less hackish than what Robert suggested. But still no possibility to fetch a non trivial depth of recursion. I've done this sort of thing with a recursive mixin. The basic idea is something like char [] testRecursion(bool done) { return done? `true`: `mixin("testRecursion( XXX)`; } template isRecursive(T) { const bool isRecursive = mixin(testRecursion()); } where XXX is some expression involving T. It works because if the condition isn't true, the recursive bit is just a string which is never parsed. But if it is true, it gets mixed in recursively. There might be something a bit less hacky for this situation*. But the recursive mixin trick will work even for fiendishly difficult cases. You can hide any old garbage that wouldn't normally compile for ANY reason. * for D2.0, you can probably use __traits(compiles, XXX) > > import std.metastrings; > private typedef int TID; // TypeID for checking purposes > class C(T){ > alias .TID TID; > pragma( msg, Format!(is( T.TID== TID))); > } > class D{ > private typedef int TID; > } > void main(){ > auto d= new C!( D); > pragma( msg, "d done"); > auto c1= new C!(int); > pragma( msg, "c1 done"); > auto c2= new C!( C!(int));; > pragma( msg, "c2 done"); > auto c3= new C!( C!( C!(int))); > pragma( msg, "c3 done"); > } > > -manfred | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply