www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Polymorphism in regular variadic function

reply Bill Baxter <wbaxter gmail.com> writes:
Is there any way to check if an argument is type T or anything derived 
from it using the TypeInfo?

Basically I want this:

class Foo { int x = 3; }
class Bar : Foo { long y = 4; }

void printargs(...)
{
     printf("%d arguments\n", _arguments.length);
     for (int i = 0; i < _arguments.length; i++)
     {   _arguments[i].print();

         // Want to accept Foo or anything derived from Foo here!
	if (_arguments[i] == typeid(Foo))
	{
	    Foo f = *cast(Foo*)_argptr;
	    _argptr += Foo.sizeof;
	    printf("\t%p\n", f);
	}
	else
	    assert(0);
     }
}


--bb
Dec 04 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Bill Baxter" <wbaxter gmail.com> wrote in message 
news:el2iq4$2gb3$1 digitaldaemon.com...
 Is there any way to check if an argument is type T or anything derived 
 from it using the TypeInfo?

 Basically I want this:

 class Foo { int x = 3; }
 class Bar : Foo { long y = 4; }

 void printargs(...)
 {
     printf("%d arguments\n", _arguments.length);
     for (int i = 0; i < _arguments.length; i++)
     {   _arguments[i].print();

         // Want to accept Foo or anything derived from Foo here!
 if (_arguments[i] == typeid(Foo))
 {
     Foo f = *cast(Foo*)_argptr;
     _argptr += Foo.sizeof;
     printf("\t%p\n", f);
 }
 else
     assert(0);
     }
 }


 --bb

Heheh.. I did something like: TypeInfo ti = _arguments[i]; TypeInfo_Class tic = cast(TypeInfo_Class)ti; if(tic) { ClassInfo ci = tic.info; for( ; ci !is null; ci = ci.base) if(ci == Foo.classinfo) { // it's derived, do what you will } if(ci is null) { // we got to the base without finding Foo, // it's not derived from Foo } } I wonder if there's any way to take advantage of the internal casting functions (which are used whenever you do a dynamic downcast). Well, now that I think about it, you might be able to replace the above condition with: if(tic) { Object o = va_arg!(Object)(_argptr); Foo f = cast(Foo)o; if(f !is null) { // it's a Foo } } Which .. would probably work. Give it a shot.
Dec 04 2006
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Thanks Jarrett,
This TypeInfo_Class thing seems to be undocumented.

Incidentally it's a piece of cake with a variadic template, I just 
wanted to see try it with a regular function first before going all 
templatey.

I haven't tried your code, but it seems like your cast to Object in the 
second suggestion is not going to be safe if the thing really isn't an 
Object.  The following cast to Foo will try to do some vtable stuff I 
guess, and that could result in a bad memory access, no?

--bb

Jarrett Billingsley wrote:
 "Bill Baxter" <wbaxter gmail.com> wrote in message 
 news:el2iq4$2gb3$1 digitaldaemon.com...
 Is there any way to check if an argument is type T or anything derived 
 from it using the TypeInfo?

 Basically I want this:

 class Foo { int x = 3; }
 class Bar : Foo { long y = 4; }

 void printargs(...)
 {
     printf("%d arguments\n", _arguments.length);
     for (int i = 0; i < _arguments.length; i++)
     {   _arguments[i].print();

         // Want to accept Foo or anything derived from Foo here!
 if (_arguments[i] == typeid(Foo))
 {
     Foo f = *cast(Foo*)_argptr;
     _argptr += Foo.sizeof;
     printf("\t%p\n", f);
 }
 else
     assert(0);
     }
 }


 --bb

Heheh.. I did something like: TypeInfo ti = _arguments[i]; TypeInfo_Class tic = cast(TypeInfo_Class)ti; if(tic) { ClassInfo ci = tic.info; for( ; ci !is null; ci = ci.base) if(ci == Foo.classinfo) { // it's derived, do what you will } if(ci is null) { // we got to the base without finding Foo, // it's not derived from Foo } } I wonder if there's any way to take advantage of the internal casting functions (which are used whenever you do a dynamic downcast). Well, now that I think about it, you might be able to replace the above condition with: if(tic) { Object o = va_arg!(Object)(_argptr); Foo f = cast(Foo)o; if(f !is null) { // it's a Foo } } Which .. would probably work. Give it a shot.

--bb
Dec 05 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Bill Baxter" <dnewsgroup billbaxter.com> wrote in message 
news:el52bq$2dcb$1 digitaldaemon.com...
 Thanks Jarrett,
 This TypeInfo_Class thing seems to be undocumented.

 Incidentally it's a piece of cake with a variadic template, I just wanted 
 to see try it with a regular function first before going all templatey.

 I haven't tried your code, but it seems like your cast to Object in the 
 second suggestion is not going to be safe if the thing really isn't an 
 Object.  The following cast to Foo will try to do some vtable stuff I 
 guess, and that could result in a bad memory access, no?

Hmm.. I don't think it should. TypeInfo_Class is, well, the typeinfo for a class, which all derive from Object, so getting the param as an Object shouldn't be a problem, should it? ..oh crap. Interfaces also have a TypeInfo_Class. :S And since they aren't _required_ to be castable to object (i.e. COM interfaces).. Yeah, the other way is necessary.
Dec 05 2006
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Jarrett Billingsley wrote:
 "Bill Baxter" <dnewsgroup billbaxter.com> wrote in message 
 news:el52bq$2dcb$1 digitaldaemon.com...
 Thanks Jarrett,
 This TypeInfo_Class thing seems to be undocumented.

 Incidentally it's a piece of cake with a variadic template, I just wanted 
 to see try it with a regular function first before going all templatey.

 I haven't tried your code, but it seems like your cast to Object in the 
 second suggestion is not going to be safe if the thing really isn't an 
 Object.  The following cast to Foo will try to do some vtable stuff I 
 guess, and that could result in a bad memory access, no?

Hmm.. I don't think it should. TypeInfo_Class is, well, the typeinfo for a class, which all derive from Object, so getting the param as an Object shouldn't be a problem, should it?

Oh, I see, I didn't realize the TypeInfo_Class bits applied to the second suggestion also. TypeInfo ti = _arguments[i]; TypeInfo_Class tic = cast(TypeInfo_Class)ti; if(tic) { Object o = va_arg!(Object)(_argptr); Foo f = cast(Foo)o; .. So yeh, that does look like it would work, except for, as you say, the fact that it doesn't... :( --bb
Dec 05 2006
prev sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Jarrett Billingsley wrote:

 Heheh.. I did something like:
 
 TypeInfo ti = _arguments[i];
 TypeInfo_Class tic = cast(TypeInfo_Class)ti;
 
 if(tic)
 {
     ClassInfo ci = tic.info;
 
     for( ; ci !is null; ci = ci.base)
         if(ci == Foo.classinfo)
         {
             // it's derived, do what you will
         }
 
     if(ci is null)
     {
         // we got to the base without finding Foo,
         // it's not derived from Foo
     }
 }
 

I added this tip to the comments page for Phobos/object. http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Phobos/Object --bb
Dec 05 2006