Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > type_info, vtable

Reply
Thread Tools

type_info, vtable

 
 
tom_usenet
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 13:02:53 GMT, http://www.velocityreviews.com/forums/(E-Mail Removed) (Alf P. Steinbach)
wrote:

>On Fri, 22 Aug 2003 11:40:23 GMT, (E-Mail Removed) (tom_usenet) wrote:
>
>>For columns the situation is simple. The column index is known for a
>>particular 'dynamic_cast' statement at compile time. For rows the
>>situation is more complex. The row index is only found when the object
>>begin passed to the 'dynamic_cast' statement is known, and this is
>>only knowable in general at runtime. So isn't this row index then both
>>an explicit representation of a type (the 'constructor call' type),
>>and only knowable at run-time? Yes to the last, but no to the first:
>>it's not an explicit representation, it cannot be used to determine
>>anything about the type involved (except via additional and otherwise
>>unnecessary information).

>
>Just to pin down our differences, it's the "but no to the first", and
>the following justification, that I don't agree with.
>
>In my view an address of the constructor call stored in each (non-POD)
>object _is_ an explicit type representation, RTTI "Type Information".


Why is that an explicit type representation, while your throw row
index is not? You realise what I mean by a constructor call statement?
I don't mean the address of the constructor call (which would
identifiy a type directly), I just mean the instruction address of a
jump statement to that constructor. e.g.

A a; //constructor call statement 100, say.
A b; //constructor call statement 101, say.

At runtime, this map is built up:
(a's runtime address)->100
(b's runtime address)->101

This has nothing to do with the type. e.g. In another program:

A a; //statement 100
B b; //statement 101

>And it can easily be used to obtain information about the type, namely
>via 'dynamic_cast' to various destination types -- I just note in
>passing that if it were not so (which it is) it would not be a working
>implementation of 'dynamic_cast'.


Yes, this is true. However, equivalently, catch blocks can be used to
gain information about the runtime type of exceptions:

try
{
f();
}
catch(Type1& t)
{
}
catch(Type2& t)
{
}
//etc.

In the example above, at compile time you have no information at all
about the runtime type of the exception that will come through, if any
(except that it is one that is thrown somewhere), but you can use the
catch blocks to find out its runtime type.

>>Your argument is specious, since the fact that exception handling does
>>not require RTTI can be simply extended to an argument that
>>dynamic_cast doesn't require RTTI. Either your definition of RTTI is
>>wrong, or dynamic_cast doesn't require RTTI.

>
>Your assertion that dynamic_cast cannot be used to obtain information
>about the dynamic type is incorrect, and so that argument is a fallacy.
>
>But that does not mean that the definitions I know of RTTI are
>in some sense "correct".
>
>It does, however, mean that any definition of RTTI that doesn't
>require storage of an explicit type representation is a practically
>useless definition, void of meaning.


Ahh, now we're getting somewhere. You now say RTTI involves storing
along with an object information relating to its dynamic type, and I
agree that that is a reasonable definition. However, note that a
identical kind of type representation has to be stored along side a
thrown exception (say its throw statement "number", its type, or
whatever strange implementation you go for).

I'm starting to think that my argument is too subtle...

Tom
 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 14:26:00 GMT, (E-Mail Removed) (tom_usenet) wrote:

>On Fri, 22 Aug 2003 13:02:53 GMT, (E-Mail Removed) (Alf P. Steinbach)
>wrote:
>
>>On Fri, 22 Aug 2003 11:40:23 GMT, (E-Mail Removed) (tom_usenet) wrote:
>>
>>>For columns the situation is simple. The column index is known for a
>>>particular 'dynamic_cast' statement at compile time. For rows the
>>>situation is more complex. The row index is only found when the object
>>>begin passed to the 'dynamic_cast' statement is known, and this is
>>>only knowable in general at runtime. So isn't this row index then both
>>>an explicit representation of a type (the 'constructor call' type),
>>>and only knowable at run-time? Yes to the last, but no to the first:
>>>it's not an explicit representation, it cannot be used to determine
>>>anything about the type involved (except via additional and otherwise
>>>unnecessary information).

>>
>>Just to pin down our differences, it's the "but no to the first", and
>>the following justification, that I don't agree with.
>>
>>In my view an address of the constructor call stored in each (non-POD)
>>object _is_ an explicit type representation, RTTI "Type Information".

>
>Why is that an explicit type representation, while your throw row
>index is not?


Because the dynamic_cast information can be usefully employed by any
code it's passed to, e.g. to check whether it represents some given
type, or a type that is derived from some type, and so on. So one
difference between an explicit and an implicit representation is the
functionality available. Another difference for this particular
example is the memory consumption, O(K) versus O(n).



>You realise what I mean by a constructor call statement?


Yep, but I don't think the details of representation matter much.



>... catch blocks can be used to
>gain information about the runtime type of exceptions:
>
>try
>{
> f();
>}
>catch(Type1& t)
>{
>}
>catch(Type2& t)
>{
>}
>//etc.


In some weird sense, disregarding everything of relevance, this is
true.

But much more true: exception handling can only _lose_ explicit type
knowledge, not _gain_ more explicit knowledge than what was present
in the first place.

To perhaps better see this (or see it all, I'm beginning get exasperated),
consider a piece of code that is passed a pointer p. Via RTTI this code
can gain more explicit knowledge about the type of *p. Via exception
handling it can only lose some of the explicit knowledge it has.

This is the fundamental reason why exception handling cannot emulate
'dynamic_cast'.

Haven't we established that enough times?



>>It does, however, mean that any definition of RTTI that doesn't
>>require storage of an explicit type representation is a practically
>>useless definition, void of meaning.

>
>Ahh, now we're getting somewhere. You now say RTTI involves storing
>along with an object information relating to its dynamic type, and I
>agree that that is a reasonable definition.


Goody.



>However, note that a identical kind of type representation has to
>be stored along side a thrown exception (say its throw statement
>"number", its type, or whatever strange implementation you go for).


Not identical except in its direct representation. There is a difference
in available functionality, due to what is known _about_ that piece of
information. For 'dynamic_cast' maintaining that knowledge "about"
requires O(n) memory consumption, where n is the (maximum) number of
(simultanously existing) objects, so it's very real, and quantifiable.



>I'm starting to think that my argument is too subtle...


From my point of view, your argument is just a little bit confused.

Hardly surprising given the common misunderstanding that RTTI is
necessary for exception handling.

 
Reply With Quote
 
 
 
 
tom_usenet
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 14:07:54 GMT, (E-Mail Removed) (Alf P. Steinbach)
wrote:

>On Fri, 22 Aug 2003 13:43:57 GMT, (E-Mail Removed) (tom_usenet) wrote:
>
>> We know at the point of construction what row of the
>>>matrix to look at, but if we still know that at the dynamic_cast then we
>>>have associated a row-index with each object. Since there is a one-one
>>>correspondence between rows and types, this information can be said to
>>>be type information.

>>
>>There isn't necessarily such a one-to-one correspondence. If you have
>>one row per type, then some of the rows may be identical, which makes
>>the correspondance only many-to-one, strictly speaking.

>
>Strictly speaking that holds only for row contents; for row indexes
>the correspondence (with the optimized/reduced table) would be o.t.o.


Yes, I was assuming that with the optimized/reduced table, each row is
unique, so several types map to the same row. IOW, several types have
the same row index, and many object creations have the same row index.
How the compiler automagically works out the row index for a
particular bit of code that creates an object isn't really important,
as long as you note it doesn't have to be dependent on the type of the
object.

>>>The matrix of object creations and dynamic_casts along with the
>>>row-index to object association could certainly be used to implement
>>>exception handling, but the converse fails. The throw-catch matrix
>>>cannot emulate dynamic_cast, even if extended to include all object
>>>creations and dynamic_casts, because the row-index is not known at the
>>>site of the dynamic_cast.

>>
>>It is if the row index is placed inside the object (or its vtable), or
>>if a map of object address to row index is maintained.

>
>Buster mentioned that earlier, so presumably the above paragraph refers
>to the situation sans explicit type information. Get it?
>
>
>>This was my
>>point, that the matrix bit that was being bandied around could also
>>provide the basis of a dynamic_cast implementation, just as it could
>>provide the basis of an exception handling implementation.

>
>For exception handling the total amount of memory needed in addition
>to the matrix is constant.


Right, you can only throw one exception at a time. So you only need
the explicit type representation of that one exception (be that
representation in the form of a row index, a type_info object, or
whatever).

>For dynamic_cast it is O(n), where n is maximum number of simultanously
>existing objects.


Right. So you only need the explicit type representation of every
object (be that representation in the form of a row index, a type_info
object, or whatever).

>To me (but mind you, I'm not very sophisticated) that looks like a
>difference of some sort. _Could_ it be that it has something to do with
>explicit type representation? I just ask.


No, it is the difference between 1 "explicit type representation" and
n "explicit type representation"s, as I've stated in various ways in
various posts.

That is, if you choose to consider your row index thing an "explicit
type representation".

Tom
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 15:14:10 GMT, (E-Mail Removed) (tom_usenet) wrote:

>No, it is the difference between 1 "explicit type representation" and
>n "explicit type representation"s, as I've stated in various ways in
>various posts.
>
>That is, if you choose to consider your row index thing an "explicit
>type representation".


No, that's incorrect. Formally the reason is that exactly one
possibility (the case for exception handling) has _zero_ information
content, log 1 = 0; the case of 1 is very, very special. And so the
case of exactly one possibility makes an implicit representation
possible; it's not possible with more than one possibility, where
the non-zero information content must be explicit in some way.

Practically, ah, how can I phrase this?

Practically (searching, searching, searching) the throw statement id
in the compatibility matrix implementation of exception handling is
like an x86 16-bit "near" pointer, where the relevant memory segment is
implicit via both usage of the pointer and processor state, whereas
explicit type information in each object is like a full 32 or 48 bit
pointer, specifying all there is to know explicitly and in a way that
can easily be copied (without losing the implicit context), compared,
and so forth -- the functionality I spoke of earlier.

 
Reply With Quote
 
Rob Williscroft
Guest
Posts: n/a
 
      08-22-2003
tom_usenet wrote in news:(E-Mail Removed):

>>For exception handling the total amount of memory needed in addition
>>to the matrix is constant.

>
> Right, you can only throw one exception at a time. So you only need
> the explicit type representation of that one exception (be that
> representation in the form of a row index, a type_info object, or
> whatever).
>
>>For dynamic_cast it is O(n), where n is maximum number of simultanously
>>existing objects.

>
> Right. So you only need the explicit type representation of every
> object (be that representation in the form of a row index, a type_info
> object, or whatever).
>
>


Maybe I'm confused about dynamic_cast, but doesn't it require
a pointer or reference to an object with at least one virtual
function to work.

So it should only be nesaasaery to associate a dynamic typeid
with the vtable (or whatever is used) in order to do the
dynamic_cast.

I.e. the overhead would be O(n) where n is the number of dynamic
types (*) in the program, which is a constant.

(*) possibly ? plus the number of times they are inherited.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
 
Reply With Quote
 
Ron Natalie
Guest
Posts: n/a
 
      08-22-2003

"Rob Williscroft" <(E-Mail Removed)> wrote in message
> Maybe I'm confused about dynamic_cast, but doesn't it require
> a pointer or reference to an object with at least one virtual
> function to work.


Well in some cases it doesn't, but in most of the interesting cases
it does. Your observation is correct. All the places where RTTI
behaves polymorhically (dynamic_cast or typeinfo) requires a
polymorphic class (at least one virtual function). This is not a
coincidence, the idea was to not require the overhead of RTTI unless
the user was doing something polymorhically anyhow.

> I.e. the overhead would be O(n) where n is the number of dynamic
> types (*) in the program, which is a constant.


The incremental overhead to already polymorhic classes is a small
constant added to each types vtable. The overhead to non-polymorphic
class is the cost of including some typing feature (notably the vtable
pointer) which may be large if the objects are already small.



 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 15:42:40 GMT, (E-Mail Removed) (tom_usenet) wrote:

>If you call a particular function, all you know about the exception
>escaping is that it is restricted by the throw clause of that
>function. You can proceed to narrow down that type using catch blocks.


"That type" being the static type of the throw statement -- and what
is the point?

 
Reply With Quote
 
tom_usenet
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 15:55:03 GMT, (E-Mail Removed) (Alf P. Steinbach)
wrote:

>On Fri, 22 Aug 2003 15:42:40 GMT, (E-Mail Removed) (tom_usenet) wrote:
>
>>If you call a particular function, all you know about the exception
>>escaping is that it is restricted by the throw clause of that
>>function. You can proceed to narrow down that type using catch blocks.

>
>"That type" being the static type of the throw statement -- and what
>is the point?


Yes, but all dynamic_cast can do is give you the static type of the
object when it was created. What is the point?

Tom
 
Reply With Quote
 
Ivan Vecerina
Guest
Posts: n/a
 
      08-22-2003
"Ron Natalie" <(E-Mail Removed)> wrote in message
news:3f463ab7$0$17747$(E-Mail Removed) m...
| ............ All the places where RTTI
| behaves polymorhically ..............

You mean that there is such a thing as non-polymorphic RTTI ?

As I understand this usage, it seems to support that the type
matching mechanisms involved in EH may be labelled as "RTTI".

Do we owe this whole thread to a terminology misunderstanding?

Best regards,
Ivan
--
http://www.post1.com/~ivec


 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      08-22-2003
On Fri, 22 Aug 2003 15:42:40 GMT, (E-Mail Removed) (tom_usenet) wrote:

>On Fri, 22 Aug 2003 14:55:33 GMT, (E-Mail Removed) (Alf P. Steinbach)
>wrote:
>
>>>Why is that an explicit type representation, while your throw row
>>>index is not?

>>
>>Because the dynamic_cast information can be usefully employed by any
>>code it's passed to, e.g. to check whether it represents some given
>>type, or a type that is derived from some type, and so on. So one
>>difference between an explicit and an implicit representation is the
>>functionality available. Another difference for this particular
>>example is the memory consumption, O(K) versus O(n).

>
>The functionality available is identical - you can check the "thing"
>(exception or object) to see whether it is derived from a particular
>type.


And George W. _is_ an earthworm.

Yes, you can check whether the "thing" is derived from a particular
type T, as long as that happens in the context of exception handling,
and type T happens to be the type of the 'catch' clause of the currently
examined frame, or a base class of that type.

No, you cannot check the "thing" to see whether it is derived from
any arbitrary type T, for to do that you need some way to obtain the
column index for any arbitrary type T, assuming a matrix that needlessly
contain information about all types. And exception handling does _not_
require this functionality, nor the complete all-types matrix, which is
required for RTTI. Hence, again, exception handling does not require
RTTI, and it can use optimizations that renders the mechanism unsuitable
as a platform for implementing RTTI.

I'm not sure whether the implied question was about that, though.

If the question is still about the difference between explicit and
implicit, consider that with the ability to obtain the matrix index
of any arbitrary type T, call that function <g> 'typeid', the code
can know that a particular index represents a particular type. And
furthermore, it can check whether an index represent any particular
type. That is an explicit representation; via the added functionality
of the 'typeid' function the index contains enough information to be
meaningful on its own, not just in a particular, limited context.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
can some one please demystify vtable/vftable Paul C++ 1 06-24-2004 08:43 AM
HELP: wxValidator and undefined reference to `vtable ...` under linux Quansheng Liang C++ 2 05-25-2004 01:17 PM
Undefined symbols: vtable for Foo r C++ 2 08-02-2003 08:18 PM
A::A[not-in-charge]() undefined reference to `vtable for A' Daniel Heiserer C++ 1 08-01-2003 04:05 PM
I am confused with VTable ;-) Pani C++ 2 07-23-2003 10:50 AM



Advertisments