www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Implicit castable structs

reply Frank Benoit <keinfarbton googlemail.com> writes:
In GTK programming, there are struct that act like a object hierarchy.

struct GtkWidget{ /* data member */ }
struct GtkContainer{
	GtkWidget widget; // parent is always first member
	// more data members
}
struct GtkBin{
	GtkContainer container; // parent is always first member
	// more data members
}
extern(C) void gtk_widget_foo( GtkWidget* widget );

// in user code ...
GtkBin* bin;
gtk_widget_foo( bin ); // Error: cannot implicit cast

Can the D compiler be enhanced to allow this? More precisely:
"A pointer to a struct is implicitly convertable to all types, that map 
to the first position in the struct"

In the case above, a GtkBin* would be convertable to GtkContainer* and 
GtkWidget*. A GtkContainer* would /not/ be convertable to GtkBin* 
because it does not contain it.
Jan 08 2008
next sibling parent Sean Kelly <sean f4.ca> writes:
Frank Benoit wrote:
 
 Can the D compiler be enhanced to allow this? More precisely:
 "A pointer to a struct is implicitly convertable to all types, that map 
 to the first position in the struct"
That's a pretty cool idea. It would certainly work. Sean
Jan 08 2008
prev sibling next sibling parent reply "Kris" <foo bar.com> writes:
Yeah, that's old-school inheritance. But I think it's probably a bit dodgy 
to sidestep type-safety to do what you want. Besides, it's not hard to write 
this instead (the old school way):

#  gtk_widget_foo (&bin->container.widget);

the codegen will be the same as just using 'bin' by itself, yet the 
type-safety is fully retained.

On the other hand, if there were an opCast() in the struct to support what 
you're suggesting ....

- Kris



"Frank Benoit" <keinfarbton googlemail.com> wrote in message 
news:fm0vht$1tv7$1 digitalmars.com...
 In GTK programming, there are struct that act like a object hierarchy.

 struct GtkWidget{ /* data member */ }
 struct GtkContainer{
 GtkWidget widget; // parent is always first member
 // more data members
 }
 struct GtkBin{
 GtkContainer container; // parent is always first member
 // more data members
 }
 extern(C) void gtk_widget_foo( GtkWidget* widget );

 // in user code ...
 GtkBin* bin;
 gtk_widget_foo( bin ); // Error: cannot implicit cast

 Can the D compiler be enhanced to allow this? More precisely:
 "A pointer to a struct is implicitly convertable to all types, that map to 
 the first position in the struct"

 In the case above, a GtkBin* would be convertable to GtkContainer* and 
 GtkWidget*. A GtkContainer* would /not/ be convertable to GtkBin* because 
 it does not contain it.
 
Jan 08 2008
next sibling parent reply Dan <murpsoft hotmail.com> writes:
Kris Wrote:

 Yeah, that's old-school inheritance. But I think it's probably a bit dodgy 
 to sidestep type-safety to do what you want. Besides, it's not hard to write 
 this instead (the old school way):
 
 #  gtk_widget_foo (&bin->container.widget);
 
 the codegen will be the same as just using 'bin' by itself, yet the 
 type-safety is fully retained.
 
 On the other hand, if there were an opCast() in the struct to support what 
 you're suggesting ....
 
 - Kris
 
 
 
 "Frank Benoit" <keinfarbton googlemail.com> wrote in message 
 news:fm0vht$1tv7$1 digitalmars.com...
 In GTK programming, there are struct that act like a object hierarchy.

 struct GtkWidget{ /* data member */ }
 struct GtkContainer{
 GtkWidget widget; // parent is always first member
 // more data members
 }
 struct GtkBin{
 GtkContainer container; // parent is always first member
 // more data members
 }
 extern(C) void gtk_widget_foo( GtkWidget* widget );

 // in user code ...
 GtkBin* bin;
 gtk_widget_foo( bin ); // Error: cannot implicit cast

 Can the D compiler be enhanced to allow this? More precisely:
 "A pointer to a struct is implicitly convertable to all types, that map to 
 the first position in the struct"

 In the case above, a GtkBin* would be convertable to GtkContainer* and 
 GtkWidget*. A GtkContainer* would /not/ be convertable to GtkBin* because 
 it does not contain it.
 
Multiple opCast is the #2 requested feature on that "vote for D changes" website, and IMHO the most desireable one for my project. My code would be dramatically more attractive... *gorgeous* if you could do the following: struct Value { const(char)[] opCast() { bla bla bla } int opCast() { bla bla bla } and: Value myfunc() { return 4; // performs opAssign() } Regards, Dan.
Jan 09 2008
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
opCast is also not really good.
passing a null pointer would crash then. (or not?)
Jan 09 2008
parent reply 0ffh <frank youknow.what.todo.interNETz> writes:
Frank Benoit wrote:
 opCast is also not really good.
 passing a null pointer would crash then. (or not?)
Yes, IIRC there was some obnoxious "assert(this !is null);" in all non-static member functions... regards, frank
Jan 09 2008
parent reply Dan <murpsoft hotmail.com> writes:
0ffh Wrote:

 Frank Benoit wrote:
 opCast is also not really good.
 passing a null pointer would crash then. (or not?)
Yes, IIRC there was some obnoxious "assert(this !is null);" in all non-static member functions... regards, frank
I *need* to be able to go: Value myValue = 4; int bob = myValue; At the moment I'm accomplishing that by doing: Value myValue = 4; int bob = Value.toInteger(); Which is essentially identical to opCast(), except it gets ugly. It's pretty clear to me that Value is performing implicit opAssign/opCall when something goes in, and likewise it would be clear with opCast. The other major place I'd like it to handle this is with functions. I can't do this: Value myFunc() { return 4; } or this: Value myFunc(Value self, Value cc) { bla bla bla } myFunc(3,5); If I got all this opCall/opAssign/opCast sorted out, my source would be about 15% smaller because a fair chunk of it is type conversions to handle ECMAScript's var. Regards, Dan
Jan 09 2008
parent Dan <murpsoft hotmail.com> writes:
Perhaps, to clarify;
What I've got:

static Value Global_parseFloat(Value self, Value cc, Value[] a ...) { 
    if(a.length) 
        return cast(Value) a[0].toReal(); 
    return NAN; 
} 

static Value Global_isNaN(Value self, Value cc, Value[] a ...) { 
    return cast(Value) ( (!a.length || a[0].toReal() == real.nan?) true :
false); 
}

~~

What I want:

extern(Walnut):

Value Global_parseFloat(Value[] a ...) {
    if(a.length)
        return cast(real) a[0];
    return real.nan;
}

Value Global_isNaN(Value[] a ...) {
    return (!a.length || cast(real) a[0] == real.nan);
}
Jan 09 2008
prev sibling parent Frank Benoit <keinfarbton googlemail.com> writes:
Kris schrieb:
 Yeah, that's old-school inheritance. But I think it's probably a bit dodgy 
 to sidestep type-safety to do what you want. Besides, it's not hard to write 
 this instead (the old school way):
 
 #  gtk_widget_foo (&bin->container.widget);
 
hm yes, this is certainly true. GtkMessageDialog* msgdlg; gtk_widget_foo (&msgdlg.dialog.window.bin.container.widget); gtk_widget_foo (cast(GtkWidget*)msgdlg); Both are bad, the second can be shorter. Even if i hate explicit upcast, in this case I prefer it :)
Jan 09 2008
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Frank Benoit" wrote
 In GTK programming, there are struct that act like a object hierarchy.

 struct GtkWidget{ /* data member */ }
 struct GtkContainer{
 GtkWidget widget; // parent is always first member
 // more data members
 }
 struct GtkBin{
 GtkContainer container; // parent is always first member
 // more data members
 }
 extern(C) void gtk_widget_foo( GtkWidget* widget );

 // in user code ...
 GtkBin* bin;
 gtk_widget_foo( bin ); // Error: cannot implicit cast

 Can the D compiler be enhanced to allow this? More precisely:
 "A pointer to a struct is implicitly convertable to all types, that map to 
 the first position in the struct"

 In the case above, a GtkBin* would be convertable to GtkContainer* and 
 GtkWidget*. A GtkContainer* would /not/ be convertable to GtkBin* because 
 it does not contain it.
I always thought it would be cool to have inheritance for structs, not for virtual function overloads, but just for this implicit casting purposes, and inheriting final functions: struct GtkWidget {} struct GtkContainer : GtkWidget {} struct GtkBin : GtkContainer {} -Steve
Jan 14 2008