Topic: typeid and extending RTTI
Author: mpr@absoft.com (Michael Rice)
Date: 1996/06/05 Raw View
>>>>> Jason Merrill <jason@cygnus.com> writes:
>> I assume since type_info was made a polymorphic type, someone is
>> supposed to use it as a base class. Can I assume the implementation
>> is allowed to do this?
>Yes. How else could they be used for dynamic_cast, without burdening
>typeid(int) with a lot of unnecessary fields?
Where in the draft does it say be can use type_info or typeid in
implementing dynamic_cast anyway? I realize they are certainly
very closely related and certainly could (probably should) be used
to implement dynamic_cast, but the draft doesn't make this easy...
Even if by some stroke of luck the draft was changed (see previous
post on this) to outlaw any use of typeid without including <typeinfo>
first, we'd still be stuck with a dynamic_cast problem. Since the
draft doesn't state <typeinfo> needs to be included for dynamic_casts
we'd have to still come up with a implementation hack to cover this.
So from the previous discussion we are left with the following:
Implementation defines a type much like the type_info class described
in the draft (call it __type_info). Implementation defines as
many derived classes as it needs to implement the typeid operator and/or
dynamic_cast. Internally when it comes across a dynamic_cast it can
use the __type_info type even if <typeinfo> is not included. Now for
the fun part: If it comes across a typeid operator and type_info is
defined (since <typeinfo> was included) everything is fine. If not
it must determine if the use of typeid is trivial. If it is not
trivial we get an error message, if it is trivial we generate something
called a "lvalue that has the incompletely-defined class type const
std::type_info." What exactly this is I am not sure, but maybe it
is an uninitialized __type_info object.
The actual header file <typeinfo> would then include just:
typedef __type_info type_info;
This is what I consider an ugly implementation hack. For one thing, the
actual definition of type_info cannot be in the <typeinfo> header.
The definition of __type_info or any of the related derived classes
cannot be in the <typeinfo> header either, as they would be
redefined if the user actually included the header.
On the other hand, let's pretend that the use of dynamic_cast and typeid
required the inclusion of <typeinfo>. Now the exact class definition
can be in the header file. The derived classes can be in the header
file. No hacks are needed in the implementation (that I can think of
off hand), no incompletely-defined class objects need to be created,
etc.
The committee must have a different idea of how this should be implemented,
but I am not exactly sure what that idea is.
>> Can I also assume the user may want to use it as a base class? (See the
>> C++ Report July/August 93 p. 51 for a discussion, but I have no idea if
>> this is still accurate...)
>Can you summarize? I can't imagine why the user would want to derive from
>type_info.
I quote from the above mentioned article:
Users could also decide to extend the RTTI provided by an implementation.
This could be done by providing a table that would associate the
user-provided RTTI with the standard information provided by the
implementation. This could be done as follows:
class user_RTTI;
void func(C* p) {
user_RTTI *pu = user_RTTI_table[typeid(*p)];
// user 'pu' to access user specific RTTI
}
End quote.
This doesn't do any deriving from type_info, and I agree I can't see
any reason to do so. I was just wondering if this is allowed or
disallowed by the current draft.
I'd also be interested to know what the above example is trying to
do. If anyone could come up with a useful example that would
compile, I'd be interested...
>> How should we interpret 5.2.7p1?
>The type of the expression is type_info; the type of the object it refers
>to may be type_info or a derived type.
>
>Consider typeid(Derived) as being converted into a call to a function like
>
>const type_info &
>__Derived_typeid (magic *base_info)
>{
> static extra_type_info foo (base_info);
> return foo;
>}
>
>This is pretty close to how g++ 2.8 will work.
Will it still be required to include <typeinfo> before using a
dynamic_cast? Does the draft allow this?
--
Mike Rice (mpr@absoft.com)
Absoft Corporation
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: jason@cygnus.com (Jason Merrill)
Date: 1996/06/06 Raw View
>>>>> Michael Rice <mpr@absoft.com> writes:
> Even if by some stroke of luck the draft was changed (see previous
> post on this) to outlaw any use of typeid without including <typeinfo>
> first, we'd still be stuck with a dynamic_cast problem. Since the
> draft doesn't state <typeinfo> needs to be included for dynamic_casts
> we'd have to still come up with a implementation hack to cover this.
Not really. I expect everyone will implement dynamic_cast by a call to a
magic library function; all you have to do at the point of use is pass
the result of typeid() to __dynamic_cast; you don't need to know anything
about type_info to do that.
> So from the previous discussion we are left with the following:
> Implementation defines a type much like the type_info class described
> in the draft (call it __type_info).
> The actual header file <typeinfo> would then include just:
> typedef __type_info type_info;
> This is what I consider an ugly implementation hack.
This won't work, because then writing
struct std::type_info *p;
would be ill formed; typedefs cannot be used with 'struct'. Apparently
what an implementation must do is to define an internal type with no name
(or with a name, but invisible to lookup) such that typeid() returns it,
and magically give that type the name 'type_info' when <typeinfo> is
included, perhaps with a '#pragma type_info'. Now, that's an ugly
implementation hack.
Actually, it occurs to me that the wording in the draft,
6 If the header <typeinfo> (_lib.type.info_) is not included prior to a
use of typeid, the result of a typeid expression is an lvalue that has
the incompletely-defined class type const std::type_info, and a pro-
gram that explicitly names this class type before inclusion of the
header is ill-formed.
allows another implementation: Predeclare std::type_info and set some sort
of 'booby-trapped' flag on it until <typeinfo> is #included. I'd rather
just do without the latter requirement.
> For one thing, the actual definition of type_info cannot be in the
> <typeinfo> header.
Sure it can. It only needs to be *declared* implicitly by the compiler.
The only reason the compiler needs to know anything about type_info is so
that it knows the type of typeid expressions, and the only thing it needs
to know is that such a type exists; everything else can be handled in the
library (including <typeinfo>).
>>> Can I also assume the user may want to use it as a base class? (See the
>>> C++ Report July/August 93 p. 51 for a discussion, but I have no idea if
>>> this is still accurate...)
>> Can you summarize? I can't imagine why the user would want to derive from
>> type_info.
> I quote from the above mentioned article:
> Users could also decide to extend the RTTI provided by an implementation.
> This could be done by providing a table that would associate the
> user-provided RTTI with the standard information provided by the
> implementation. This could be done as follows:
> class user_RTTI;
> void func(C* p) {
> user_RTTI *pu = user_RTTI_table[typeid(*p)];
> // user 'pu' to access user specific RTTI
> }
> End quote.
> This doesn't do any deriving from type_info, and I agree I can't see
> any reason to do so. I was just wondering if this is allowed or
> disallowed by the current draft.
It's not explicitly disallowed, so it's allowed (but useless).
> I'd also be interested to know what the above example is trying to
> do.
Provide additional RTTI info that the compiler doesn't provide. Things
like a canonical name (since type_info::name() is implementation-defined),
or persistence-handling functions, or whatever.
>> This is pretty close to how g++ 2.8 will work.
> Will it still be required to include <typeinfo> before using a
> dynamic_cast?
No.
> Does the draft allow this?
No.
Jason
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1996/06/06 Raw View
In article 1lg@absoft.absoft.com, mpr@absoft.com (Michael Rice) writes:
> Where in the draft does it say be can use type_info or typeid in
> implementing dynamic_cast anyway? I realize they are certainly
> very closely related and certainly could (probably should) be used
> to implement dynamic_cast, but the draft doesn't make this easy...
>
> Even if by some stroke of luck the draft was changed (see previous
> post on this) to outlaw any use of typeid without including <typeinfo>
> first, we'd still be stuck with a dynamic_cast problem. Since the
> draft doesn't state <typeinfo> needs to be included for dynamic_casts
> we'd have to still come up with a implementation hack to cover this.
I hope you aren't confusing the description of a valid C++ program with
what an implementor is allowed to use under the hood ("bonnet", for Brits).
A C++ program that tries to use type_info without including <typeinfo> is
ill-formed. The implementation may do any illegal thing it wants, and
typically must do illegal things. The implementor knows the implementation
details and might choose to use typeid and type_info invisibly to
implement dynamic_cast. Or underlying information might be used to implement
both typeid and dynamic_cast. As long as the implementation satisfies the
requirements of the language definition, it doesn't matter how it does so.
After all, the implementation doesn't even need to be written in C++, let
alone adhere internally to strict C++ rules.
> On the other hand, let's pretend that the use of dynamic_cast and typeid
> required the inclusion of <typeinfo>. Now the exact class definition
> can be in the header file.
I agree that would be nicer for users, since they could see what the class
looked like. I see no advantage in the current draft wording, which does
not require <typeinfo> before invoking typeid. I don't think the number
of useful programs would be reduced by requiring <typeinfo>.
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Michael Rice" <mpr@absoft.com>
Date: 1996/05/31 Raw View
Keeping this in mind:
Section 5.2.7 para 1 of the 26 January 1996 Draft states:
The result of a typeid expression is an lvalue of type
const std::type_info (18.5.1).
I now turn to extending type_info.
I assume since type_info was made a polymorphic type, someone is
supposed to use it as a base class. Can I assume the implementation
is allowed to do this? Can I also assume the user may want to use
it as a base class? (See the C++ Report July/August 93 p. 51 for a
discussion, but I have no idea if this is still accurate...)
Let's say the implementation decides to extend the type_info class.
In the typeinfo header we have the following (using gcc-like model):
class type_info {
public:
...
virtual const char* __get_name() const { return 0; }
const char* name() const ( return __get_name(); }
};
class extra_type_info : public type_info {
public:
const char* _name;
..
const char* __get_name() const { return _name; }
// inherit name()
};
Where extra_type_info contains extra data for polymorhic classes.
Now the user has something like this:
#include <typeinfo>
class Base {
public:
virtual void f();
};
class Derived : public Base {
public:
};
void foo(Base* b)
{
cout << typeid(*b).name() << endl; // could be "Base" or "Derived"?
}
The idea here is typeid(*b) returns a const std::type_info that has
a dynamic type of extra_type_info.
Does 5.2.7p1 allow this or does the dynamic type have to be
const std::type_info? Should it say that it "is a lvalue of
type const std::type_info or a type derived from const std::type_info" ?
In other words can this expression evaluate false?
typeid(type_info) == typeid(typeid(void *))
How should we interpret 5.2.7p1?
--
Mike Rice (mpr@absoft.com)
Absoft Corporation
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: jason@cygnus.com (Jason Merrill)
Date: 1996/05/31 Raw View
>>>>> Michael Rice <mpr@absoft.com> writes:
> I assume since type_info was made a polymorphic type, someone is
> supposed to use it as a base class. Can I assume the implementation
> is allowed to do this?
Yes. How else could they be used for dynamic_cast, without burdening
typeid(int) with a lot of unnecessary fields?
> Can I also assume the user may want to use it as a base class? (See the
> C++ Report July/August 93 p. 51 for a discussion, but I have no idea if
> this is still accurate...)
Can you summarize? I can't imagine why the user would want to derive from
type_info.
> The idea here is typeid(*b) returns a const std::type_info that has
> a dynamic type of extra_type_info.
> Does 5.2.7p1 allow this or does the dynamic type have to be
> const std::type_info? Should it say that it "is a lvalue of
> type const std::type_info or a type derived from const std::type_info" ?
> In other words can this expression evaluate false?
> typeid(type_info) == typeid(typeid(void *))
Yes.
> How should we interpret 5.2.7p1?
The type of the expression is type_info; the type of the object it refers
to may be type_info or a derived type.
Consider typeid(Derived) as being converted into a call to a function like
const type_info &
__Derived_typeid (magic *base_info)
{
static extra_type_info foo (base_info);
return foo;
}
This is pretty close to how g++ 2.8 will work.
Jason
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]