September 24, 2003
"Philippe Mori" <philippe_mori@hotmail.com> wrote in message news:bkqfd3$1fkc$1@digitaldaemon.com...
> If the object.cast syntax is used, then we might want to be able to define our cast to a given type :
>
> class C {
>     operator castTo(D) { return ... }
>     operator castTo(E) { return ... }
>
>     template (T)
>     operator castTo(T) { return member.castTo(T); }
> }

Sure!  But we would need some official way to accept a _type_ as a function parameter!

> OTHO, if we uses a syntax like cast(B, b), we should be able to define our owns casting functions that works the same way:

I really don't like this syntax;  it's confusing which comes first, the type or the rvalue.

Sean


September 24, 2003
Philippe Mori wrote:
> If the object.cast syntax is used, then we might want to be able
> to define our cast to a given type :
> 
> class C {
>     operator castTo(D) { return ... }
>     operator castTo(E) { return ... }
> 
>     template (T)
>     operator castTo(T) { return member.castTo(T); }
> }

This introduces the possibility to mess with some assumptions we have about casting.

For example, it should be possible to cast the object that is returned by castTo back to the original type. This would have to be explicitly supported by the programmer the returned object.

I'm not sure wether this is necessarily such a bad thing, though. After all, operator overloads can always cause stuff like this. On the other hand, this seems like it could get complicated pretty quickly. Imagine the following case:

class A
{
	B b;
	C c;

	operator castTo(B) { return b; }
	operator castTo(C) { return c; }
};

A a;

//This works
a.castTo(C);

//And this works;
a.castTo(B);

//Then this should work as well
a.castTo(B).castTo(C)


So B would not only have to know how it can be casted back to A, but it should also know how to cast to the "sister" interface C.

Note that this concept is pretty similar to the way Microsoft's COM and the QueryInterface method works. MS uses this quite a bit to implement interfaces using aggregated objects. Does anyone have sufficient experience with this to offer an opinion on wether it is worth the trouble?

Hauke


September 24, 2003
I like this kind of cast. I. e. variable.doCast(newType) etc...



In article <bkrjpa$vg$1@digitaldaemon.com>, Sean L. Palmer says...
>
>Nah, Ant's form is better.  Clearer.
>
>b.cast(B).func();
>
>Works even if B is a complicated typespec;  easy to parse;  easy to read. Self-documenting.
>
>myObjectPtr[n].cast(myFoo*[])[i]->DoFooStuff("foo baby".cast(wchar[]));
>
>This is good.  I like it better than the cast D has now.
>
>DMD still hasn't gotten rid of C's typecast!  I thought the D spec doesn't support C typecasts?
>
>Sean
>
>"Antti Sykäri" <jsykari@gamma.hut.fi> wrote in message news:slrnbn1eo0.dbp.jsykari@pulu.hut.fi...
>> > In article <bkq9th$17fn$1@digitaldaemon.com>, Dario says...
>> >> I would prefer something like:
>> >>    class A {}
>> >>    class B:A {void func(){}}
>> >>    A b = new B;
>> >>    B.cast(b).func();
>>
>> I stared that for a moment and thought that you surely made a typo there and actually meant to write:
>>
>> b.cast(B).func();
>>
>> Which kind of makes sense.
>>
>> (similarly as Ant suggested:)
>>
>> In article <bkqaoi$18hk$1@digitaldaemon.com>, Ant wrote:
>> >
>> > Yes! finally something that makes sense!
>> > We have been waiting for this for decades.
>> >
>> > ? b.castTo(B).func() ?
>>
>> How about:
>>
>> cast(B, b).func()
>>
>> cast(B: b).func();
>>
>> cast(B; b).func(); // Syntax a bit similar to foreach(); emphasizes that
>>                    // cast is not just any function
>>
>> or even
>>
>> cast(b, B).func();
>> cast(b to B).func();
>> cast(b as B).func();
>> cast(b -> B).func(); // too bad -> already has a meaning
>> cast(b: B).func();
>> cast(B b).func();
>>
>> cast(B) b.func(); // Java style, huh?
>>
>> (cast(B) b).func(); // What we have now. Cluttered.
>>
>> But for what it's worth, D isn't trying to be Java, so well-written programs contain very few casts anyway and those that remain deserve to stand out. Right?
>>
>> -Antti
>>
>
>


September 24, 2003
> > If the object.cast syntax is used, then we might want to be able to define our cast to a given type :
> >
> > class C {
> >     operator castTo(D) { return ... }
> >     operator castTo(E) { return ... }
> >
> >     template (T)
> >     operator castTo(T) { return member.castTo(T); }
> > }
>
> Sure!  But we would need some official way to accept a _type_ as a
function
> parameter!
>

I think this would surely be a good thing to accept a type as a function parameter and it would be interesting for metaprogramming. Here a simple example for a factory:

    class Base { }
    class Der1 : Base { }
    class Der2 : Base { }
    class Der3 : Base { }

    Base CreateObject(type t, int arg1, int arg2)
    {
        return new t(arg1, arg2);
    }

    Base a = CreateObject(Der1, 5, 3);
    Base b = CreateObject(typeof(a), 6, 4);

But for casting purpose this is not strictly necessary since in
C++ we have conversion operator but we do not have
type function parameters:

    class C {    // C++ sample
    public:
        // the typename give the operator name.
        // for complex type a typedef might be required.
        operator double() const { return 23.4; }

        // template is even supported...
        // Here we allows any supported conversion from a member
        template <typename T>
        operator T { return member; }

        M member;
    };

So IMHO, we should choose the syntax mainly according to the following rules:

- easy to uses and to read.
- consistent with the language (template, predefine members syntax,...)

> > OTHO, if we uses a syntax like cast(B, b), we should be able to define our owns casting functions that works the same way:
>
> I really don't like this syntax;  it's confusing which comes first, the
type
> or the rvalue.

I see... and with Ant sample, I see why this syntax is not elegant for complex expression in which there are multiples casts...

>
> Sean
>
>


September 24, 2003
> > If the object.cast syntax is used, then we might want to be able to define our cast to a given type :
> >
> > class C {
> >     operator castTo(D) { return ... }
> >     operator castTo(E) { return ... }
> >
> >     template (T)
> >     operator castTo(T) { return member.castTo(T); }
> > }
>
> This introduces the possibility to mess with some assumptions we have about casting.
>

In C++, we can define our owns conversion functions... The biggest problem we have in C++ are:

- unintended conversion (a conversion that is not always desirable), like the conversion from some string classes to const char * or some automatic pointers classes to the pointer.


- ambiguities when a class allows conversion to a class that accept original type in one of its constructor:

    class A;
    class B {
    public:
        operator A() const;
    };

    class A {
    public:
        A (B const &b) { }
    };

> For example, it should be possible to cast the object that is returned by castTo back to the original type. This would have to be explicitly supported by the programmer the returned object.
>

Enven in the language not all casts allows to returns to the original exactly:

    double d = 1.2;
    int i = cast(int) d;
    double d2 = cast(double) i;

    d will be different than d2 (but in that case, the cast is allowed).

> I'm not sure wether this is necessarily such a bad thing, though. After all, operator overloads can always cause stuff like this. On the other hand, this seems like it could get complicated pretty quickly. Imagine the following case:
>
> class A
> {
> B b;
> C c;
>
> operator castTo(B) { return b; }
> operator castTo(C) { return c; }
> };
>
> A a;
>
> //This works
> a.castTo(C);
>
> //And this works;
> a.castTo(B);
>
> //Then this should work as well
> a.castTo(B).castTo(C)
>
>
> So B would not only have to know how it can be casted back to A, but it should also know how to cast to the "sister" interface C.
>
> Note that this concept is pretty similar to the way Microsoft's COM and the QueryInterface method works. MS uses this quite a bit to implement interfaces using aggregated objects. Does anyone have sufficient experience with this to offer an opinion on wether it is worth the
trouble?

For COM stuff, we need to be able to delegate to the outer object. That is the subobjects b and c need to be able to get the this pointer of the A object that contains them.

IMO, the cleanest way to handled that would be to support local classes that have access to the outer class.

In such a case, COM compatible casting would be easy to implement
provide that cast operator have priority over predefined cast (to ensure
that casting to IUnknown or I2 in the example below will return the proper
interface).

Also for COM programming, with need 2 casting operators: One that
do the casting for a given object and one that forward casting to the
outer object (otherwise, we would have infinite loops or case where
the identity won't be respected (i.e. for I2 we always want to returns
either A or C object - not sometime ones and other times the other-
and that without depending on the source of the cast).

class A : I1, I2 {
    local class B : I2 {
        template (T) operator castTo(T) { return outer.castTo(T); }
    } b;

    local class C : I3 {
        template (T) operator castTo(T) { return outer.castTo(T); }
    } c;

    operator castTo(I2) { return b.internal_castTo(I2) }
    operator castTo(I3) { return c.internal_castTo(I3) }
}

So to implement COM interface casting, which might be great for COM programming, I think we need some extra casting operators. In essence, we need an operator that is called by QueryInterface for each subobject. That operator will then forward to the outer object which will the uses our internal casting.

Also we need blind query... but that we be done with a template and verifying the result of the cast....

>
> Hauke
>
>


September 25, 2003
Antti Sykäri:
> I stared that for a moment and thought that you surely made a typo there
> and actually meant to write:
> b.cast(B).func();
> Which kind of makes sense.

That wan't a typo! ;-)
I thought of that because Ant's version is complicated to parse
(function don't get types as parameters).
Anyway I am convinced that Ant's version is more intuitive too.

I noticed that there are no comments from Walter...
Walter, what do you think? You aren't going to keep the
prefix cast, are you?


December 03, 2003
"Dario" <supdar@yahoo.com> wrote in message news:bkvsqs$26e9$1@digitaldaemon.com...
> Antti Sykäri:
> > I stared that for a moment and thought that you surely made a typo there
> > and actually meant to write:
> > b.cast(B).func();
> > Which kind of makes sense.
>
> That wan't a typo! ;-)
> I thought of that because Ant's version is complicated to parse
> (function don't get types as parameters).
> Anyway I am convinced that Ant's version is more intuitive too.
>
> I noticed that there are no comments from Walter...
> Walter, what do you think? You aren't going to keep the
> prefix cast, are you?

The postfix cast does look good, but I don't see it has much advantage over the prefix cast.


December 03, 2003
"Walter" <walter@digitalmars.com> wrote in message news:bqjfni$nc0$1@digitaldaemon.com...
>
> "Dario" <supdar@yahoo.com> wrote in message news:bkvsqs$26e9$1@digitaldaemon.com...
> > Antti Sykäri:
> > > I stared that for a moment and thought that you surely made a typo
there
> > > and actually meant to write:
> > > b.cast(B).func();
> > > Which kind of makes sense.
> >
> > That wan't a typo! ;-)
> > I thought of that because Ant's version is complicated to parse
> > (function don't get types as parameters).
> > Anyway I am convinced that Ant's version is more intuitive too.
> >
> > I noticed that there are no comments from Walter...
> > Walter, what do you think? You aren't going to keep the
> > prefix cast, are you?
>
> The postfix cast does look good, but I don't see it has much advantage
over
> the prefix cast.

Looks too much like a function call to me. What's wrong with cast(B, b) ?

I agree that the prefix cast must die.


December 03, 2003
"Matthew Wilson" <matthew.hat@stlsoft.dot.org> wrote in message news:bqjrg3$19kg$1@digitaldaemon.com...
> > > I noticed that there are no comments from Walter...
> > > Walter, what do you think? You aren't going to keep the
> > > prefix cast, are you?
> >
> > The postfix cast does look good, but I don't see it has much advantage
> over
> > the prefix cast.
>
> Looks too much like a function call to me. What's wrong with cast(B, b) ?
>
> I agree that the prefix cast must die.

Because it is not immediately obvious which of cast's two parameters are the thing to be casted, and which is the type to cast to.

b.cast(B) is much clearer in this regard, which is why everybody was
promoting it back then.  Apparently Walter is just getting to that
discussion.  ;)

B.cast(b) might work.  Either way, it might need to have some extra
parenthesis, like this:

(new b).cast(B)

(B*).cast(b);

I wish a good cast syntax would be chosen, but picking one is not easy, it's all bad.

Sean


December 03, 2003
> > > > I noticed that there are no comments from Walter...
> > > > Walter, what do you think? You aren't going to keep the
> > > > prefix cast, are you?
> > >
> > > The postfix cast does look good, but I don't see it has much advantage
> > over
> > > the prefix cast.
> >
> > Looks too much like a function call to me. What's wrong with cast(B, b)
?
> >
> > I agree that the prefix cast must die.
>
> Because it is not immediately obvious which of cast's two parameters are
the
> thing to be casted, and which is the type to cast to.
>
> b.cast(B) is much clearer in this regard, which is why everybody was
> promoting it back then.  Apparently Walter is just getting to that
> discussion.  ;)
>
> B.cast(b) might work.  Either way, it might need to have some extra
> parenthesis, like this:
>
> (new b).cast(B)
>
> (B*).cast(b);
>
> I wish a good cast syntax would be chosen, but picking one is not easy,
it's
> all bad.

cast<B>(b) ??