问题
There are many reasons not to use typeid
. Other than for using members of type_info
(implementation defined behavior), it is usually (always?) possible to provide similar functionality using other C++ language features, eg: overloading, virtual functions etc.
So, excluding usage that relies on the implementation defined behavior, does anybody have a real world example where typeid
is the best solution?
回答1:
boost::any
uses typeid
to implement any_cast
.
template<typename T> any_cast(const any& other) {
if(typeid(T) != other.type()) throw bad_any_cast();
//...actual cast here...
}
You can't be sure T
is polymorphic, so dynamic_cast
is out of the question, and the enclosed type within the boost::any
call is lost by now, so none of the other casts can provide any sort of type safety.
回答2:
So, excluding usage that relies on the implementation defined behavior, does anybody have a real world example where typeid is the best solution?
I sometimes use it in debug outputs, to verify that a template argument passed to my function is indeed of a given type. This makes sense in my case since the actual template argument passed to my function is generated by a specialised metafunction and I want to make sure that the right metafunction is used.
回答3:
When implementing multimethods (or multiple dispatch), where the actual call is chosen from e.g. a map, using std::type_info*
as a key.
回答4:
Write a dynamic tree where you can on the runtime modify structure of the tree where there are different types in each link, it'll need typeid. dynamic_cast is not enough.
Edit: Here's some details:
class I {
public:
virtual std::string type() const=0;
virtual void *value() const=0;
};
template<class T>
class Impl : public I
{
public:
Impl(T t) : t(t) { }
std::string type() const { return typeid(T).name(); }
void *value() const { return &t; }
private:
T t;
};
And then build a tree out of these:
template<class Node, class Link>
class Tree { };
With link type being the I* interface... Since the above works for any values of type T1,T2,T3,T4, we could also with similar classes for any functions T->T1, T->T2, T->T3, T->T4, and use that function type as the Node of the tree. Now you have proper expressions described in dynamic tree.
回答5:
You can use typeid
to compare the actual types of two objects. Could be useful if you want to check equality of two objects, and first make sure they are of the exact same type (though I must say I haven't seen this done a lot, so there might be a good reason why this is not a good idea...).
回答6:
I use it to probe the class type of the exception in my catch all handler.
// fudge vtable existence (thrown exceptions must have one)
class StubException
{
virtual ~StubException();
};
.....
catch(...)
{
StubException *e = getExceptionObject(); // compiler/rt specific
std::string s = typeid(e).name();
...
throw;
}
The function getExceptionObject()
is part of a small utility library I wrong to access additional information about exceptions. It comes in very handy when a function throws an exception I should be catch but don't. It has definitely saved a lot of frustration over the years since I immediately know the type of exception that needs coverage.
来源:https://stackoverflow.com/questions/6751061/when-is-using-typeid-the-best-solution