Topic: comparing type_info ?
Author: Esa Pulkkinen <esap@cs.tut.fi>
Date: 1998/08/31 Raw View
"Paul D. DeRocco" <pderocco@ix.netcom.com> writes:
> True. I really meant to say that the ability to know at run-time what
> classes are derived from what, based on some sort of internal symbol,
> exists. If this symbol isn't a type_info itself, it would obviously be
> easy to link it and the corresponding type_info together, so that this
> functionality could be applied by the user to type_info objects.
I think it's almost possible to build this information using the
existing C++ facilities. I'll outline one approach to implementing it.
You can determine at compile-time whether a particular class is
(publicly) derived from another - I think this could be used to
construct the extended type information needed. Here's the way to check
for derivation (actually, this checks which of T* and void* is a better
match given U* ; I think this is close enough):
// WARNING: Untested code follows:
template <class T,class U>
struct DerivationTraits {
struct Impl {
typedef char ary_1[1]; // sizeof of the array is 1
typedef char ary_2[2]; // sizeof of the array is 2
static ary_1 *f(T *) { static ary_1 x; return &x; }
static ary_2 *f(void*) { static ary_2 x; return &x; }
};
// The following is the magic - using the return type to determine
// which function was selected by the overload resolution:
// This *does* work for egcs, and EDG-based compilers.
// IMO it's also allowed by the std.
enum { UDerivedFromT = (sizeof(*Impl::f( (U*)0 )) == 1) };
};
Now you just need to use a map or some such to map pairs of type_info
objects into DerivationTraits<T,U>::UDerivedFromT. An approach is:
struct RegistrationInterface { virtual bool Query(type_info*) const =0; };
template <class T> struct RegisteredInfo : public RegistrationInterface
{
static map<type_info*,bool> info;
static void Register(type_info *, bool x);
bool Query(type_info *x) const throw (bad_cast);
};
map<type_info*, RegistrationInterface*> singletonTypeMap;
template <class T,class U>
struct RegisterInfo
{
RegisterInfo()
{ RegisteredInfo<T>::Register(&typeid(U),
DerivationTraits<T,U>::UDerivedFromT);
RegisteredInfo<U>::Register(&typeid(T),
DerivationTraits<U,T>::UDerivedFromT):
// Also handle registration of T and U into 'singletonTypeMap' here.
}
};
This will provide means to look up the type of the first object using
the first type_info pointer from 'singletonTypeMap', then that object
can handle the second type_info pointer by looking up from its
map<>:
bool IsDerivedFrom(const type_info &a,const type_info &b)
throw(bad_cast)
{
RegisterationInterface *ri = singletonTypeMap[&a];
if (!ri) throw bad_cast;
return ri->Query(&b);
}
The only problem that remains is registering all pairs of types that are
queried. This can be left for the user (The user just needs to insert
'RegisterInfo<T,U> tmp;' for each pair of types he uses - or he'll just
get an exception from the query). It's not that bad - you need to do
that with templates for current compilers anyway. Maybe a preprocessor
could be written to do this automatically. Of course, this registration
does generate a dependency to both T and U - which may (or then, maybe
not) be a problem. Another problem is that if the user does forget the
registration - then only testing can find the problem, because you only
get a run-time error if the lookup fails. This is also near the limit of
current compilers' capabilities, so I wouldn't much recommend its use on
portable code.
--
Esa Pulkkinen | C++ programmers do it virtually
E-Mail: esap@cs.tut.fi | everywhere with class, resulting
WWW : http://www.cs.tut.fi/~esap/ | in multiple inheritance.
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Alain Miniussi <miniussi@ilog.fr>
Date: 1998/09/02 Raw View
Esa Pulkkinen wrote:
>
> "Paul D. DeRocco" <pderocco@ix.netcom.com> writes:
> I think it's almost possible to build this information using the
> existing C++ facilities. I'll outline one approach to implementing it.
I know, I have already done that, I just have a problem with the
"almost" part.
> The only problem that remains is registering all pairs of types that are
> queried. This can be left for the user (The user just needs to insert
> 'RegisterInfo<T,U> tmp;' for each pair of types he uses - or he'll just
> get an exception from the query). It's not that bad -
I think it is, since the user has to build the whole derivation tree (and
"each pair" seems to be even worse). And it can be avoided as long as :
- you allow the comparaison engine to instanciate user types
(I can be a problem)
- you ask the user to register instances of concerned type instead of
the type itself (ie: the user must do engine::register(new T()); instead
of engine::register<T>())
You never need to provide both type to the registration engine, registration
looks like
engine::declare<T1>();
engine::declare<T2>();
engine::declare<T3>();
The engine establish the derivation relations,
and the user does not need to rebuild the derivation tree.
Without alowing the engine to work on instances, I can easily answer
to the question : "given an object, which types in the hierarchie
are a base class for that object", the problem is: I can't find
the best match (yes, it for a non intrusive multiple method dispatcher).
Now if I allow the engine to work on instances and
I can answer the first question, it's easy to have the partial order
the types, but I need and instance for each type, which a true limit
(if it's a hierarchy, it probably involve abstract classes, and there
some other problems). So the original question was "Since this inforamtion,
(A derive from B) is deduced at runtime with type_info object (I'm not
interested in knowing the value of dynamic_cast<T>(o), I just want to know
if it's null or not), why can't I get it without an instance (I think I
can get it, but in a so dirty way...)
> you need to do
> that with templates for current compilers anyway. Maybe a preprocessor
> could be written to do this automatically. Of course, this registration
> does generate a dependency to both T and U - which may (or then, maybe
> not) be a problem. Another problem is that if the user does forget the
> registration - then only testing can find the problem, because you only
> get a run-time error if the lookup fails. This is also near the limit of
> current compilers' capabilities, so I wouldn't much recommend its use on
> portable code.
I have an implementation that needs dynamic_cast and basic templates
(actualy, the hard part is to have "map" working with Sun CC. By the way,
RogueWaves claims that their standard lib is shiped with Sun CC, so why
is it not there ?). And if the user forget a registration, it's not that
bad, you only loose precision and you can emit a warning at run time.
Thanks,
Alain
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Alain Miniussi <miniussi@ilog.fr>
Date: 1998/08/24 Raw View
I have a question about comparison of type_info objects. It's
probably a FAQ, but since I can't find an answer in the FAQ.....
There are 3 way of comparing type_info objects: ==, != and .before
Then, given two type_info objects representing two polimorphic
classes, where is no way to tell if one class is a base class
for the other.
The strange point is that the information has to exist somewhere at
run time (in order to implement the dynamic cast) so it would
cost nothing to provide the functionnality.
In other word,
dynamic_cast<T*>(v);
doesn't really care about v, it only need typeid(v),
so why do I need v ?
Alain
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 1998/08/24 Raw View
Alain Miniussi wrote:
>
> I have a question about comparison of type_info objects. It's
> probably a FAQ, but since I can't find an answer in the FAQ.....
>
> There are 3 way of comparing type_info objects: ==, != and .before
> Then, given two type_info objects representing two polimorphic
> classes, where is no way to tell if one class is a base class
> for the other.
>
> The strange point is that the information has to exist somewhere at
> run time (in order to implement the dynamic cast) so it would
> cost nothing to provide the functionnality.
I'm not sure that you're right. The information needed to implement a
'bool type_info::IsDerivedFrom(const typeinfo&) const;' member function
is necessarily already stored, but probably in hidden static members of
of all polymorphic classes; not necessarily in a form that can easily be
retrieved through the corresponding type_info object.
> In other word,
> dynamic_cast<T*>(v);
> doesn't really care about v, it only need typeid(v),
> so why do I need v ?
The type of *v is sufficient information for dynamic_cast<T*> to decide
whether or not to return a null pointer. However, if it doesn't return a
null pointer, the actual value of 'v' determines what the actual return
value is.
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/08/25 Raw View
Alain Miniussi wrote:
>
> There are 3 way of comparing type_info objects: ==, != and .before
> Then, given two type_info objects representing two polimorphic
> classes, where is no way to tell if one class is a base class
> for the other.
>
> The strange point is that the information has to exist somewhere at
> run time (in order to implement the dynamic cast) so it would
> cost nothing to provide the functionnality.
>
> In other word,
> dynamic_cast<T*>(v);
> doesn't really care about v, it only need typeid(v),
> so why do I need v ?
As James Kuyper pointed out, dynamic_cast isn't just a test, it's a
cast, so it most certainly needs the value of v. In fact, for casting
from a second or later base class to a derived class (a common use), it
may return a different pointer, due to the offset of the base class
within the derived class.
That said, it is tempting to wish for some standard functions for
manipulating type_info objects intelligently. As you point out, the
functionality obviously exists internally. However, the functionality
internally is more complicated than you might think. For instance, if B
is a private base class of D, should your hypothetical function reveal
that D is derived from B, or should it hide this fact? The dynamic_cast
mechanism hides it by returning a null pointer in this case. Whether you
want this hidden with respect to type_info objects depends upon what
you're trying to accomplish, so there's no single test that will serve
all purposes.
By the way, the type_info::before function simply supplies some
arbitrary (and possibly meaningless) ordering on type_info objects,
purely so that they can be placed in collections (such as STL maps and
sets) that order the elements for fast retrieval.
--
Ciao,
Paul
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Barry Margolin <barmar@bbnplanet.com>
Date: 1998/08/25 Raw View
In article <35E215C8.BC7334A5@ix.netcom.com>,
Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
>That said, it is tempting to wish for some standard functions for
>manipulating type_info objects intelligently. As you point out, the
>functionality obviously exists internally.
Not necessarily. The standard specifies a way to go from an object to its
type_info, but doesn't require a way to go the other way. While the
implementation *could* maintain a table mapping type_info values to their
corresponding vtables (the index in the table could be used to implement
the ordering relationship), there's nothing requiring this.
--
Barry Margolin, barmar@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]