digitalmars.D.learn - Possible Bug with Interfaces in Variadic Functions?
- Daniel Giddings (70/70) Sep 17 2006 Hi All, I'm new to D, and have come across the following problem. I
- Bruno Medeiros (24/112) Sep 26 2006 You are using typeid() comparison incorrectly (no fault of yours, the
- Daniel Giddings (4/28) Sep 26 2006 That works nicely.
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
Sep 17 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
Sep 26 2006
That works nicely.
Thanks,
:-) Dan
Bruno Medeiros wrote:
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());
}
}
Sep 26 2006








Daniel Giddings <danielg microforte.com.au>