Possible Bug with Interfaces in Variadic Functions?

Bruno Medeiros brunodomedeiros+spam at com.gmail
Tue Sep 26 10:20:11 PDT 2006


Daniel Giddings wrote:
> Hi All, I'm new to D, and have come across the following problem. I 
> thought it best to ask about it before reporting it as a bug.
> 
> The problem I've come across is passing a class with an interface base 
> into a variadic function and accessing it as the interface. It crashes 
> the program with some strange behaviour. As far as I can tell I'm not 
> doing anything wrong.
> 
> Anyway, here's the program:
> 
> --------------------------------------------------------
> import std.stdio;
> import std.stdarg;
> 
> class B
> {
>     char[] f() { return "B.f"; }
> }
> 
> class DB : B
> {
>     char[] f() { return "DB.f"; }
> }
> 
> interface I
> {
>     char[] f();
> }
> 
> class CI : I
> {
>     char[] f() { return "CI.f"; }
> }
> 
> void output( ... )
> {
>     for( int i = 0; i < _arguments.length; ++i )
>     {
>         if( _arguments[i] == typeid(int) )
>             writefln( "int: %s", va_arg!(int)(_argptr) );
>        
>         if( _arguments[i] == typeid(char[]) )
>             writefln( "char[]: %s", va_arg!(char[])(_argptr) );
>        
>         if( _arguments[i] == typeid(B) )
>             writefln( "B: %s", va_arg!(B)(_argptr).f() );   
>        
>         if( _arguments[i] == typeid(I) )
>         {
>             writefln( "Print here for test purposes only - CI appears 
> after this" );
>             writefln( "I: %s", va_arg!(I)(_argptr).f() );
>         }
>     }
> }
> 
> void main()
> {
>     output( 5, "Hello World!", new DB, new CI );
> }
> --------------------------------------------------------
> 
> The output I'm receiving is:
> 
> int: 5
> char[]: Hello World!
> B: DB.f
> Print here for test purposes only - CI appears after this
> CI
> I: Error: Access Violation
> 
> where as I would have expected:
> 
> int: 5
> char[]: Hello World!
> B: DB.f
> Print here for test purposes only - CI appears after this
> I: CI.f
> 
> I added the class example with a base class as well, and it behaves as I 
> expected.
> 
> Is there anything I'm doing incorrectly? It's easy enough to get around 
> the problem for what I want to do, but I thought I'd bring it up.
> 
> Cheers,
> 
> :-) Dan

You are using typeid() comparison incorrectly (no fault of yours, the 
spec is erroneous, see http://d.puremagic.com/issues/show_bug.cgi?id=373 ).

Using '==' to compare TypeInfos will test the equality of the type's 
"archetype", that is, if they are both a struct, a pointer, a class, 
etc. Apparently interfaces and classes belong to the same archetype 
(which is class), so any TypeInfo equality comparison between any of 
these will allways result true.
Using 'is' to compare TypeInfos will test for an exact type match, which 
is also not what you, since it will disregard polymorphism.

Here's how you can do it:

   // Check for class archetype:
   if( _arguments[i] == typeid(Object) ) {
     auto obj = va_arg!(Object)(_argptr);
     // check if obj is-a I
     if( (cast(I) obj) != null ) {
       I myi = cast(I) obj;
       // use myi
       writefln(myi.f());
     }
   }

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D



More information about the Digitalmars-d-learn mailing list