Jump to page: 1 2
Thread overview
Test for self referential templated Class
Jun 30, 2008
Manfred Nowak
Jun 30, 2008
janderson
Jun 30, 2008
Manfred Nowak
Jun 30, 2008
Koroskin Denis
Jun 30, 2008
Manfred_Nowak
Jun 30, 2008
Robert Fraser
Jun 30, 2008
Manfred_Nowak
Jun 30, 2008
Michel Fortin
Jun 30, 2008
Manfred_Nowak
Jun 30, 2008
Don
Jul 02, 2008
Fawzi Mohamed
Jul 01, 2008
JAnderson
Jul 01, 2008
JAnderson
June 30, 2008
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
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
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
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
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
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
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
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
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
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
« First   ‹ Prev
1 2