Thread overview
Implicit castable structs
Jan 08, 2008
Frank Benoit
Jan 08, 2008
Sean Kelly
Jan 09, 2008
Kris
Jan 09, 2008
Dan
Jan 09, 2008
Frank Benoit
Jan 09, 2008
0ffh
Jan 10, 2008
Dan
Jan 10, 2008
Dan
Jan 09, 2008
Frank Benoit
January 08, 2008
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.

January 08, 2008
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
January 09, 2008
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.
> 


January 09, 2008
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.
January 09, 2008
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 :)
January 09, 2008
opCast is also not really good.
passing a null pointer would crash then. (or not?)
January 09, 2008
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
January 10, 2008
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
January 10, 2008
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);
}

January 14, 2008
"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