Thread overview
Polymorphism in regular variadic function
Dec 05, 2006
Bill Baxter
Dec 06, 2006
Bill Baxter
Dec 06, 2006
Bill Baxter
Dec 06, 2006
Bill Baxter
December 05, 2006
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
December 05, 2006
"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.


December 06, 2006
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
December 06, 2006
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
December 06, 2006
"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.


December 06, 2006
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