Topic: Add dynamic_cast<type_info&>


Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/09/07
Raw View
"Etay Bogner" <Etay_Bogner@mail.stil.scitex.com> writes:

>[...] why not have a dynamic_cast<type_info&) ?
>
>So one can pass a type_info, which was NOT obtained via typeid(), to a
>function which will, among others, use dynamic_cast ...

I don't understand your suggestion.  I suspect that it is a half-baked
idea which when analyzed will turn out to not make any sense.  But if
you are willing to explain it, I'm willing to explore it further.

The syntax `dynamic_cast<type_info&>(foo)' already has a defined
meaning.  Were you proposing to change this?  If so, what semantics
do you propose, and how do they differ from the existing semantics?

Or were you proposing to define semantics for `dynamic_cast<bar>(foo)'
in the case where `bar' is type `type_info'?  (In that case, shouldn't
you have said dynamic_cast<const type_info&>?  Why require the
type_info to be a modifiable lvalue?)  If you were proposing to define
semantics for `dynamic_cast<bar>(foo)', what would be the static type
of that expression?  What would be the behaviour at run-time?

--
Fergus Henderson             |  #define x t=a[i],a[i]=a[m],a[m]=t
                             |  char a[]=" 12345678";main(m,i,j,t){for(i=m;i<
fjh@cs.mu.oz.au              |  9;x,i++)for(x,j=m;--j?(t=a[m-j]-a[m])-j&&t+j:
http://www.cs.mu.oz.au/~fjh  |  main(m+1)*0;);m-9||puts(a+1);} /* 8 queens */

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: Etay_Bogner@mail.stil.scitex.com (Etay Bogner)
Date: 1995/09/08
Raw View
In article <42nsuv$bqf@engnews2.Eng.Sun.COM>, clamage@Eng wrote:

>> I don't see what problem you are trying to solve. The expression
>>         typeid(p)
>> returns a 'const type_info&'. If given a pointer to a polymorphic type,
>> it returns the type of the actual object; otherwise it returns the static
>> type of the expression. What programs are made simpler by giving special-
>> case semantics to dynamic_cast instead of just writing 'typeid', which seems
>> to be what you want anyway?

When you write an object IO mechanism, you encounter the following problem :

When you READ ( LOAD ) an object from the data base, what type will you RETURN ?

There are several solutions to object IO, and I have another one too, but
the problem is the same.

A natural interface to such a mechanism is ( from the USER prespective ) :

try {
    A* a;
    Load(a); // here I have a nicer interface, but that's not the issue
    }
catch (bad_cast& cast) {
    }

meaning that the user THINKS that now he would get an A ( or something
derived from it ), or in other words "GIVE ME THE NEXT A in the data
base", and if not he would get a "bad_cast" exception, for example.

Now, how would you write such a template ( for Load ):

void* readNextObjectFromDataBase(); // this is actually something like a
virtual function

template <class T>
void Load(T*& t) {
    t = dynamic_cast<T*>(readNextObjectFromDataBase()); // this is NOT accepted
    }

It must be clear that "readNextObjectFromDataBase()" has a pointer to the
complete object and of course that it has it's type id.

So the question is "how to cast that void* to T* ?".

Facts :

1) The objects are not derived from a common base.

2) "readNextObjectFromDataBase()" has all the information to do the dynamic_cast
PER type. Again ,think of it as a virtual function.

3) "readNextObjectFromDataBase()" must have the SAME interface for all
types ( and that's not new ).

4) So, readNextObjectFromDataBase() can return void* only or a pair<const
type_info&, void*>.
you can't write in Load the dynamic cast from a void*, so you can't write Load


5) my solution : re-write "readNextObjectFromDataBase()" so it will accept
a 'const type_info&' so it CAN write the dynamic_cast and return a void*
to T*.

so that becomes :

void* readNextObjectFromDataBase(const type_info&); // this is actually
something like a virtual function

template <class T>
void Load(T*& t) {
    t = static_cast<T*>(readNextObjectFromDataBase(typeid(T*))); // this
IS accepted, and perfectly OK, if no exception was thrown
    }

A bad_cast exception is thrown from "readNextObjectFromDataBase()" if needed.

So, finally, since the implementations today act as if they send a 'const
type_info&' as a parameter to dynamic_cast, why not use it ?

Actually, I solved the problem by saving enough information, and the only
limitation is that you can't use the SAME data base between platforms, or
even compilers on the same platform.

Etay.

-- Etay Bogner,
-- Etay_Bogner@mail.stil.scitex.com,
-- Scitex Corp.
-- Israel.
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: Etay_Bogner@mail.stil.scitex.com (Etay Bogner)
Date: 1995/09/08
Raw View
(A copy of this message has also been posted to the following newsgroups:
comp.std.c++)

In article <MATT.95Sep8112137@physics2.Berkeley.EDU>,
fjh@munta.cs.mu.OZ.AU (Fergus Henderson) wrote:

>> I already know that the static type of `dynamic_cast<T*>(p)' is `T*',
>> because `dynamic_cast<T*>(p)' is already part of standard C++.
>> What I am asking about is the static type of your newly proposed syntax
>> `dynamic_cast<bar>(foo)', where `bar' is a value of type type_info, not
>> a type.
>>
>> I think your idea doesn't make sense, because there *isn't* any sensible
>> static type for that expression.  Since C++ is a statically typed language,
>> every expression must have a static type, but that expression can't have
>> one.  Therefore it doesn't work in C++.

The sensible static type for that expression will be a 'void*'.

I know this sounds ugly, but so does 'dynamic_cast<void*>(p)', which as
I'm sure you know, returns a pointer to the complete object, but in the
form of a void*.

The issue here is that one has the ability to 'cast-down' to the complete
object, using 'dynamic_cast<void*>(p)' ( meaning, without knowing the
complete type type) and getting a void*, but no ability to 'cast-up' ( an
implicit procedure in C++ ) without knowing the sub-type type at compile
time.

This is needed in the same cases it is needed when using the returned
pointer from 'dynamic_cast<void*>(p)', to do the inverse-operation.

Please look at another article of mine in this thread for a usage and an
implementation.

Etay.

-- Etay Bogner,
-- Etay_Bogner@mail.stil.scitex.com,
-- Scitex Corp.
-- Israel.
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: Etay Bogner <Etay_Bogner@mail.stil.scitex.com>
Date: 1995/09/08
Raw View
In article <MATT.95Sep7112147@physics10.Berkeley.EDU>,
fjh@munta.cs.mu.OZ.AU (Fergus Henderson) wrote:

>> Or were you proposing to define semantics for `dynamic_cast<bar>(foo)'
>> in the case where `bar' is type `type_info'?  (In that case, shouldn't
>> you have said dynamic_cast<const type_info&>?  Why require the
>> type_info to be a modifiable lvalue?)  If you were proposing to define
>> semantics for `dynamic_cast<bar>(foo)', what would be the static type
>> of that expression?  What would be the behaviour at run-time?

Fergus,

I know my article wasn't that clear, so I'll explain again :

Yes, what I ment was 'dynamic_cast<bar>(foo)' where 'bar' is a 'const
type_info&'.

First, the usage :

A 'const type_info&' is stored somewhere, and I want to use this data to
try and cast a pointer ( or a reference ) to the type that is represented
by the stored type_info.

The implementation :

I've seen two compilers that implemented dynamic_cast. In both, the
expression 'dynamic_cast<T*>(p)' was translated to a function call ( a
runtime library function, of course ), and the parameters were the RTTI
object, and some other stuff for p, including the RTTI object of the
static type of p. 'RTTI object' is something that can actually be the
known type_info& object returned from typeid.

A simple implementation of 'typeid' will be to have a pointer in the
virtual table to point to an 'extended' type_info structure, meaning that
the type_info structure that we know from 'typeinfo.h' has actually more
fields. That's why you can't copy it or derive from it ( it has only one
constructor, the copy-constructor, which is private, and the operator= is
also private ).

So, the conclusion from this SHORT study-case, is that the STATIC type in
the expression 'dynamic_cast<T*>(p)' is NOT a static type at all.



Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/09/08
Raw View
Etay Bogner <Etay_Bogner@mail.stil.scitex.com> writes:

>fjh@munta.cs.mu.OZ.AU (Fergus Henderson) wrote:
>
>>> If you were proposing to define
>>> semantics for `dynamic_cast<bar>(foo)', what would be the static type
>>> of that expression?  What would be the behaviour at run-time?
[...]
>A 'const type_info&' is stored somewhere, and I want to use this data to
>try and cast a pointer ( or a reference ) to the type that is represented
>by the stored type_info.
[...]
>So, the conclusion from this SHORT study-case, is that the STATIC type in
>the expression 'dynamic_cast<T*>(p)' is NOT a static type at all.
>
>From here, it's easy to understand that the STATIC RETURN TYPE of the
>exspression 'dynamic_cast<T*>(p)' should be T*, as it is now.

I already know that the static type of `dynamic_cast<T*>(p)' is `T*',
because `dynamic_cast<T*>(p)' is already part of standard C++.
What I am asking about is the static type of your newly proposed syntax
`dynamic_cast<bar>(foo)', where `bar' is a value of type type_info, not
a type.

I think your idea doesn't make sense, because there *isn't* any sensible
static type for that expression.  Since C++ is a statically typed language,
every expression must have a static type, but that expression can't have
one.  Therefore it doesn't work in C++.

>So, what I'm actually saying is that if it's possible to perform the
>dynamic_cast without knowing the T being used, why not do so ?

Because in fact it is not possible, unless the result of the dynamic_cast
is discarded.  The reason the compiler needs to know the type is
so that it can statically typecheck the containing expression.

>My suggestion is that if the compiler encounters an expression like :
>
>'dynamic_cast<ATypeInfo>(p)' were ATypeInfo is a 'const type_info&'
>
>the compiler won't try to cast p to ATypeInfo, which will ALWAYS fail, but
>it will try to cast p to the type ATypeInfo contains data for.

And supposing the compiler encounters an expression like

 int f(const type_info& ATypeInfo) {
  int x = dynamic_cast<ATypeInfo>(p);
  return x;
 }

what is the compiler going to do then?  Type-check the initialization
of `x' at run-time?  I suppose that would be do-able, but it wouldn't
be easy, and it certainly wouldn't be C++.

--
Fergus Henderson             |  #define x t=a[i],a[i]=a[m],a[m]=t
                             |  char a[]=" 12345678";main(m,i,j,t){for(i=m;i<
fjh@cs.mu.oz.au              |  9;x,i++)for(x,j=m;--j?(t=a[m-j]-a[m])-j&&t+j:
http://www.cs.mu.oz.au/~fjh  |  main(m+1)*0;);m-9||puts(a+1);} /* 8 queens */

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: Etay_Bogner@mail.stil.scitex.com (Etay Bogner)
Date: 1995/09/09
Raw View
In article <MATT.95Sep8112137@physics2.Berkeley.EDU>,
fjh@munta.cs.mu.OZ.AU (Fergus Henderson) wrote:

>> I already know that the static type of `dynamic_cast<T*>(p)' is `T*',
>> because `dynamic_cast<T*>(p)' is already part of standard C++.
>> What I am asking about is the static type of your newly proposed syntax
>> `dynamic_cast<bar>(foo)', where `bar' is a value of type type_info, not
>> a type.
>>
>> I think your idea doesn't make sense, because there *isn't* any sensible
>> static type for that expression.  Since C++ is a statically typed language,
>> every expression must have a static type, but that expression can't have
>> one.  Therefore it doesn't work in C++.

The sensible static type for that expression will be a 'void*'.

I know this sounds ugly, but so does 'dynamic_cast<void*>(p)', which as
I'm sure you know, returns a pointer to the complete object, but in the
form of a void*.

The issue here is that one has the ability to 'cast-down' to the complete
object, using 'dynamic_cast<void*>(p)' ( meaning, without knowing the
complete type type) and getting a void*, but no ability to 'cast-up' ( an
implicit procedure in C++ ) without knowing the sub-type type at compile
time.

This is needed in the same cases it is needed when using the returned
pointer from 'dynamic_cast<void*>(p)', to do the inverse-operation.

Please look at another article of mine in this thread for a usage and an
implementation.

Etay.

-- Etay Bogner,
-- Etay_Bogner@mail.stil.scitex.com,
-- Scitex Corp.
-- Israel.

---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]