By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,750 Members | 1,221 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,750 IT Pros & Developers. It's quick & easy.

type_info, vtable

P: n/a
What is a type_info function, more particularly, what is a type_info node?
Are these related to the vtable by any means?
I have seen linker errors such as:
"undefined reference to SomeClass type_info node" or
"undefined reference to SomeClass type_info function"

What does that really mean? What is the linker looking for?

Thanks.
Jul 19 '05 #1
Share this Question
Share on Google+
54 Replies


P: n/a
"sks_cpp" <sk*****@hotmail.com> wrote in message
news:Nn*******************@news2.central.cox.net.. .
| What is a type_info function, more particularly, what is a type_info node?
| Are these related to the vtable by any means?

Somewhat. In several implementations, the vtable stores the address of
the type_info data structure.
This data structure is used to implement Run-Time Type Identification
(RTTI),
a feature which is required for exception handling, dynamic_cast calls,
and the implementation of the typeid operator (see header <typeinfo>).

| I have seen linker errors such as:
| "undefined reference to SomeClass type_info node" or
| "undefined reference to SomeClass type_info function"

Some C++ compiler implementations allow to enable/disable support
for RTTI. You probably need to enable it for some files...
hth
--
Ivan Vecerina <> http://www.post1.com/~ivec
Brainbench MVP for C++ <> http://www.brainbench.com


Jul 19 '05 #2

P: n/a
Ivan Vecerina wrote:
This data structure is used to implement Run-Time Type Identification
(RTTI), a feature which is required for exception handling,


RTTI isn't need for exception handling, neither would it be sufficient.

Jul 19 '05 #3

P: n/a
"Rolf Magnus" <ra******@t-online.de> wrote in message
news:bh*************@news.t-online.com...
| Ivan Vecerina wrote:
|
| > This data structure is used to implement Run-Time Type Identification
| > (RTTI), a feature which is required for exception handling,
|
| RTTI isn't need for exception handling, neither would it be sufficient.

I did not claim it was sufficient.

But RTTI is needed to match catch handlers with exceptions.
Consider:

#include <vector>
#include <string>
#include <iostream>
#include <exception>
int main()
{
try {
std::vector<std::string> tooBig(1UL<<31,"just some string");
}
catch(std::exception& x) {
std::cerr << "Failure: "<<x.what()<<std::endl;
}
}

How would the C++ run-time handle a failure of this memory allocation
without RTTI?
Regards,
Ivan
--
http://www.post1.com/~ivec
Jul 19 '05 #4

P: n/a
On Tue, 19 Aug 2003 15:29:37 +0200, "Ivan Vecerina" <iv**@myrealbox.com> wrote:
Consider:

#include <vector>
#include <string>
#include <iostream>
#include <exception>
int main()
{
try {
std::vector<std::string> tooBig(1UL<<31,"just some string");
}
catch(std::exception& x) {
Preferably use

catch( std::exception const& x )

std::cerr << "Failure: "<<x.what()<<std::endl;
}
}

How would the C++ run-time handle a failure of this memory allocation
without RTTI?


The actual types are not needed at run-time, only the compatibility
matrix of catches and throws.

That abstract matrix can be optimized in umpteen ways.

One way, but not the only way, is to use RTTI.

Jul 19 '05 #5

P: n/a

"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f****************@News.CIS.DFN.DE...
On Tue, 19 Aug 2003 15:29:37 +0200, "Ivan Vecerina" <iv**@myrealbox.com>

wrote:

How would the C++ run-time handle a failure of this memory allocation
without RTTI?


The actual types are not needed at run-time, only the compatibility
matrix of catches and throws.

That abstract matrix can be optimized in umpteen ways.

One way, but not the only way, is to use RTTI.


Furthermore, exception handling uses compile-time types,
not run-time (e.g. dynamic) types. Try this example:

#include <iostream.h>

struct Base
{
virtual ~Base()
{
}
};

struct Derived : public Base
{
};

int main()
{
Base *p = new Derived;

try
{
throw *p;
}
catch( const Derived & )
{
cout << "Derived" << endl;
}
catch( const Base & )
{
cout << "Base" << endl;
}
catch( ... )
{
cout << "<unknown>" << endl;
}

delete p;

return 0;
}

This program prints "Base".

Cheers!

- Risto -

Jul 19 '05 #6

P: n/a
On Tue, 19 Aug 2003 19:48:09 +0200, "Ivan Vecerina" <iv**@myrealbox.com> wrote:
"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f****************@News.CIS.DFN.DE...
| On Tue, 19 Aug 2003 15:29:37 +0200, "Ivan Vecerina" <iv**@myrealbox.com>
wrote:
| > try {
| > std::vector<std::string> tooBig(1UL<<31,"just some string");
| > }
| > catch(std::exception& x) {
|
| Preferably use
|
| catch( std::exception const& x )
Agreed.

| > std::cerr << "Failure: "<<x.what()<<std::endl;
| > }
| > }
| >
| >How would the C++ run-time handle a failure of this memory allocation
| >without RTTI?
|
| The actual types are not needed at run-time, only the compatibility
| matrix of catches and throws.
|
| That abstract matrix can be optimized in umpteen ways.
|
| One way, but not the only way, is to use RTTI.

Actually, the exact same thing can be said of dynamic_cast:
you only need a compatibility matrix of source and destination types.
I see where the confusion stems from now.

No, dynamic cast is a very different. With 'throw' the compiler knows
the exact type of the argument. With 'dynamic_cast' the argument can
be a pointer to an object that according to the standard must have its
dynamic type checked (a pointer to 'throw' is not checked for dyntype).
Clearly, Exception Handling does require a form of run-time type
identification (albeit this RTTI does not formally need to
rely on a data structure known to the linker as 'type_info').
Nope.

Let's just put things in the context of the OP, who was requesting
information on why his linker reported missing 'type_info' nodes.
I explained which language features may "require" them, and that
enabling RTTI is probably the way to have them generated.

Was this incorrect?


That I don't know...

Jul 19 '05 #7

P: n/a
"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f****************@News.CIS.DFN.DE...
| On Tue, 19 Aug 2003 19:48:09 +0200, "Ivan Vecerina" <iv**@myrealbox.com>
wrote:
| >"Alf P. Steinbach" <al***@start.no> wrote in message
| >news:3f****************@News.CIS.DFN.DE...
| >| The actual types are not needed at run-time, only the compatibility
| >| matrix of catches and throws.
| >|
| >| That abstract matrix can be optimized in umpteen ways.
| >|
| >| One way, but not the only way, is to use RTTI.
| >
| >Actually, the exact same thing can be said of dynamic_cast:
| >you only need a compatibility matrix of source and destination types.
|
| I see where the confusion stems from now.
|
| No, dynamic cast is a very different. With 'throw' the compiler knows
| the exact type of the argument.

Yes, just as when a new object is created (e.g. with the 'new' operator).

| With 'dynamic_cast' the argument can
| be a pointer to an object that according to the standard must have its
| dynamic type checked (a pointer to 'throw' is not checked for dyntype).

And when a catch clause is encountered during stack unwinding, the
dynamic type of the exception being thrown (and eventually re-thrown)
needs to be matched with the type of the catch clause.

For dynamic_cast as well, the compiler could make some static program
analysis and establish that the provided object has to be of a specific
type. The fact is, in practice, this would be too difficult.
And it would be about as difficult to pre-match try and catch clauses.

When compiling a throw clause, the catch handlers that will be on the
call stack are not known. Reciprocally, when compiling a try-catch block,
the throw statements that may be invoked are unknown. So the matching
of these two types somehow has to happen at run-time.

For dynamic_cast, RTTI involves the matching of a type identifier
which is defined during object creation (and typically stored within
the vtbl of an object, with a locally known type.
For Exception Handling, RTTI involves the matching of a type identifier
somehow defined at an unknown throw point, with the locally known
type of a catch clause (or reciprocally).
It just isn't that much different. And as far as I know (from the last
time I checked the internals of a C++ runtime core), the same kind of
type information is typically used to implement both these mechanisms.
Kind regards,
Ivan
--
http://www.post1.com/~ivec
Jul 19 '05 #8

P: n/a
On Wed, 20 Aug 2003 16:30:22 +0200, "Ivan Vecerina" <iv**@myrealbox.com> wrote:
"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f****************@News.CIS.DFN.DE...
| On Tue, 19 Aug 2003 19:48:09 +0200, "Ivan Vecerina" <iv**@myrealbox.com>
wrote:
| >"Alf P. Steinbach" <al***@start.no> wrote in message
| >news:3f****************@News.CIS.DFN.DE...
| >| The actual types are not needed at run-time, only the compatibility
| >| matrix of catches and throws.
| >|
| >| That abstract matrix can be optimized in umpteen ways.
| >|
| >| One way, but not the only way, is to use RTTI.
| >
| >Actually, the exact same thing can be said of dynamic_cast:
| >you only need a compatibility matrix of source and destination types.
|
| I see where the confusion stems from now.
|
| No, dynamic cast is a very different. With 'throw' the compiler knows
| the exact type of the argument.

Yes, just as when a new object is created (e.g. with the 'new' operator).

| With 'dynamic_cast' the argument can
| be a pointer to an object that according to the standard must have its
| dynamic type checked (a pointer to 'throw' is not checked for dyntype).

And when a catch clause is encountered during stack unwinding, the
dynamic type of the exception being thrown (and eventually re-thrown)
needs to be matched with the type of the catch clause.


At run-time there is no need for _type_ matching to determine the relevant
catch-clause, if any; only compatibility is relevant, and as mentioned the
compatibility matrix can be optimized and implemented in umpteen ways.

RTTI means "Run-Time Type Information", which isn't necessarily involved.

Jul 19 '05 #9

P: n/a
On Wed, 20 Aug 2003 14:50:01 GMT, al***@start.no (Alf P. Steinbach)
wrote:
And when a catch clause is encountered during stack unwinding, the
dynamic type of the exception being thrown (and eventually re-thrown)
needs to be matched with the type of the catch clause.
At run-time there is no need for _type_ matching to determine the relevant
catch-clause, if any; only compatibility


Do you mean type compatibility? Or what?

is relevant, and as mentioned thecompatibility matrix can be optimized and implemented in umpteen ways.
This is true for dynamic cast too - you only need to check the
compatibility of the source and destination types. In practice, may
dynamic_cast calls can be realized using a "compatibility matrix",
since the compiler can sometimes statically determine the type of the
object. Just as with exceptions, when it can *sometimes* statically
determine the call stack associated with a particular throw.
RTTI means "Run-Time Type Information", which isn't necessarily involved.


Some processing has to be done at runtime that involves types. What do
you call it?

Tom
Jul 19 '05 #10

P: n/a
On Wed, 20 Aug 2003 15:51:53 GMT, to********@hotmail.com (tom_usenet) wrote:
On Wed, 20 Aug 2003 14:50:01 GMT, al***@start.no (Alf P. Steinbach)
wrote:
And when a catch clause is encountered during stack unwinding, the
dynamic type of the exception being thrown (and eventually re-thrown)
needs to be matched with the type of the catch clause.
At run-time there is no need for _type_ matching to determine the relevant
catch-clause, if any; only compatibility


Do you mean type compatibility? Or what?


That was further up the tread. From the programmer's point of view
it is type compatibility. But wrt. to what happens at run-time it
is throw/catch statement compatibility; no types _need_ to be
examined or compared at run-time.

is relevant, and as mentioned the
compatibility matrix can be optimized and implemented in umpteen ways.
This is true for dynamic cast too - you only need to check the
compatibility of the source and destination types.


That disregards when (compile time, run time) the check wrt. type
needs to be done, which is the question debated.

In practice, may
dynamic_cast calls can be realized using a "compatibility matrix",
since the compiler can sometimes statically determine the type of the
object. Just as with exceptions, when it can *sometimes* statically
determine the call stack associated with a particular throw.
RTTI means "Run-Time Type Information", which isn't necessarily involved.
Some processing has to be done at runtime that involves types.


Nope. Unless you mean that information is used that the compiler derived
from types. Everything in the compiled program is in some way derived
from or associated with types, so that is a meaningless argument.

What do you call it?


Exception handling?

Jul 19 '05 #11

P: n/a
"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f****************@News.CIS.DFN.DE...
On Wed, 20 Aug 2003 16:30:22 +0200, "Ivan Vecerina" <iv**@myrealbox.com> wrote:
....
| With 'dynamic_cast' the argument can
| be a pointer to an object that according to the standard must have its
| dynamic type checked (a pointer to 'throw' is not checked for dyntype).

And when a catch clause is encountered during stack unwinding, the
dynamic type of the exception being thrown (and eventually re-thrown)
needs to be matched with the type of the catch clause.


At run-time there is no need for _type_ matching to determine the relevant
catch-clause, if any; only compatibility is relevant, and as mentioned the
compatibility matrix can be optimized and implemented in umpteen ways.


Can you clarify the fundamental difference you see between the type
compatibility tests performed by calls to dynamic_cast, and the type
compatibility tests required by EH to find catch handlers ?
RTTI means "Run-Time Type Information", which isn't necessarily involved.


Given separate compilation and dynamically linked library, can you
explain how an exception thrown by one library can be matched with
a catch handler in another library without performing a run-time
test based on some type of type identifier ?

Do you know of a compiler where dynamic_cast and EH do not share a
common infrastructure for checking the compatibility of types ?

Have you heard that RTTI had been adopted by the C++ committee in
spite of Stroustrup's reservations (leads to bad coding style...),
and that one of the strong arguments in favor of RTTI's adoption
was that the underlying mechanisms where required by EH anyway ?
Sincerely,
Ivan
--
http://www.post1.com/~ivec
Jul 19 '05 #12

P: n/a
"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f**************@News.CIS.DFN.DE...
On Thu, 21 Aug 2003 00:58:45 +0200, "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
Can you clarify the fundamental difference you see between the type
compatibility tests performed by calls to dynamic_cast, and the type
compatibility tests required by EH to find catch handlers ?


I thought I did: the former can only be performed at run-time, hence
"Run Time Type Information", because no compiler can even _in principle_
predict the dynamic type of *p in the general case. The latter,

compatibility between throw statements and catch statements, can in principle be computed at compile time as a huge matrix. The huge matrix is not very practical so various optimizations are used, including RTTI, but that does not make
RTTI _required_; it's just one option among many.
But again: if you assume global program analysis, dynamic_cast may also
rely on a compatibility matrix between the locations were object instances
are created, and the calls to dynamic_cast. A huge matrix which may also
be 'optimized' in various ways.
The mechanism is still the same: some source type needs to be checked
for compatibility with some destination type, and a pointer offset has
to be applied.
The only difference I see is that, for dynamic_cast, the object's type
is typically stored with the object (e.g. in the vtbl). For EH, the
thrown type needs to be stored somewhere so that it can be matched
during stack-unwinding (to be accessible to catch()-handling code).
Or reciprocally, try-catch() blocks that are on the call stack need
to somehow be identified at run-time -- as you can't always know at
compile time where a throwing function has been called from.
RTTI means "Run-Time Type Information", which isn't necessarily
involved.
Given separate compilation and dynamically linked library, can you
explain how an exception thrown by one library can be matched with
a catch handler in another library without performing a run-time
test based on some type of type identifier ?


No. Dynamically linked libraries are not part of C++. In a C++
implementation that supports dynamically linked libraries the most
natural way would be to use some form of RTTI, but I fail to see
any proof that RTTI is required in this case (with some more constraints
imposed, e.g. current linker technology, such a proof may be possible).


The reality of C/C++ today is separate compilation and limited
support for whole program optimization. But I agree that the standard
says very little about separate compilation.
Maybe in the informative annex about C compatibility (C1.6/2):
"When comparing types in different compilation units, C++ relies on
name equivalence when C relies on structural equivalence."
Have you heard that RTTI had been adopted by the C++ committee in
spite of Stroustrup's reservations (leads to bad coding style...), ....and that one of the strong arguments in favor of RTTI's adoption
was that the underlying mechanisms where required by EH anyway ?

.... Do you have any references for that rumour?


I have no concrete information about what these 'reservations' were.
But I remember reading about the common underlying mechanism in
several instances.
What a quick google search brings:

Bruce Eckel's Thinking in C++, 2nd ed., Volume 2, Revision 2:
About RTTI:
"When exception handling was added to C++, it required the exact type
information about objects. It became an easy next step to build access
to that information into the language."
http://nicolas.blancpain.free.fr/Doc...Chapter08.html

Some random web doc:
"Why might RTTI be useful?
Input of objects (what kind is it?), OODBs, debugging
Despite Stroustrup's reservations, RTTI adopted by
ANSI/ISO committee (Borland 4.0)
Why is RTTI already implied by exception handling?
catch needs to discriminate types"
http://www.eecs.lehigh.edu/~glennb/oose/13exRTTI.doc

NB: BS actually proposed RTTI in the form of dynamic_cast:
"BS: Yes, I was the one who invented the dynamic_cast syntax to
parallel the syntax for explicitly qualified template function calls.
Together with Dmitry Lenkov from HP, I was the proposer of the
runtime type identification (RTTI) mechanisms.
RTTI is easily overused. However, ...."
http://www.research.att.com/~bs/omo_interview.html
Nothing that authoritative indeed. I don't have BS's D&E
or his other books here to look for a quote.
Maybe some committee member could help here...
Kind regards,
Ivan
--
http://www.post1.com/~ivec
Jul 19 '05 #13

P: n/a
On Thu, 21 Aug 2003 08:21:53 +0200, "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f**************@News.CIS.DFN.DE...
On Thu, 21 Aug 2003 00:58:45 +0200, "Ivan Vecerina"<ivecATmyrealboxDOTcom> wrote:
>Can you clarify the fundamental difference you see between the type
>compatibility tests performed by calls to dynamic_cast, and the type
>compatibility tests required by EH to find catch handlers ?


I thought I did: the former can only be performed at run-time, hence
"Run Time Type Information", because no compiler can even _in principle_
predict the dynamic type of *p in the general case. The latter,

compatibility
between throw statements and catch statements, can in principle be

computed
at compile time as a huge matrix. The huge matrix is not very practical

so
various optimizations are used, including RTTI, but that does not make
RTTI _required_; it's just one option among many.


But again: if you assume global program analysis, dynamic_cast may also
rely on a compatibility matrix between the locations were object instances
are created, and the calls to dynamic_cast.


That's pure nonsense. After an object is created pointers to it are passed
around in an unpredictable way, and it's the pointers you cast.

Now I just saw Tom Usenet's reply with an example of what could be
unpredictable _control flow_ -- which btw. is irrelevant to RTTI.

Perhaps you're confusing stack unwinding (where information about which
throw statement has been executed is directly available) with checking
the dynamic type of *p?

>Have you heard that RTTI had been adopted by the C++ committee in
>spite of Stroustrup's reservations (leads to bad coding style...),... >and that one of the strong arguments in favor of RTTI's adoption
>was that the underlying mechanisms where required by EH anyway ?

...
Do you have any references for that rumour?


I have no concrete information about what these 'reservations' were.
But I remember reading about the common underlying mechanism in
several instances.
What a quick google search brings:

Bruce Eckel's Thinking in C++, 2nd ed., Volume 2, Revision 2:
About RTTI:
"When exception handling was added to C++, it required the exact type
information about objects. It became an easy next step to build access
to that information into the language."
http://nicolas.blancpain.free.fr/Doc...Chapter08.html


Don't rely on such rumors for technical or accurate information.
Some random web doc:
And don't rely on random web documents for what you only need
logic to resolve.
Nothing that authoritative indeed.
And don't rely on authority as a substitute for logic.

I don't have BS's D&E
or his other books here to look for a quote.
Maybe some committee member could help here...


Uh, again, don't rely on authority as a substitute for logic.
Hth.,

- Alf

Jul 19 '05 #14

P: n/a
Risto Lankinen wrote:
Furthermore, exception handling uses compile-time types,
not run-time (e.g. dynamic) types. Try this example:

#include <iostream.h>

struct Base
{
virtual ~Base()
{
}
};

struct Derived : public Base
{
};

int main()
{
Base *p = new Derived;

try
{
throw *p;
}
catch( const Derived & )
{
cout << "Derived" << endl;
}
catch( const Base & )
{
cout << "Base" << endl;
}
catch( ... )
{
cout << "<unknown>" << endl;
}

delete p;

return 0;
}

This program prints "Base".


I guess that "throw *p;" actually creates a copy of the base class part
of the object (i.e. it slices it off) and throws that. That's why a
Base is caught instead of a Derived. Try this example instead:

#include <iostream>

using namespace std;

struct Base
{
virtual ~Base()
{
}
};

struct Derived : public Base
{
};

int main()
{
Derived d;

try
{
throw d;
}
catch( const Base & b)
{
cout << "reference to Base caught" << endl;
if (typeid(b) == typeid(Derived))
cout << "but the actual class is Derived" << endl;
}
catch( ... )
{
cout << "not a base" << endl;
}

return 0;
}

Jul 19 '05 #15

P: n/a
Ivan Vecerina wrote:
| RTTI isn't need for exception handling, neither would it be
| sufficient.

I did not claim it was sufficient.

But RTTI is needed to match catch handlers with exceptions.
Consider:

#include <vector>
#include <string>
#include <iostream>
#include <exception>
int main()
{
try {
std::vector<std::string> tooBig(1UL<<31,"just some string");
}
catch(std::exception& x) {
std::cerr << "Failure: "<<x.what()<<std::endl;
}
}

How would the C++ run-time handle a failure of this memory allocation
without RTTI?


I don't know. Maybe you should ask the gcc developers, since you can
disable RTTI and still use exceptions in g++.

Jul 19 '05 #16

P: n/a
On Thu, 21 Aug 2003 10:44:37 GMT, al***@start.no (Alf P. Steinbach)
wrote:
On Thu, 21 Aug 2003 09:34:53 GMT, to********@hotmail.com (tom_usenet) wrote:
On Wed, 20 Aug 2003 18:10:34 GMT, al***@start.no (Alf P. Steinbach)
wrote:
is relevant, and as mentioned the
>compatibility matrix can be optimized and implemented in umpteen ways.

This is true for dynamic cast too - you only need to check the
compatibility of the source and destination types.

That disregards when (compile time, run time) the check wrt. type
needs to be done, which is the question debated.
Exception checks cannot in general be made at compile time - this
seems to be the error you are making.

e.g.

struct A
{
virtual ~A(){}
};

struct B: A{};

void throwA()
{
throw A();
}

void throwB()
{
throw B();
}

#include <iostream>

int main()
{
int i;
std::cin >> i;
void (*fptr)() = i > 0? throwA: throwB;
try
{
fptr();
}
catch(B const&)
{
std::cout << "B\n";
}
catch(A const&)
{
std::cout << "A\n";
}
}

How do you suggest that the check be made at compile time in general,
with whole program analysis or otherwise?


It seems your thinking is _very_ confused here. Am I right in assuming
that the term 'check', as used above, includes stack unwinding?

Stack unwinding cannot be done at compile time; there is no stack at
that time.


I assumed you misunderstood this. Your posts seemed to imply that you
thought that the catch associated with each throw could be resolved at
compile time, given whole program analysis.

Stack unwinding has nothing to do with RTTI.


No, of course not.

Now, I think I have the source of our misunderstanding. You seem to
think that the fact that the compiler knows the type of an object at
the throw site is somehow different from the compiler knowing the type
when it calls a constructor to create an object.

The only difference is that for exceptions, you only have one active
exception at a time (well, per thread), whereas you can have any
number of active objects at a time. The nature of the checking
required to match that global exception type against a catch block
though is identical to the checking required in a dynamic cast.

So, it seems that all you are saying is that you don't need to embed
type information in your exception objects, and I don't think anyone
has disagreed with this.

Tom
Jul 19 '05 #17

P: n/a
On Thu, 21 Aug 2003 14:06:47 GMT, to********@hotmail.com (tom_usenet) wrote:
Stack unwinding cannot be done at compile time; there is no stack at
that time.
I assumed you misunderstood this. Your posts seemed to imply that you
thought that the catch associated with each throw could be resolved at
compile time, given whole program analysis.

Stack unwinding has nothing to do with RTTI.


No, of course not.

Now, I think I have the source of our misunderstanding. You seem to
think that the fact that the compiler knows the type of an object at
the throw site is somehow different from the compiler knowing the type
when it calls a constructor to create an object.


Could you translate that to English?

I fail to see any difference between statically knowing the type of
an object and statically knowing the type of an object.

Furthermore, I fail to see any connection to the question of whether
RTTI is necessary for exception handling.

The only difference is that for exceptions, you only have one active
exception at a time (well, per thread), whereas you can have any
number of active objects at a time.
Heya, "Tom Usenet", I used to think that you were a rational being,
perhaps someone well-known in the C++ community. But I can't make
head or tail of this statement. Since when did active objects become
part of standard C++ (yes, I do know there are extensions)?
The nature of the checking
required to match that global exception type against a catch block
though is identical to the checking required in a dynamic cast.
That's incorrect, because one can be done at compile time, the other
not.

N'th recap: for exception handling the only necessary information is
whether any given 'throw' is compatible with any given 'catch', and that
information can be deduced at compile time; abstractly it's a boolean
matrix indexed by 'throw'-statements and 'catch'-statements; a bit more
concretely it's a matrix of stubs indexed the same way.

To be even more clear (I strive, I strive), consider what must happen
when an exception is thrown. The run-time support must first of all
determine the dynamically innermost enclosing matching 'catch'. One
way to do that is to walk the stack frames and for each frame, check
whether that frame has a compatible and enclosing 'catch'. To do each
such check it can use RTTI. Alternatively, it can simply check a compile-
time generated table that does not involve types at all, just machine
code addresses for 'throw' and 'catch' statements; no RTTI.

Having found a handler (assuming one exists), the stack must be unwound,
calling destructors of local objects. This does not involve RTTI.

Then, the thrown object (or a copy of it) must be passed to the handler.

Again, this does not or need not involve RTTI.

For a dynamic cast source/destination compatibility can in general not
be established at compile time, even _in principle_, and so run-time
type information, RTTI, is required for that, different from exception
handling.
So, it seems that all you are saying is that you don't need to embed
type information in your exception objects, and I don't think anyone
has disagreed with this.


What I'm saying is that RTTI is not necessary for exception handling.

If that parses the same as the intended meaning of the above statement,
then we're in agreement.

If not, then what does that statement mean (in clear English)?

Jul 19 '05 #18

P: n/a
On Thu, 21 Aug 2003 16:19:41 GMT, al***@start.no (Alf P. Steinbach)
wrote:
So in your view the similarity of a possible implementation of one
aspect of RTTI, one the one hand, and the requirements of exception
handling, on the other, makes RTTI necessary for exception handling?

How?
A runtime lookup, best implemented on types, is required to implement
exception handling. This is also true of dynamic_cast.

I'm not saying that dynamic_cast is used to implement exception
handling, but that the implementation of both will no doubt use common
facilities, since matching a catch block is very similar to checking a
dynamic_cast. Do you agree?
I just have to say it, because it's so appropriate: since the doll is
so similar to the person, sticking needles into the doll will harm the
person. *Sticking needle into a Tom Usenet doll*. Uh, troll?
And you think I'm trolling!?
...
For a dynamic cast source/destination compatibility can in general not
be established at compile time, even _in principle_, and so run-time
type information, RTTI, is required for that, different from exception
handling.
But at compile time you cannot determine the destination catch of
every throw statement. What's the difference? You still need to do a
runtime lookup, in a matrix or otherwise.


Yeah, yeah, similarity: something happens at run-time in both cases,
hence, RTTI is necessary for exception handling.


Not just something, but something very similar happens in both cases.
I never said that RTTI is required to implement exception handling
(Ivan did at first, although he clarified that he wasn't referring to
the specific features of type_info and dynamic_cast), just that the
two involve very similar concepts, and can share a lot of
implementation.
...
I think we have a disagreement about what RTTI means.


Perhaps, if you're not just trolling.


No.

In my view, RTTI means "Run-Time Type Information":
No disagreement there.

having availableat run-time the following functionality:

- dynamic_cast
- std::typeinfo
And typeid.

How is dynamic_cast, in your view, necessary for exception handling?
Consider that we've already established that it's not necessary for
finding an exception handler.

Alternatively, how is std::typeinfo necessary for exception handling?

Alternatively, how is a mechanism that for all practical purposes make
this functionality trivial, _necessary_ for exception handling?


I was simply disagreeing with your earlier assertions that matching
throws with catches, and using dynamic_cast, are completely different
(something about compile time vs runtime that Ivan and I disagreed
with). They aren't - they are conceptually very similar, and
implementing the infrastructure for one should give you quite a lot of
the infrastructure required by the other.

Tom
Jul 19 '05 #19

P: n/a
"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f***************@News.CIS.DFN.DE...
On Thu, 21 Aug 2003 15:48:04 GMT, to********@hotmail.com (tom_usenet) wrote:
Right, I agree with that. But, fairly similarly, every constructor
call in a program can be matched with every dynamic_cast statement,
and a matrix produced. This matrix is indexed by constructor call
statements and dynamic_cast statements. Each object stores the
statement (code address) that created it (not necessarily inside the
object).


So in your view the similarity of a possible implementation of one
aspect of RTTI, one the one hand, and the requirements of exception
handling, on the other, makes RTTI necessary for exception handling?


dynamic_cast and type matching in EH both require that instances of
types that derive from each other can be identified.
As both of these very similar mechanisms require type identification
at run time, is it unreasonable to call them both "RTTI mechanisms" ?
How is dynamic_cast, in your view, necessary for exception handling?
Consider that we've already established that it's not necessary for
finding an exception handler.

Alternatively, how is std::typeinfo necessary for exception handling?


And how is std::typeinfo necessary for dynamic_cast ?

You seem to have your very own specific definition of what RTTI is.
Somehow it seems to include dynamic_cast, but excludes the
equivalent mechanism needed to support exception handling.

Since "RTTI" is not a term formally defined in the standard,
I think it is just pointless to keep arguing.
Regards,
--
http://www.post1.com/~ivec
Jul 19 '05 #20

P: n/a
"Rolf Magnus" <ra******@t-online.de> wrote in message
news:bi*************@news.t-online.com...
Ivan Vecerina wrote:
How would the C++ run-time handle a failure of this memory allocation
without RTTI?


I don't know. Maybe you should ask the gcc developers, since you can
disable RTTI and still use exceptions in g++.


From what I saw on google, there seems to have been some bugs with
EH when RTTI was disabled. And it's for the best if these were
fixed.

An implementation could also offer a compile mode where dynamic_cast
is supported, but not type_info.

But yes, it would be nice if a compiler writer/maintainer could tell
us if run-time type identification in EH and dynamic_cast share
some common code...
Regards,
--
http://www.post1.com/~ivec

Jul 19 '05 #21

P: n/a
On Thu, 21 Aug 2003 17:22:38 GMT, to********@hotmail.com (tom_usenet) wrote:
On Thu, 21 Aug 2003 16:19:41 GMT, al***@start.no (Alf P. Steinbach)
wrote:
So in your view the similarity of a possible implementation of one
aspect of RTTI, one the one hand, and the requirements of exception
handling, on the other, makes RTTI necessary for exception handling?

How?
A runtime lookup, best implemented on types


Pascal is "better" than Java. So there!
is required to implement exception handling. This is also true of
dynamic_cast.
Similarity again. Yada yada yada. Did you know, both the earthworm and
George W. are lifeforms, and even more surprising, both are (to the best
of my knowledge) based on an incredibly complex molecule called DNA?
I'm not saying that dynamic_cast is used to implement exception
handling, but that the implementation of both will no doubt use common
facilities, since matching a catch block is very similar to checking a
dynamic_cast. Do you agree?
Of course not, since it's illogical.

If you replace "will no doubt" with "can", and "is very similar to" with
"has some similarity with", then yes.
I just have to say it, because it's so appropriate: since the doll is
so similar to the person, sticking needles into the doll will harm the
person. *Sticking needle into a Tom Usenet doll*. Uh, troll?


And you think I'm trolling!?


Yep, I'm 99% sure now. ;-)
...
I was simply disagreeing with your earlier assertions that matching
throws with catches, and using dynamic_cast, are completely different
(something about compile time vs runtime that Ivan and I disagreed
with).
As we have established, they are very different.

Matching a throw with a catch involves a stack walk; using a dynamic_cast
does not. Checking whether a given throw is compatible with a given catch
can always be done at compile time. That is not the case for a dynamic_cast.
And so on and so forth. How can this be so difficult to grasp?

You'll have to quote the statement of mine which was sufficiently
unclear about that that it could be interpreted as something else.
They aren't - they are conceptually very similar
No. See immediately above, and the thread in general. However, checking
whether a given throw is compatible with a given catch is conceptually
somewhat similar to a dynamic_cast.

But again, similarity at an abstract level between a part of A and
a part of B does not make A necessary for B.
and
implementing the infrastructure for one should give you quite a lot of
the infrastructure required by the other.


No. It can, but won't necessarily. In particular, a simple throw/catch
compatibility table, computed from compile-time symbol table information,
is presumably of little or no use in implementing dynamic_cast.

Jul 19 '05 #22

P: n/a
On Thu, 21 Aug 2003 19:40:36 +0200, "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f***************@News.CIS.DFN.DE...
On Thu, 21 Aug 2003 15:48:04 GMT, to********@hotmail.com (tom_usenet)wrote:
>Right, I agree with that. But, fairly similarly, every constructor
>call in a program can be matched with every dynamic_cast statement,
>and a matrix produced. This matrix is indexed by constructor call
>statements and dynamic_cast statements. Each object stores the
>statement (code address) that created it (not necessarily inside the
>object).


So in your view the similarity of a possible implementation of one
aspect of RTTI, one the one hand, and the requirements of exception
handling, on the other, makes RTTI necessary for exception handling?


dynamic_cast and type matching in EH both require that instances of
types that derive from each other can be identified.


That's correct.

As both of these very similar mechanisms require type identification
at run time,
That's incorrect.

is it unreasonable to call them both "RTTI mechanisms" ?


Yes.

Jul 19 '05 #23

P: n/a

"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f***************@News.CIS.DFN.DE...
On Thu, 21 Aug 2003 19:40:36 +0200, "Ivan Vecerina"

<ivecATmyrealboxDOTcom> wrote:
....
As both of these very similar mechanisms require type identification
at run time,


That's incorrect.

....
is it unreasonable to call them both "RTTI mechanisms" ?


Yes.


Again, what seems to define type identification for you is
the use of a type identifier associated with an object instance;
using a type identifier associated with a catch block on
the call stack is not.

This is your own definition - feel free:
Since "RTTI" is not a term formally defined in the standard,
I think it is just pointless to keep arguing.

Jul 19 '05 #24

P: n/a
On Fri, 22 Aug 2003 06:42:35 +0200, "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

"Alf P. Steinbach" <al***@start.no> wrote in message
news:3f***************@News.CIS.DFN.DE...
On Thu, 21 Aug 2003 19:40:36 +0200, "Ivan Vecerina"<ivecATmyrealboxDOTcom> wrote:
...
>As both of these very similar mechanisms require type identification
>at run time,


That's incorrect.

...
> is it unreasonable to call them both "RTTI mechanisms" ?


Yes.


Again, what seems to define type identification for you is
the use of a type identifier associated with an object instance;
using a type identifier associated with a catch block on
the call stack is not.


Funny, we seem to have posted new replies at the same time...

See my other (new) reply here for what I hope is a clarification.

Of course, it may be that it will only muddle waters even more.
This is your own definition - feel free:
>Since "RTTI" is not a term formally defined in the standard,
>I think it is just pointless to keep arguing.


Wasn't that _your_ definition?

Jul 19 '05 #25

P: n/a
On Fri, 22 Aug 2003 05:35:17 GMT, al***@start.no (Alf P. Steinbach)
wrote:
is it unreasonable to call them both "RTTI mechanisms" ?
Yes.


The question is : what is the defining characteristic/s of RTTI?
Pure RTTI seems to be exactly equivalent to 'dynamic_downcast', like,
say, the Eiffel assignment attempt. But what about that is it that
makes it "Run Time" (which we've had such a hard time pinning down),
and what about that is it that makes it "Type Information" (ditto)?

That's a bit subtle, and I agree with Tom Usenet that that is probably
why we have not managed to agree.

As I see it:
"Run Time" --> Only _knowable_ at run time, i.e. potentially
changing over time for the same code snippet.

"Type Info" --> An _explicit representation_ of a type.
I think you all agree with the "Run Time" definition, and probably
associate "potentially changing" in the context of exception handling
with "changing catch statement" depending on how a 'throw' is reached.

The "Type Info" is a bit harder, but here's an example, namely the
'throw'/'catch' compatibility matrix revisited. This matrix is in its most
basic form indexed by 'throw' statements and 'catch' statements. But in
typical code the number of thrown types tends to be very small, a handful
or so, and likewise for the number of caught types. And so all rows
representing 'throw' statements of the same type can essentially be
collapsed into one common row, plus an external vector that maps 'throw'
statements to rows. And ditto for columns indexed by 'catch' statements.

In this optimization a single row that represents a set of 'throw'
statements of the same type is in effect an identification of that type
in the sense that there is a one-to-one mapping between the relevant
types and corresponding rows. But it is not an explicit representation,
for given the (index to) a row one cannot obtain any information about
the type except via additional otherwise unnecessary stored associations,
nor can the row be used for anything but 'catch'/'throw' compatibility
checking. And the row is not "only knowable at run-time"; it can be (and
must, in order to practically useful, be) constructed at compile time.

For columns the situation is more complex, for a column index is only
available when a stack frame with a containing 'catch' has been found.
So isn't this column index then both an explicit representation of a
type (the 'catch' 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).

In short, all that's necessary for C++ exception handling is _implicit_
type representation that cannot be used for any other purpose. And so
it's not surprising that C++ EH cannot emulate 'dynamic_cast'. Or that
the functionality of 'dynamic_cast', or basic RTTI, is not required.

The end result of this analysis-by-example is that the concept of RTTI
hinges crucially on _explicit_ type representation.


No, you've shown that exception handling *doesn't* hinge on explicit
type representation. This is also true of dynamic_cast. Here's a
rewrite of your example:

The "Type Info" is a bit harder, but here's an example, namely the
'constructor call'/'dynamic_cast' compatibility matrix revisited. This
matrix is in its most basic form indexed by 'constructor call'
statements and 'dynamic_cast' statements. In typical code the number
of created types tends to be quite large, but the number of types
dynamically casted to tends to be small. And so all rows representing
'constructor call' statements of the same type can essentially be
collapsed into one common row, plus an external vector that maps
'constructor call' statements to rows. And ditto for columns indexed
by 'dynamic_cast' statements.

In this optimization a single row that represents a set of
'constructor call' statements of the same type is in effect an
identification of that type in the sense that there is a one-to-one
mapping between the relevant types and corresponding rows. But it is
not an explicit representation, for given the (index to) a row one
cannot obtain any information about the type except via additional
otherwise unnecessary stored associations, nor can the row be used for
anything but 'dynamic_cast' compatibility checking.

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).

In short, all that's necessary for C++ dynamic_cast is _implicit_
type representation that cannot be used for any other purpose.
Some very thinking-circuit-activating books have been written about just that little
crucial but hard-to-pin-down difference. Hofstadter's "Gödel, Escher,
Bach" comes to mind, as well as Scott Fahlman's "NETL", not to mention
Wolfram's "A new kind of physics". It's no wonder that we find it hard
to agree on the dividing line...


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.

However, neither of these arguments change the fact that matching
catch blocks and performing dynamic_casts both conceptually involve
taking a type, and checking it to see whether it is derived from
another type, and performing this check at runtime.

If your position is simply that you choose not to call that RTTI, we
can agree to disagree.

Tom
Jul 19 '05 #26

P: n/a
Dynamic_cast can't be made to work that way.

Exception handling is different. What happens when an exception is
thrown? We know what row of the matrix we need (this information is
encoded in the 'throw', not in the exception object) and we know what
stack frame we are in. We move up a frame until we reach a stack frame
with a catch clause. That gives us a column of the matrix. If the throw
and catch match according to the matrix, we stop. Otherwise we carry on.

Try to use a matrix of object creations to dynamic_casts to emulate
dynamic cast in a similar way. What happens when a constructor is
invoked? What doesn't and couldn't happen is a systematic search for a
dynamic_cast. 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.

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.

Corrections are welcome.

Regards,
Buster

Jul 19 '05 #27

P: n/a
On Thu, 21 Aug 2003 17:51:55 GMT, al***@start.no (Alf P. Steinbach)
wrote:
As we have established, they are very different.

Matching a throw with a catch involves a stack walk; using a dynamic_cast
does not. Checking whether a given throw is compatible with a given catch
can always be done at compile time. That is not the case for a dynamic_cast.
You can check, at compile time, whether any particular call to an
object constructor is compatible with any particular dynamic_cast.
And so on and so forth. How can this be so difficult to grasp?
Because it is factually incorrect! (the bit about dynamic_cast, not
the bit about exceptions).

You'll have to quote the statement of mine which was sufficiently
unclear about that that it could be interpreted as something else.
To clarify, the statements that you have made that I disagree with:

"With 'dynamic_cast' the argument can be a pointer to an object that
according to the standard must have its dynamic type checked (a
pointer to 'throw' is not checked for dyntype)."

This is inconsistent. The "dynamic type" does not need to be looked up
to perform a dynamic_cast - only an index into a matrix needs to be
computed. According to your definition, this does not count as "having
its dynamic type checked".

Here's another quote (from me and then your response):

"What I mean is that there is no fundamental difference between the
runtime check required by dynamic_cast and the runtime check required
to select a catch block.

For dynamic cast the compiler could build up a matrix of every use of
a type in dynamic cast, and every creation of an object.

For exception handling, the compiler could build up a matrix of every
use of a type in a throw, and every use in a catch.

What's the difference?


The first is nonsense since the type of *p cannot be predicted in the
general case.
"

I disagree with this too.

Your assertion that the type of *p cannot be predicted at compile time
is true. But why do you think that leads to "the first is nonsense"?

My equivalent statement about your throw/catch matrix would be:
"The second is nonsense since the type caught cannot be predicted in
the general case."

But in fact, neither statement is nonsense.
They aren't - they are conceptually very similar


No. See immediately above, and the thread in general. However, checking
whether a given throw is compatible with a given catch is conceptually
somewhat similar to a dynamic_cast.

But again, similarity at an abstract level between a part of A and
a part of B does not make A necessary for B.


We're agreed there, but that was never what I was disagreeing with.
and
implementing the infrastructure for one should give you quite a lot of
the infrastructure required by the other.


No. It can, but won't necessarily. In particular, a simple throw/catch
compatibility table, computed from compile-time symbol table information,
is presumably of little or no use in implementing dynamic_cast.


On the contrary, the same matrix (with an extra column for each
dynamic_cast target type and an extra row for each created object
type) is fine for dynamic_cast compatibility checks too (ignoring
virtual inheritence for now).

Tom
Jul 19 '05 #28

P: n/a
On Fri, 22 Aug 2003 11:40:23 GMT, to********@hotmail.com (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".

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'.
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.
However, neither of these arguments change the fact that matching
catch blocks and performing dynamic_casts both conceptually involve
taking a type, and checking it to see whether it is derived from
another type, and performing this check at runtime.
In my considered opinion George W. requires earthworms, since they
are somewhat similar at the genetic level. Bright insight! Perhaps
he's going fishing?
If your position is simply that you choose not to call that RTTI, we
can agree to disagree.


That seems to be the case, yes.

Jul 19 '05 #29

P: n/a
On Fri, 22 Aug 2003 13:29:03 +0100, Buster Copley <bu****@none.com>
wrote:
Dynamic_cast can't be made to work that way.

Exception handling is different. What happens when an exception is
thrown? We know what row of the matrix we need (this information is
encoded in the 'throw', not in the exception object) and we know what
stack frame we are in. We move up a frame until we reach a stack frame
with a catch clause. That gives us a column of the matrix. If the throw
and catch match according to the matrix, we stop. Otherwise we carry on.
Right.

Try to use a matrix of object creations to dynamic_casts to emulate
dynamic cast in a similar way. What happens when a constructor is
invoked? What doesn't and couldn't happen is a systematic search for a
dynamic_cast.
Of course not. Two options - either the row number is placed inside
the object, or the address of the object is added to a map of object
address - to row number.

We know at the point of construction what row of thematrix 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.
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. 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. This is
because the matrix is just an implementation of type compatibility,
something that is central to both dynamic_cast and throw/catch
matching.

For an exception, you have to walk the stack to find the column index.
For a dynamic_cast you have to lookup the row index for the object in
question (either inside the object, or in an object address indexed
map). There are different operations, but they are both still runtime
operations (hence my disagreement with assertions about exceptions
being compile time, and dynamic_cast being runtime).

Tom
Jul 19 '05 #30

P: n/a
On Fri, 22 Aug 2003 13:02:53 GMT, al***@start.no (Alf P. Steinbach)
wrote:
On Fri, 22 Aug 2003 11:40:23 GMT, to********@hotmail.com (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
Jul 19 '05 #31

P: n/a
On Fri, 22 Aug 2003 14:26:00 GMT, to********@hotmail.com (tom_usenet) wrote:
On Fri, 22 Aug 2003 13:02:53 GMT, al***@start.no (Alf P. Steinbach)
wrote:
On Fri, 22 Aug 2003 11:40:23 GMT, to********@hotmail.com (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.

Jul 19 '05 #32

P: n/a
On Fri, 22 Aug 2003 14:07:54 GMT, al***@start.no (Alf P. Steinbach)
wrote:
On Fri, 22 Aug 2003 13:43:57 GMT, to********@hotmail.com (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
Jul 19 '05 #33

P: n/a
On Fri, 22 Aug 2003 15:14:10 GMT, to********@hotmail.com (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.

Jul 19 '05 #34

P: n/a
tom_usenet wrote in news:3f****************@news.easynet.co.uk:
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/
Jul 19 '05 #35

P: n/a

"Rob Williscroft" <rt*@freenet.REMOVE.co.uk> 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.

Jul 19 '05 #36

P: n/a
On Fri, 22 Aug 2003 15:42:40 GMT, to********@hotmail.com (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?

Jul 19 '05 #37

P: n/a
On Fri, 22 Aug 2003 15:55:03 GMT, al***@start.no (Alf P. Steinbach)
wrote:
On Fri, 22 Aug 2003 15:42:40 GMT, to********@hotmail.com (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
Jul 19 '05 #38

P: n/a
"Ron Natalie" <ro*@sensor.com> wrote in message
news:3f***********************@news.newshosting.co 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
Jul 19 '05 #39

P: n/a
On Fri, 22 Aug 2003 15:42:40 GMT, to********@hotmail.com (tom_usenet) wrote:
On Fri, 22 Aug 2003 14:55:33 GMT, al***@start.no (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.

Jul 19 '05 #40

P: n/a
Ron Natalie wrote in news:3f***********************@news.newshosting.co m:

"Rob Williscroft" <rt*@freenet.REMOVE.co.uk> 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.


Right, this seperates the idea of std::typeinfo as a static part
of RTTI and dynamic_cast<> and typeid( polymorhic_type ) as the
dynamic (runtime) part of RTTI.
Also what are the cases in which dynamic_cast<> doesn't need
a polymorhic type ?

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.


I've seen borlands non-standard __rtti keyword that does this on
a class by class basis, and also a compiler option (borland again)
that add's rtti to just about every thing. I've allway's assumed this
was non-standard i.e. not C++ (the compiler version 4.52 if memory
serves, so quite old now).


Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 19 '05 #41

P: n/a

"Rob Williscroft" <rt*@freenet.REMOVE.co.uk> wrote in message
Also what are the cases in which dynamic_cast<> doesn't need
a polymorhic type ?


If
the type casted to is the same (or more cv-qualified) as the operand, or
the operand is a null pointer, or
the casted to type is a pointer/reference to an unambiguous accessible
base class of the operand
the operand does not need to be a pointer or lvalvue of polymorphic type.

5.2.7 of the standard lists the above conversions and then at line 6 says
"Otherwise, v shall be a poitner to or an lvalue of a polymorphic type."

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.


I've seen borlands non-standard __rtti keyword that does this on
a class by class basis, and also a compiler option (borland again)
that add's rtti to just about every thing. I've allway's assumed this
was non-standard i.e. not C++ (the compiler version 4.52 if memory
serves, so quite old now).


It is a nonstandard option. The standard ties RTTI behavior to virtual
functions being present.

Jul 19 '05 #42

P: n/a

"tom_usenet" <to********@hotmail.com> wrote in message news:3f****************@news.easynet.co.uk...
,

Given that the "thing" is an exception in this case, this isn't a
limitation!
Huh? Any type can be thrown.


No it isn't! It is only required for the types that are actually used
in a dynamic cast, just as for exception handling, it is only required
for those types used in a catch.


RTTI is not required at all for exceptions to work. The exception object
is not polymorphic. It's copied on basis of it's static type and that static
type is matched against the catch blocks. The only thing that may happen
is one of the implicit conversions.
Jul 19 '05 #43

P: n/a

"tom_usenet" <to********@hotmail.com> wrote in message
news:3f****************@news.easynet.co.uk...

I still think catch blocks are a type of RTTI (along with
dynamic_cast, typeid, etc.), since they allow you to get information
about the type of an exception at runtime.


Like many have already said, this is an illusion. In a very similar
way to exceptions, the following program seemingly implements
"a type of RTTI":

void Catch( int ) { cout << "int caught!"; }
void Catch( char * ) { cout << "char * caught!"; }

template <typename T> void Throw( const T &r ) { Catch(r); }

int main()
{
rand()%2 ? Throw( 1 ) : Throw( "" );
}

However, all of the magic takes place at compile time (it really
takes place more typically at link time if we're splitting hairs, but
the point remains: exceptions are run-time-static by nature).

- Risto -

Jul 19 '05 #44

P: n/a
On Tue, 26 Aug 2003 09:24:05 GMT, "Risto Lankinen"
<rl******@hotmail.com> wrote:

"tom_usenet" <to********@hotmail.com> wrote in message
news:3f****************@news.easynet.co.uk...

I still think catch blocks are a type of RTTI (along with
dynamic_cast, typeid, etc.), since they allow you to get information
about the type of an exception at runtime.


Like many have already said, this is an illusion. In a very similar
way to exceptions, the following program seemingly implements
"a type of RTTI":

void Catch( int ) { cout << "int caught!"; }
void Catch( char * ) { cout << "char * caught!"; }

template <typename T> void Throw( const T &r ) { Catch(r); }

int main()
{
rand()%2 ? Throw( 1 ) : Throw( "" );
}

However, all of the magic takes place at compile time (it really
takes place more typically at link time if we're splitting hairs, but
the point remains: exceptions are run-time-static by nature).


Ahh, so your hair is run-time-static vs run-time-dynamic, although
your example is only about the compile-time concepts of templates and
overloading.

RTTI has neither the word dynamic nor the work static in it - it is
the runtime bit that is important, and also the "information" bit.
Exception handling requires runtime compatibility checking of thrown
types with caught types, and how you implement this doesn't change
what it is. dynamic_cast requires runtime compatibility checking of
object types with cast-to types. You can implement catch blocks in any
number of ways that don't involve direct type information. You can
implement dynamic_cast in any number of ways that don't involve type
information. So why isn't exception handling a type of RTTI?

The word "information" is Alf's point of contention, but my point was
that dynamic_cast doesn't require type information either - you just
need to match object creations with matrix rows. His entropy arguments
are irrelevent. He's trying to say that because there is only one
exception, there is no "information" associated with it. However, RTTI
certainly doesn't have a formal definition that uses any mathematical
definition of "information".

I suppose my point is really that RTTI should be reserved for
type_info and typeid, and that a new term should be invented for
dynamic_cast and exception handling, such as "Runtime type
compatibility checking", or RTCC, since neither of them involve
information about the type, only about the compatibility of types.

Tom
Jul 19 '05 #45

P: n/a
Hi!

"tom_usenet" <to********@hotmail.com> wrote in message
news:3f****************@news.easynet.co.uk...
RTTI has neither the word dynamic nor the work static in it - it is
the runtime bit that is important, and also the "information" bit.
Would you therefore call the _static_ selection of overloaded
functions...

void Catch( int );
void Catch( void * );

.... a type of RTTI? Why, or why not? If not, what would you
call it instead?
I suppose my point is really that RTTI should be reserved for
type_info and typeid, and that a new term should be invented for
dynamic_cast and exception handling, such as "Runtime type
compatibility checking", or RTCC, since neither of them involve
information about the type, only about the compatibility of types.


Like it has been explained, the implementation details of
dynamic_cast and exception handling do not necessarily
intersect. Attempting to define a descriptive term for what
does not exist is a futile exercise.

On the other hand, if the new term is to describe the union
(rather than intersection) of the two, then things like virtual
methods where the compiler selects a method at run-time
based on the actual type of a polymorphic reference or
pointer, and even overloaded methods where the compiler
selects a method _seemingly_ at run-time based on the
static type of its argument also fall in the domain of this
new term.

Cheers!

- Risto -

Jul 19 '05 #46

P: n/a

"tom_usenet" <to********@hotmail.com> wrote in message news:3f****************@news.easynet.co.uk...
The static type is known at the throw site, just as the static type of
an object is known at its creation site.

The point is that the static type isn't known at the catch site,
except through matching of catch blocks, which happens in a similar
way to resolution to dynamic_casts (via implicit conversions from
actual type to cast-to type).


No it does NOT work that way. There's no dynamic typing involved.
It uses the equivelent of calling typeinfo on a non-pointer/non-reference.
It's entirely static.
Jul 19 '05 #47

P: n/a
On Tue, 26 Aug 2003 08:57:04 GMT, to********@hotmail.com (tom_usenet) wrote:
I still think catch blocks are a type of RTTI (along with
dynamic_cast, typeid, etc.), since they allow you to get information
about the type of an exception at runtime.

This is different from saying that
1. Exception handling requires RTTI
2. Exception handling requires type_info
3. Exception handling requires dynamic_cast.

IMHO, all of the above are false.


I'd just like to clear up a little point. Long after we agreed that
RTTI involves storing some type descriptor in each object, I continued
to meet your arguments with (essentially) the simple assertion that
exception handling does not require RTTI. It didn't occur to me to say
right out that
Exception handling does not require storing a type descriptor in
each object.
since, after all, we'd agreed that that was was RTTI was, and you could
not be _that_ blind, could you?

Now, perhaps, can you see that at least the claim that exception handling
is a _form_ of RTTI is inconsistent with the above definition?

Perhaps even, when you think really Really REALLY hard about it (hold your
pants!), _if_ exception handling is a form of RTTI, then (a) all exception
handling involves RTTI, and so (b) exception handling is not possible to have
without also having RTTI, and so -- from (b) -- (c) exception handling
_requires_ RTTI, in contradiction with your stm that (2) is false?

Jul 19 '05 #48

P: n/a
On Tue, 26 Aug 2003 10:07:40 -0400, "Ron Natalie" <ro*@sensor.com>
wrote:

"tom_usenet" <to********@hotmail.com> wrote in message news:3f****************@news.easynet.co.uk...
The static type is known at the throw site, just as the static type of
an object is known at its creation site.

The point is that the static type isn't known at the catch site,
except through matching of catch blocks, which happens in a similar
way to resolution to dynamic_casts (via implicit conversions from
actual type to cast-to type).
No it does NOT work that way.


What way?
There's no dynamic typing involved.
The static type of an exception isn't known at the site at which it is
caught. It depends how you define "static" and "dynamic". If you
define "static type" as a type known by the compiler at compile time
at a particular line of code, then exception types are dynamic except
at the throw site. Normal object types are dynamic except at their
creation site.
It uses the equivelent of calling typeinfo on a non-pointer/non-reference.
It's entirely static.


Again, what do you mean by static? The static type of an exception is
only known at the throw statement.

The bit that dynamic_cast and catch have in common is the need to
determine whether type A (unknown at the point of the check at compile
time, in one case held in the object, in the other case held in the
stack frame?) is derived from type B (known at the point of the check
at compile time).

Tom
Jul 19 '05 #49

P: n/a

"tom_usenet" <to********@hotmail.com> wrote in message news:3f****************@news.easynet.co.uk...
The point is that the static type isn't known at the catch site,
except through matching of catch blocks, which happens in a similar
way to resolution to dynamic_casts (via implicit conversions from
actual type to cast-to type).
No it does NOT work that way.


What way?


By looking at the same stuff dynamic_cast (i.e., vtable).

It uses the equivelent of calling typeinfo on a non-pointer/non-reference.
It's entirely static.
Again, what do you mean by static? The static type of an exception is
only known at the throw statement.


By static, I mean that there is no reason that the object needs to be tagged
with some type information so that the object type can be detected when you
only have a pointer or reference to a possible base class..
The bit that dynamic_cast and catch have in common is the need to
determine whether type A (unknown at the point of the check at compile
time, in one case held in the object, in the other case held in the
stack frame?) is derived from type B (known at the point of the check
at compile time).


Nope. Dynamic cast needs additional help because it has no clue what
the object that the pointer/reference actually is (only that it knows what a
permissable base class is). It needs to inspect the object to determine
what the t ype really is.

Throwing execptions is different. At compile time essentially the throw code
only has to remember the static type (you can't throw polymorphically) of the
experssion thrown. This is then checked at runtime against the various
catch blocks as it's unwinding the stack. However the value actually thrown
is immaterial, the exception handling code doesn't EVER need to look at it
until it has already found the catch block and needs it to initalize the local
variable there.
Jul 19 '05 #50

54 Replies

This discussion thread is closed

Replies have been disabled for this discussion.