Thread overview
typecasts (again) a cast with 2 params
Feb 05, 2003
Mike Wynn
Mar 07, 2003
Walter
Mar 07, 2003
Mike Wynn
Mar 11, 2003
Walter
Mar 11, 2003
Mike Wynn
Mar 11, 2003
Walter
Mar 11, 2003
Mike Wynn
Apr 04, 2003
Walter
February 05, 2003
having just run fowl a simple missing &, I wondered what the responce to
allowing a typecast to not take one type as a param but two
so instead of (or as well as)  `cast( type )var;` there would be a `cast(
to-type, from-type) var;`
so that any changes in var would be reflected by an error.
for instance
uint stuff[] = new uint[4];
...
void * foo = cast(void *)(&(stuff[1])); // fine but there are times when you
want this.
however
void * foo = cast(void *)(stuff[1]); // rather different and may not be what
was required;

these would become
void * foo = cast(void *, uint*)(&(stuff[1])); // fine but there are times
when you want this.
however
void * foo = cast(void *, uint)(stuff[1]); // I really mean cast uint
element 1 to a void *
if, by mistake you wrote
void * foo = cast(void *, uint*)(stuff[1]);
then the compiler could warn you that the rhs was of the incorrect type.
uint not uint*

my reasoning is this, with one hand D offers GC which make robust OO
programming a little easier, and allows much simpler exception as each
unwound method frame does not now require cleaning up as much (the gc does
it later, only auto's need explicit cleanup to be added by the compiler).
then on the other the single 'C' cast (even if not 'C' style) allows,
without warning anything to be transmuted into anything else.
I would like to see the 'C' cast only allow for "safe" casts
numerics <-> numeric, or pointer<->pointer but not numeric<->pointer.
pointers to struct should be treated like objects 'C' casts; only allowed if
they inherit (or in the case of a struct, a pointer to the first member).
otherwise a two type cast is required. informing yourself, other programmers
and the compiler that you do know what you are doing.

Mike.




March 07, 2003
"Mike Wynn" <mike.wynn@l8night.co.uk> wrote in message news:b1s5ev$mg9$1@digitaldaemon.com...
> my reasoning is this, with one hand D offers GC which make robust OO
> programming a little easier, and allows much simpler exception as each
> unwound method frame does not now require cleaning up as much (the gc does
> it later, only auto's need explicit cleanup to be added by the compiler).
> then on the other the single 'C' cast (even if not 'C' style) allows,
> without warning anything to be transmuted into anything else.
> I would like to see the 'C' cast only allow for "safe" casts
> numerics <-> numeric, or pointer<->pointer but not numeric<->pointer.
> pointers to struct should be treated like objects 'C' casts; only allowed
if
> they inherit (or in the case of a struct, a pointer to the first member). otherwise a two type cast is required. informing yourself, other
programmers
> and the compiler that you do know what you are doing.

I understand your reasoning. D has a number of features to reduce the need for casting in ordinary programming, but they'll always be needed as an escape from the typing system. But, of course, escaping from the type system means you're on your own. I think your idea has merit, but it doesn't address the common casting problem of getting the wrong number of *'s when converting pointer types, etc.


March 07, 2003
"Walter" <walter@digitalmars.com> wrote in message news:b495tq$16l3$1@digitaldaemon.com...
>
> "Mike Wynn" <mike.wynn@l8night.co.uk> wrote in message news:b1s5ev$mg9$1@digitaldaemon.com...
> > my reasoning is this, with one hand D offers GC which make robust OO programming a little easier, and allows much simpler exception as each unwound method frame does not now require cleaning up as much (the gc
does
> > it later, only auto's need explicit cleanup to be added by the
compiler).
> > then on the other the single 'C' cast (even if not 'C' style) allows,
> > without warning anything to be transmuted into anything else.
> > I would like to see the 'C' cast only allow for "safe" casts
> > numerics <-> numeric, or pointer<->pointer but not numeric<->pointer.
> > pointers to struct should be treated like objects 'C' casts; only
allowed
> if
> > they inherit (or in the case of a struct, a pointer to the first
member).
> > otherwise a two type cast is required. informing yourself, other
> programmers
> > and the compiler that you do know what you are doing.
>
> I understand your reasoning. D has a number of features to reduce the need for casting in ordinary programming, but they'll always be needed as an escape from the typing system. But, of course, escaping from the type
system
> means you're on your own. I think your idea has merit, but it doesn't address the common casting problem of getting the wrong number of *'s when converting pointer types, etc.
>
in what way does it not solve the wrong *'s problem

nothing is going to stop what should be
int foo( void * param ) {
    bar ** ptr = cast(bar**)param;
}
being written as
int foo( void * param ) {
    bar * ptr = cast(bar*)param;
}

but will stop
int foo( int ** param ) {
    bar ** ptr = cast(bar**)(*param);
}
for being written as
int foo( int ** param ) {
    bar ** ptr = cast(bar**)param;
}

int foo( int ** param ) {
    bar ** ptr = cast(int* to bar**)(*param);  // valid
}

int foo( int ** param ) {
    bar ** ptr = cast(int* to bar**)(param); // not valid param is not an
int*
}

int foo( int  param ) {
    bar ** ptr = cast(int* to bar**)(param);  // invalid param is not int*
}

int foo( int param ) {
    bar ** ptr = cast(int* to bar**)(&param); // valid
}


March 11, 2003
"Mike Wynn" <mike.wynn@l8night.co.uk> wrote in message news:b49ljo$1g27$1@digitaldaemon.com...
>
> "Walter" <walter@digitalmars.com> wrote in message news:b495tq$16l3$1@digitaldaemon.com...
> >
> > "Mike Wynn" <mike.wynn@l8night.co.uk> wrote in message news:b1s5ev$mg9$1@digitaldaemon.com...
> > > my reasoning is this, with one hand D offers GC which make robust OO programming a little easier, and allows much simpler exception as each unwound method frame does not now require cleaning up as much (the gc
> does
> > > it later, only auto's need explicit cleanup to be added by the
> compiler).
> > > then on the other the single 'C' cast (even if not 'C' style) allows,
> > > without warning anything to be transmuted into anything else.
> > > I would like to see the 'C' cast only allow for "safe" casts
> > > numerics <-> numeric, or pointer<->pointer but not numeric<->pointer.
> > > pointers to struct should be treated like objects 'C' casts; only
> allowed
> > if
> > > they inherit (or in the case of a struct, a pointer to the first
> member).
> > > otherwise a two type cast is required. informing yourself, other
> > programmers
> > > and the compiler that you do know what you are doing.
> >
> > I understand your reasoning. D has a number of features to reduce the
need
> > for casting in ordinary programming, but they'll always be needed as an escape from the typing system. But, of course, escaping from the type
> system
> > means you're on your own. I think your idea has merit, but it doesn't address the common casting problem of getting the wrong number of *'s
when
> > converting pointer types, etc.
> >
> in what way does it not solve the wrong *'s problem
>
> nothing is going to stop what should be
> int foo( void * param ) {
>     bar ** ptr = cast(bar**)param;
> }
> being written as
> int foo( void * param ) {
>     bar * ptr = cast(bar*)param;
> }
>
> but will stop
> int foo( int ** param ) {
>     bar ** ptr = cast(bar**)(*param);
> }
> for being written as
> int foo( int ** param ) {
>     bar ** ptr = cast(bar**)param;
> }
>
> int foo( int ** param ) {
>     bar ** ptr = cast(int* to bar**)(*param);  // valid
> }
>
> int foo( int ** param ) {
>     bar ** ptr = cast(int* to bar**)(param); // not valid param is not an
> int*
> }
>
> int foo( int  param ) {
>     bar ** ptr = cast(int* to bar**)(param);  // invalid param is not int*
> }
>
> int foo( int param ) {
>     bar ** ptr = cast(int* to bar**)(&param); // valid
> }

It does add some redundancy which will reduce some bugs, as you illustrated. But when *** is cast to ** instead of *, it isn't caught.


March 11, 2003
> > >
> > in what way does it not solve the wrong *'s problem
> >
> > nothing is going to stop what should be
> > int foo( void * param ) {
> >     bar ** ptr = cast(bar**)param;
> > }
> > being written as
> > int foo( void * param ) {
> >     bar * ptr = cast(bar*)param;
> > }
> >
> > but will stop
> > int foo( int ** param ) {
> >     bar ** ptr = cast(bar**)(*param);
> > }
> > for being written as
> > int foo( int ** param ) {
> >     bar ** ptr = cast(bar**)param;
> > }
> >
> > int foo( int ** param ) {
> >     bar ** ptr = cast(int* to bar**)(*param);  // valid
> > }
> >
> > int foo( int ** param ) {
> >     bar ** ptr = cast(int* to bar**)(param); // not valid param is not
an
> > int*
> > }
> >
> > int foo( int  param ) {
> >     bar ** ptr = cast(int* to bar**)(param);  // invalid param is not
int*
> > }
> >
> > int foo( int param ) {
> >     bar ** ptr = cast(int* to bar**)(&param); // valid
> > }
>
> It does add some redundancy which will reduce some bugs, as you
illustrated.
> But when *** is cast to ** instead of *, it isn't caught.
>
if you write

func ( bar *** param ) {
    bar ** pp = cast( bar *** to bar ** )param;
    .....
}
instead of
func ( bar *** param ) {
    bar * pp = cast( bar *** to bar * )param;
    .....
}
nothing will every catch that error I accept that,
but what it does catch is changes in params/members and missing '&' and *'s
(no matter how many &*'s are involved as long as you've got the right types
in the cast expr)

and especially when passing params as void * to c, where you know what you
want you can write
func ( bar ** foo ) {
    void * pp = cast( bar *** to void * )&param; // has to have the & or its
an error
    .....
}
which will catch the missing & or *
[void * pp = cast( bar* to void*)*param;] {&param or param would cause
error}

or course you need to get the from type correct but as it stands

void * pp = cast(void*)*bar;
void * pp = cast(void*)bar;
void * pp = cast(void*)&bar;

are all valid and might be correct there is no way to get the compiler to check you've got the right number of &,* 's for what you think should be passed (be it Bar ******* or Bar*)

if this is not what you mean by 'But when *** is cast to ** instead of *, it
isn't caught.'
can you post an example please.


March 11, 2003
"Mike Wynn" <mike.wynn@l8night.co.uk> wrote in message news:b4lnf4$cik$1@digitaldaemon.com...
> if this is not what you mean by 'But when *** is cast to ** instead of *,
it
> isn't caught.'

It is what I meant, you have it right.


March 11, 2003
"Walter" <walter@digitalmars.com> wrote in message news:b4loik$d8q$1@digitaldaemon.com...
>
> "Mike Wynn" <mike.wynn@l8night.co.uk> wrote in message news:b4lnf4$cik$1@digitaldaemon.com...
> > if this is not what you mean by 'But when *** is cast to ** instead of
*,
> it
> > isn't caught.'
>
> It is what I meant, you have it right.
>

so am I right in assuming you do not see enough merit in having a two param
typecast, because the programmer can inform the cast to perform the wrong
action.
I (obviously) think its a step in the right direction and I can work around
it with a templated cast func (although template syntax is rather verbose)
or a nexted func to do the lhs typecheck.


April 04, 2003
"Mike Wynn" <mike.wynn@l8night.co.uk> wrote in message news:b4lrq6$lse$1@digitaldaemon.com...
> so am I right in assuming you do not see enough merit in having a two
param
> typecast, because the programmer can inform the cast to perform the wrong action.

Yes.

> I (obviously) think its a step in the right direction and I can work
around
> it with a templated cast func (although template syntax is rather verbose) or a nexted func to do the lhs typecheck.